summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Athay <ko2fan@gmail.com>2009-02-11 09:30:26 +0000
committerDavid Athay <ko2fan@gmail.com>2009-02-11 09:30:26 +0000
commit91111ca5d13072ea3b834e23835df9c077329e39 (patch)
treef0af8dd08b766164835cf9b5412a9aa3267dbad7
parent8046bb2626b30fecdcea54eb0aa3349cdb7d277b (diff)
parent63ac001daa7dfc0735dfefd9c2829c8786b4edaf (diff)
downloadmana-client-91111ca5d13072ea3b834e23835df9c077329e39.tar.gz
mana-client-91111ca5d13072ea3b834e23835df9c077329e39.tar.bz2
mana-client-91111ca5d13072ea3b834e23835df9c077329e39.tar.xz
mana-client-91111ca5d13072ea3b834e23835df9c077329e39.zip
Merge branch 'master' of git@gitorious.org:tmw/eathena
-rw-r--r--.mailmap1
-rw-r--r--AUTHORS1
-rw-r--r--README52
-rw-r--r--data/CMakeLists.txt1
-rw-r--r--data/fonts/CMakeLists.txt2
-rw-r--r--data/fonts/Makefile.am7
-rw-r--r--data/fonts/dejavusans-bold.ttfbin0 -> 569880 bytes
-rw-r--r--data/fonts/dejavusans.ttfbin569716 -> 619108 bytes
-rw-r--r--data/graphics/gui/CMakeLists.txt11
-rw-r--r--data/graphics/gui/Makefile.am12
-rw-r--r--data/graphics/gui/default.pngbin0 -> 1395 bytes
-rw-r--r--data/graphics/gui/emotions.pngbin19386 -> 0 bytes
-rw-r--r--data/graphics/gui/fixedfont.pngbin1895 -> 0 bytes
-rw-r--r--data/graphics/gui/gui.xml18
-rw-r--r--data/graphics/gui/hits_blue.pngbin589 -> 884 bytes
-rw-r--r--data/graphics/gui/hits_red.pngbin561 -> 813 bytes
-rw-r--r--data/graphics/gui/hits_yellow.pngbin894 -> 907 bytes
-rw-r--r--data/graphics/gui/menuitemD.pngbin1329 -> 0 bytes
-rw-r--r--data/graphics/gui/menuitemF.pngbin1530 -> 0 bytes
-rw-r--r--data/graphics/gui/menuitemN.pngbin1310 -> 0 bytes
-rw-r--r--data/graphics/gui/menuitemP.pngbin1436 -> 0 bytes
-rw-r--r--data/graphics/gui/rpgfont_wider.pngbin4382 -> 0 bytes
-rw-r--r--data/graphics/gui/speech_bubble.pngbin0 -> 2031 bytes
-rw-r--r--data/graphics/gui/speechbubble.xml18
-rw-r--r--data/graphics/gui/thickborder.pngbin530 -> 0 bytes
-rw-r--r--data/help/commands.txt6
-rw-r--r--data/help/skills.txt2
-rw-r--r--docs/FAQ.txt19
-rw-r--r--docs/INSTALL/win32.txt4
-rw-r--r--docs/packages.txt32
-rw-r--r--packaging/windows/make-translations.vbs42
-rw-r--r--packaging/windows/setup.nsi26
-rw-r--r--po/POTFILES.in28
-rw-r--r--po/sv.po266
-rw-r--r--src/CMakeLists.txt52
-rw-r--r--src/Makefile.am68
-rw-r--r--src/animatedsprite.cpp1
-rw-r--r--src/animationparticle.cpp1
-rw-r--r--src/being.cpp268
-rw-r--r--src/being.h117
-rw-r--r--src/beingmanager.cpp21
-rw-r--r--src/beingmanager.h39
-rw-r--r--src/configlistener.h3
-rw-r--r--src/configuration.cpp8
-rw-r--r--src/configuration.h7
-rw-r--r--src/effectmanager.cpp104
-rw-r--r--src/effectmanager.h62
-rw-r--r--src/emoteshortcut.cpp77
-rw-r--r--src/emoteshortcut.h125
-rw-r--r--src/engine.cpp51
-rw-r--r--src/engine.h2
-rw-r--r--src/equipment.cpp7
-rw-r--r--src/floor_item.cpp17
-rw-r--r--src/floor_item.h36
-rw-r--r--src/flooritemmanager.cpp3
-rw-r--r--src/game.cpp460
-rw-r--r--src/game.h8
-rw-r--r--src/graphics.cpp22
-rw-r--r--src/graphics.h28
-rw-r--r--src/gui/browserbox.cpp116
-rw-r--r--src/gui/browserbox.h8
-rw-r--r--src/gui/buddywindow.cpp83
-rw-r--r--src/gui/button.cpp46
-rw-r--r--src/gui/button.h3
-rw-r--r--src/gui/buy.cpp5
-rw-r--r--src/gui/buy.h12
-rw-r--r--src/gui/buysell.cpp3
-rw-r--r--src/gui/char_select.cpp198
-rw-r--r--src/gui/char_select.h18
-rw-r--r--src/gui/char_server.cpp30
-rw-r--r--src/gui/char_server.h2
-rw-r--r--src/gui/chat.cpp533
-rw-r--r--src/gui/chat.h62
-rw-r--r--src/gui/chatinput.h4
-rw-r--r--src/gui/checkbox.cpp31
-rw-r--r--src/gui/checkbox.h6
-rw-r--r--src/gui/color.cpp146
-rw-r--r--src/gui/color.h136
-rw-r--r--src/gui/confirm_dialog.cpp59
-rw-r--r--src/gui/confirm_dialog.h12
-rw-r--r--src/gui/connection.cpp10
-rw-r--r--src/gui/debugwindow.cpp5
-rw-r--r--src/gui/debugwindow.h4
-rw-r--r--src/gui/emotecontainer.cpp172
-rw-r--r--src/gui/emotecontainer.h136
-rw-r--r--src/gui/emoteshortcutcontainer.cpp204
-rw-r--r--src/gui/emoteshortcutcontainer.h77
-rw-r--r--src/gui/emotewindow.cpp77
-rw-r--r--src/gui/emotewindow.h (renamed from src/gui/buddywindow.h)38
-rw-r--r--src/gui/equipmentwindow.cpp214
-rw-r--r--src/gui/equipmentwindow.h54
-rw-r--r--src/gui/focushandler.cpp3
-rw-r--r--src/gui/focushandler.h2
-rw-r--r--src/gui/gui.cpp52
-rw-r--r--src/gui/gui.h8
-rw-r--r--src/gui/help.cpp17
-rw-r--r--src/gui/help.h4
-rw-r--r--src/gui/inttextfield.cpp1
-rw-r--r--src/gui/inttextfield.h3
-rw-r--r--src/gui/inventorywindow.cpp222
-rw-r--r--src/gui/inventorywindow.h41
-rw-r--r--src/gui/item_amount.cpp6
-rw-r--r--src/gui/item_amount.h4
-rw-r--r--src/gui/itemcontainer.cpp79
-rw-r--r--src/gui/itemcontainer.h32
-rw-r--r--src/gui/itemlinkhandler.cpp63
-rw-r--r--src/gui/itemlinkhandler.h40
-rw-r--r--src/gui/itempopup.cpp216
-rw-r--r--src/gui/itempopup.h54
-rw-r--r--src/gui/itemshortcutcontainer.cpp157
-rw-r--r--src/gui/itemshortcutcontainer.h43
-rw-r--r--src/gui/listbox.cpp34
-rw-r--r--src/gui/listbox.h3
-rw-r--r--src/gui/login.cpp218
-rw-r--r--src/gui/login.h59
-rw-r--r--src/gui/menuwindow.cpp45
-rw-r--r--src/gui/menuwindow.h2
-rw-r--r--src/gui/minimap.cpp75
-rw-r--r--src/gui/minimap.h12
-rw-r--r--src/gui/ministatus.cpp26
-rw-r--r--src/gui/ministatus.h7
-rw-r--r--src/gui/npc_text.cpp68
-rw-r--r--src/gui/npc_text.h23
-rw-r--r--src/gui/npcintegerdialog.cpp28
-rw-r--r--src/gui/npcintegerdialog.h19
-rw-r--r--src/gui/npclistdialog.cpp48
-rw-r--r--src/gui/npclistdialog.h10
-rw-r--r--src/gui/npcstringdialog.cpp18
-rw-r--r--src/gui/npcstringdialog.h11
-rw-r--r--src/gui/ok_dialog.cpp58
-rw-r--r--src/gui/ok_dialog.h10
-rw-r--r--src/gui/passwordfield.cpp2
-rw-r--r--src/gui/passwordfield.h5
-rw-r--r--src/gui/playerbox.cpp24
-rw-r--r--src/gui/playerbox.h4
-rw-r--r--src/gui/popupmenu.cpp91
-rw-r--r--src/gui/popupmenu.h3
-rw-r--r--src/gui/progressbar.cpp38
-rw-r--r--src/gui/progressbar.h9
-rw-r--r--src/gui/radiobutton.cpp39
-rw-r--r--src/gui/radiobutton.h5
-rw-r--r--src/gui/recorder.cpp116
-rw-r--r--src/gui/recorder.h76
-rw-r--r--src/gui/register.cpp56
-rw-r--r--src/gui/register.h23
-rw-r--r--src/gui/scrollarea.cpp51
-rw-r--r--src/gui/scrollarea.h5
-rw-r--r--src/gui/sdlinput.cpp2
-rw-r--r--src/gui/sell.cpp10
-rw-r--r--src/gui/sell.h4
-rw-r--r--src/gui/setup.cpp26
-rw-r--r--src/gui/setup.h5
-rw-r--r--src/gui/setup_audio.cpp7
-rw-r--r--src/gui/setup_audio.h4
-rw-r--r--src/gui/setup_colors.cpp249
-rw-r--r--src/gui/setup_colors.h75
-rw-r--r--src/gui/setup_joystick.cpp15
-rw-r--r--src/gui/setup_joystick.h4
-rw-r--r--src/gui/setup_keyboard.cpp20
-rw-r--r--src/gui/setup_keyboard.h11
-rw-r--r--src/gui/setup_players.cpp35
-rw-r--r--src/gui/setup_players.h17
-rw-r--r--src/gui/setup_video.cpp149
-rw-r--r--src/gui/setup_video.h10
-rw-r--r--src/gui/shop.h4
-rw-r--r--src/gui/shoplistbox.cpp28
-rw-r--r--src/gui/shoplistbox.h5
-rw-r--r--src/gui/shortcutcontainer.cpp71
-rw-r--r--src/gui/shortcutcontainer.h107
-rw-r--r--src/gui/shortcutwindow.cpp (renamed from src/gui/itemshortcutwindow.cpp)31
-rw-r--r--src/gui/shortcutwindow.h (renamed from src/gui/itemshortcutwindow.h)20
-rw-r--r--src/gui/skill.cpp122
-rw-r--r--src/gui/skill.h8
-rw-r--r--src/gui/slider.cpp16
-rw-r--r--src/gui/slider.h2
-rw-r--r--src/gui/speechbubble.cpp95
-rw-r--r--src/gui/speechbubble.h48
-rw-r--r--src/gui/status.cpp241
-rw-r--r--src/gui/status.h11
-rw-r--r--src/gui/table.cpp264
-rw-r--r--src/gui/table.h57
-rw-r--r--src/gui/table_model.cpp24
-rw-r--r--src/gui/table_model.h6
-rw-r--r--src/gui/textbox.cpp60
-rw-r--r--src/gui/textbox.h13
-rw-r--r--src/gui/textfield.cpp60
-rw-r--r--src/gui/textfield.h42
-rw-r--r--src/gui/trade.cpp182
-rw-r--r--src/gui/trade.h2
-rw-r--r--src/gui/truetypefont.cpp7
-rw-r--r--src/gui/truetypefont.h1
-rw-r--r--src/gui/updatewindow.cpp64
-rw-r--r--src/gui/updatewindow.h3
-rw-r--r--src/gui/viewport.cpp234
-rw-r--r--src/gui/viewport.h81
-rw-r--r--src/gui/widgets/dropdown.cpp203
-rw-r--r--src/gui/widgets/dropdown.h99
-rw-r--r--src/gui/widgets/resizegrip.cpp20
-rw-r--r--src/gui/widgets/resizegrip.h3
-rw-r--r--src/gui/widgets/tab.cpp47
-rw-r--r--src/gui/widgets/tab.h8
-rw-r--r--src/gui/widgets/tabbedarea.cpp2
-rw-r--r--src/gui/window.cpp255
-rw-r--r--src/gui/window.h38
-rw-r--r--src/gui/windowcontainer.h3
-rw-r--r--src/guichanfwd.h3
-rw-r--r--src/imageparticle.cpp3
-rw-r--r--src/inventory.cpp70
-rw-r--r--src/inventory.h8
-rw-r--r--src/item.h36
-rw-r--r--src/itemshortcut.cpp20
-rw-r--r--src/itemshortcut.h2
-rw-r--r--src/joystick.cpp5
-rw-r--r--src/joystick.h8
-rw-r--r--src/keyboardconfig.cpp129
-rw-r--r--src/keyboardconfig.h49
-rw-r--r--src/localplayer.cpp253
-rw-r--r--src/localplayer.h76
-rw-r--r--src/log.cpp2
-rw-r--r--src/log.h1
-rw-r--r--src/main.cpp348
-rw-r--r--src/main.h4
-rw-r--r--src/map.cpp24
-rw-r--r--src/map.h28
-rw-r--r--src/monster.cpp71
-rw-r--r--src/monster.h5
-rw-r--r--src/net/beinghandler.cpp93
-rw-r--r--src/net/beinghandler.h2
-rw-r--r--src/net/buysellhandler.cpp17
-rw-r--r--src/net/charserverhandler.cpp79
-rw-r--r--src/net/chathandler.cpp8
-rw-r--r--src/net/equipmenthandler.cpp51
-rw-r--r--src/net/inventoryhandler.cpp136
-rw-r--r--src/net/itemhandler.cpp1
-rw-r--r--src/net/loginhandler.cpp60
-rw-r--r--src/net/loginhandler.h3
-rw-r--r--src/net/maploginhandler.cpp29
-rw-r--r--src/net/messagehandler.cpp3
-rw-r--r--src/net/messagein.cpp26
-rw-r--r--src/net/messagein.h22
-rw-r--r--src/net/messageout.cpp5
-rw-r--r--src/net/network.cpp22
-rw-r--r--src/net/network.h57
-rw-r--r--src/net/npchandler.cpp15
-rw-r--r--src/net/partyhandler.cpp122
-rw-r--r--src/net/partyhandler.h39
-rw-r--r--src/net/playerhandler.cpp92
-rw-r--r--src/net/protocol.h43
-rw-r--r--src/net/skillhandler.cpp3
-rw-r--r--src/net/tradehandler.cpp47
-rw-r--r--src/npc.cpp55
-rw-r--r--src/npc.h9
-rw-r--r--src/openglgraphics.cpp23
-rw-r--r--src/particle.cpp7
-rw-r--r--src/particle.h4
-rw-r--r--src/particlecontainer.cpp5
-rw-r--r--src/particlecontainer.h6
-rw-r--r--src/particleemitter.cpp45
-rw-r--r--src/particleemitter.h9
-rw-r--r--src/particleemitterprop.h1
-rw-r--r--src/party.cpp217
-rw-r--r--src/party.h76
-rw-r--r--src/player.cpp56
-rw-r--r--src/player.h20
-rw-r--r--src/player_relations.cpp71
-rw-r--r--src/player_relations.h10
-rw-r--r--src/properties.h2
-rw-r--r--src/resources/action.cpp2
-rw-r--r--src/resources/action.h6
-rw-r--r--src/resources/ambientoverlay.cpp1
-rw-r--r--src/resources/animation.cpp11
-rw-r--r--src/resources/animation.h18
-rw-r--r--src/resources/buddylist.cpp10
-rw-r--r--src/resources/buddylist.h5
-rw-r--r--src/resources/colordb.cpp122
-rw-r--r--src/resources/colordb.h52
-rw-r--r--src/resources/dye.cpp1
-rw-r--r--src/resources/dye.h5
-rw-r--r--src/resources/emotedb.cpp140
-rw-r--r--src/resources/emotedb.h60
-rw-r--r--src/resources/image.cpp46
-rw-r--r--src/resources/image.h9
-rw-r--r--src/resources/imageloader.cpp5
-rw-r--r--src/resources/imageset.cpp6
-rw-r--r--src/resources/imageset.h1
-rw-r--r--src/resources/imagewriter.cpp6
-rw-r--r--src/resources/imagewriter.h4
-rw-r--r--src/resources/itemdb.cpp56
-rw-r--r--src/resources/itemdb.h7
-rw-r--r--src/resources/iteminfo.cpp13
-rw-r--r--src/resources/iteminfo.h19
-rw-r--r--src/resources/mapreader.cpp38
-rw-r--r--src/resources/mapreader.h4
-rw-r--r--src/resources/monsterdb.cpp32
-rw-r--r--src/resources/monsterdb.h8
-rw-r--r--src/resources/monsterinfo.cpp6
-rw-r--r--src/resources/monsterinfo.h43
-rw-r--r--src/resources/music.cpp6
-rw-r--r--src/resources/music.h6
-rw-r--r--src/resources/npcdb.cpp14
-rw-r--r--src/resources/npcdb.h8
-rw-r--r--src/resources/resource.cpp7
-rw-r--r--src/resources/resource.h9
-rw-r--r--src/resources/resourcemanager.cpp21
-rw-r--r--src/resources/resourcemanager.h6
-rw-r--r--src/resources/soundeffect.cpp3
-rw-r--r--src/resources/soundeffect.h6
-rw-r--r--src/resources/spritedef.cpp7
-rw-r--r--src/resources/spritedef.h6
-rw-r--r--src/simpleanimation.cpp16
-rw-r--r--src/simpleanimation.h11
-rw-r--r--src/sound.cpp12
-rw-r--r--src/sound.h1
-rw-r--r--src/sprite.h12
-rw-r--r--src/statuseffect.cpp10
-rw-r--r--src/text.cpp27
-rw-r--r--src/text.h25
-rw-r--r--src/textmanager.cpp18
-rw-r--r--src/textmanager.h9
-rw-r--r--src/textparticle.cpp3
-rw-r--r--src/textparticle.h5
-rw-r--r--src/utils/base64.cpp2
-rw-r--r--src/utils/strprintf.cpp1
-rw-r--r--src/utils/tostring.h15
-rw-r--r--src/utils/xml.cpp2
-rw-r--r--tmw.cbp48
326 files changed, 10137 insertions, 3888 deletions
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 00000000..aae6396b
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1 @@
+Bjørn Lindeijer <bjorn@lindeijer.nl>
diff --git a/AUTHORS b/AUTHORS
index 14d09fbf..2dba1dee 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -25,6 +25,7 @@ Guillaume Melquiond (Silene) <guillaume.melquiond gmail.com>
Ira Rice <irarice gmail.com>
Jan-Fabian Humann (Mra) <malastare gmx.net>
José Ávila <linux javila.net>
+Joshua Langley <joshlangley optusnet.com.au>
Kiyoshi Kyokai <kiyoshi.kyokai gmail.com>
Lloyd Bryant <lloyd_bryant netzero.net>
Marcel W. Wysocki <maci satgnu.org>
diff --git a/README b/README
index 1af4d3a2..e4272c12 100644
--- a/README
+++ b/README
@@ -49,15 +49,15 @@ Use arrow keys to move around. Other keys:
- F8 toggle shortcut window
- F9 show setup window
- F10 toggle debug window
-- Alt + 0-9 show emotions
-- Alt + S sit down / stand up
+- Alt + 0-9 show emotions / usuable at skill level 2.
+- Alt + S sit down / stand up / usuable at skill level 3.
- Alt + F toggle debug pathfinding feature
- Alt + P take screenshot
+- Alt + T turns on anti-trade function / usuable at skill level 1.
- A target nearest monster
- H hide all non-sticky windows
- G or Z pick up item
- Enter focus chat window / send message
-- Shift hold it when attacking to lock target for auto attack
MOUSE:
@@ -65,6 +65,38 @@ Left click to execute default action: walk, pick up an item, attack a monster
and talk to NPCs (be sure to click on their feet). Right click to show up a
context menu. Holding [Left Shift] prevents from walking when attacking.
+/Commands:
+
+- /help Displays the list of commands
+- /announce broadcasts a global msg(Gm Cammand only)
+- /clear clears the chat window
+- /who shows how many players are online
+- /where displays the map name your currently on
+- /whisper send a private msg to another player
+ (format: /whisper <charname> <message>)
+ If the <nick> has spaces in it, enclose it in double
+ quotes e.g. /whisper "char name" <message>
+- /record Records the Chat output
+ (format: /record <filename to write to> starts the record
+ session /record again
+ stops the session)
+- /party <command> <params>: Party commands
+ - /party new creates a new party /party new <party name>
+ - /party create creates a new party /party create <party name>
+ - /party prefix This commands sets the party prefix character
+ /party prefix <prefix-char>
+ "/party prefix" reports the current party prefix
+ character
+ - /party leave This command causes the player to leave the party.
+Type /help party <option> for further help.
+- /present This command gets a list of players within hearing
+- /toggle make the chatlog lose focus on a blank line or after
+ message. (format: /toggle <option>, where option can be
+ '1', 'y' or 't' to make the chatlog lose focus on a
+ blank line, and '0', 'n' or 'f' to make the chatlog lose
+ focus after every message. /toggle displays the status)
+For more information, type /help <command>
+
3. Skills
---------
@@ -73,10 +105,16 @@ point to spend on skills.
BASIC SKILLS:
-Level 1: enables the ability to trade with others
-Level 2: enables the ability to express emotions
-Level 3: enables character to sit
-Other level not yet implemented.
+Level 1: enables the ability to trade with others
+Level 2: enables the ability to express emotions
+Level 3: enables character to sit
+Level 4: enables not used
+level 5: enables the ability to join a party
+level 6: enables not used
+level 7: enables the ability to create a party
+level 8: enables not used
+level 9: enables not used
+level 10: enables not used
4. Support
----------
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt
index d5e9e88e..35b9d4e2 100644
--- a/data/CMakeLists.txt
+++ b/data/CMakeLists.txt
@@ -1,5 +1,6 @@
SET(DATA_DIR ${PKG_DATADIR}/data)
+ADD_SUBDIRECTORY(fonts)
ADD_SUBDIRECTORY(graphics)
ADD_SUBDIRECTORY(help)
ADD_SUBDIRECTORY(icons)
diff --git a/data/fonts/CMakeLists.txt b/data/fonts/CMakeLists.txt
index dc22e031..d5b6ed85 100644
--- a/data/fonts/CMakeLists.txt
+++ b/data/fonts/CMakeLists.txt
@@ -1,6 +1,6 @@
SET (FILES
dejavusans.ttf
+ dejavusans-bold.ttf
)
INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/fonts)
-
diff --git a/data/fonts/Makefile.am b/data/fonts/Makefile.am
index 331f6c8b..5aa02999 100644
--- a/data/fonts/Makefile.am
+++ b/data/fonts/Makefile.am
@@ -1,5 +1,8 @@
fontsdir = $(pkgdatadir)/data/fonts
-fonts_DATA = dejavusans.ttf
+fonts_DATA = \
+ dejavusans.ttf \
+ dejavusans-bold.ttf
-EXTRA_DIST = $(fonts_DATA)
+EXTRA_DIST = \
+ $(fonts_DATA)
diff --git a/data/fonts/dejavusans-bold.ttf b/data/fonts/dejavusans-bold.ttf
new file mode 100644
index 00000000..ebefb0ca
--- /dev/null
+++ b/data/fonts/dejavusans-bold.ttf
Binary files differ
diff --git a/data/fonts/dejavusans.ttf b/data/fonts/dejavusans.ttf
index 627cef46..6253857c 100644
--- a/data/fonts/dejavusans.ttf
+++ b/data/fonts/dejavusans.ttf
Binary files differ
diff --git a/data/graphics/gui/CMakeLists.txt b/data/graphics/gui/CMakeLists.txt
index 3d617696..6351d5ba 100644
--- a/data/graphics/gui/CMakeLists.txt
+++ b/data/graphics/gui/CMakeLists.txt
@@ -8,7 +8,8 @@ SET (FILES
checkbox.png
close_button.png
deepbox.png
- fixedfont.png
+ default.png
+ gui.xml
hits_blue.png
hits_red.png
hits_yellow.png
@@ -20,16 +21,13 @@ SET (FILES
hscroll_right_pressed.png
item_shortcut_bgr.png
mouse.png
- menuitemD.png
- menuitemF.png
- menuitemN.png
- menuitemP.png
radioin.png
radioout.png
resize.png
- rpgfont_wider.png
selection.png
slider.png
+ speech_bubble.png
+ speech_bubble.xml
tab.png
tabselected.png
target-cursor-blue-l.png
@@ -38,7 +36,6 @@ SET (FILES
target-cursor-red-l.png
target-cursor-red-m.png
target-cursor-red-s.png
- thickborder.png
unknown-item.png
vscroll_blue.png
vscroll_down_default.png
diff --git a/data/graphics/gui/Makefile.am b/data/graphics/gui/Makefile.am
index 33abf521..eb4c7365 100644
--- a/data/graphics/gui/Makefile.am
+++ b/data/graphics/gui/Makefile.am
@@ -11,8 +11,8 @@ gui_DATA = \
checkbox.png \
close_button.png \
deepbox.png \
- emotions.png \
- fixedfont.png \
+ default.png \
+ gui.xml \
hits_blue.png \
hits_red.png \
hits_yellow.png \
@@ -24,16 +24,13 @@ gui_DATA = \
hscroll_right_pressed.png \
item_shortcut_bgr.png \
mouse.png \
- menuitemD.png \
- menuitemF.png \
- menuitemN.png \
- menuitemP.png \
radioin.png \
radioout.png \
resize.png \
- rpgfont_wider.png \
selection.png \
slider.png \
+ speech_bubble.png \
+ speechbubble.xml \
tab.png \
tabselected.png \
target-cursor-blue-l.png \
@@ -42,7 +39,6 @@ gui_DATA = \
target-cursor-red-l.png \
target-cursor-red-m.png \
target-cursor-red-s.png \
- thickborder.png \
unknown-item.png \
vscroll_blue.png \
vscroll_down_default.png \
diff --git a/data/graphics/gui/default.png b/data/graphics/gui/default.png
new file mode 100644
index 00000000..4c312487
--- /dev/null
+++ b/data/graphics/gui/default.png
Binary files differ
diff --git a/data/graphics/gui/emotions.png b/data/graphics/gui/emotions.png
deleted file mode 100644
index 146f2d24..00000000
--- a/data/graphics/gui/emotions.png
+++ /dev/null
Binary files differ
diff --git a/data/graphics/gui/fixedfont.png b/data/graphics/gui/fixedfont.png
deleted file mode 100644
index 10319291..00000000
--- a/data/graphics/gui/fixedfont.png
+++ /dev/null
Binary files differ
diff --git a/data/graphics/gui/gui.xml b/data/graphics/gui/gui.xml
new file mode 100644
index 00000000..fe62528e
--- /dev/null
+++ b/data/graphics/gui/gui.xml
@@ -0,0 +1,18 @@
+<skinset name="Default" image="default.png">
+ <widget type="Window">
+ <!-- Top Row -->
+ <part type="top-left-corner" xpos="0" ypos="0" width="4" height="4" />
+ <part type="top-edge" xpos="4" ypos="0" width="3" height="4" />
+ <part type="top-right-corner" xpos="7" ypos="0" width="4" height="4" />
+
+ <!-- Middle Row -->
+ <part type="left-edge" xpos="0" ypos="4" width="4" height="10" />
+ <part type="bg-quad" xpos="11" ypos="0" width="32" height="32" />
+ <part type="right-edge" xpos="7" ypos="4" width="4" height="10" />
+
+ <!-- Bottom Row -->
+ <part type="bottom-left-corner" xpos="0" ypos="15" width="4" height="4" />
+ <part type="bottom-edge" xpos="4" ypos="15" width="3" height="4" />
+ <part type="bottom-right-corner" xpos="7" ypos="15" width="4" height="4" />
+ </widget>
+</skinset> \ No newline at end of file
diff --git a/data/graphics/gui/hits_blue.png b/data/graphics/gui/hits_blue.png
index 59458485..cfb04ab8 100644
--- a/data/graphics/gui/hits_blue.png
+++ b/data/graphics/gui/hits_blue.png
Binary files differ
diff --git a/data/graphics/gui/hits_red.png b/data/graphics/gui/hits_red.png
index da765dc4..150f1c1e 100644
--- a/data/graphics/gui/hits_red.png
+++ b/data/graphics/gui/hits_red.png
Binary files differ
diff --git a/data/graphics/gui/hits_yellow.png b/data/graphics/gui/hits_yellow.png
index d77b7c05..6975dfd5 100644
--- a/data/graphics/gui/hits_yellow.png
+++ b/data/graphics/gui/hits_yellow.png
Binary files differ
diff --git a/data/graphics/gui/menuitemD.png b/data/graphics/gui/menuitemD.png
deleted file mode 100644
index a9fe2222..00000000
--- a/data/graphics/gui/menuitemD.png
+++ /dev/null
Binary files differ
diff --git a/data/graphics/gui/menuitemF.png b/data/graphics/gui/menuitemF.png
deleted file mode 100644
index 84142a16..00000000
--- a/data/graphics/gui/menuitemF.png
+++ /dev/null
Binary files differ
diff --git a/data/graphics/gui/menuitemN.png b/data/graphics/gui/menuitemN.png
deleted file mode 100644
index bf25dd61..00000000
--- a/data/graphics/gui/menuitemN.png
+++ /dev/null
Binary files differ
diff --git a/data/graphics/gui/menuitemP.png b/data/graphics/gui/menuitemP.png
deleted file mode 100644
index 060d5a34..00000000
--- a/data/graphics/gui/menuitemP.png
+++ /dev/null
Binary files differ
diff --git a/data/graphics/gui/rpgfont_wider.png b/data/graphics/gui/rpgfont_wider.png
deleted file mode 100644
index 55ccbbd6..00000000
--- a/data/graphics/gui/rpgfont_wider.png
+++ /dev/null
Binary files differ
diff --git a/data/graphics/gui/speech_bubble.png b/data/graphics/gui/speech_bubble.png
new file mode 100644
index 00000000..3e678099
--- /dev/null
+++ b/data/graphics/gui/speech_bubble.png
Binary files differ
diff --git a/data/graphics/gui/speechbubble.xml b/data/graphics/gui/speechbubble.xml
new file mode 100644
index 00000000..1b11ea85
--- /dev/null
+++ b/data/graphics/gui/speechbubble.xml
@@ -0,0 +1,18 @@
+<skinset name="SpeechBubble" image="speech_bubble.png">
+ <widget type="Window">
+ <!-- Top Row -->
+ <part type="top-left-corner" xpos="0" ypos="0" width="14" height="14" />
+ <part type="top-edge" xpos="15" ypos="0" width="1" height="14" />
+ <part type="top-right-corner" xpos="17" ypos="0" width="17" height="14" />
+
+ <!-- Middle Row -->
+ <part type="left-edge" xpos="0" ypos="15" width="14" height="1" />
+ <part type="bg-quad" xpos="34" ypos="0" width="32" height="32" />
+ <part type="right-edge" xpos="17" ypos="15" width="17" height="1" />
+
+ <!-- Bottom Row -->
+ <part type="bottom-left-corner" xpos="0" ypos="17" width="14" height="17" />
+ <part type="bottom-edge" xpos="15" ypos="17" width="1" height="17" />
+ <part type="bottom-right-corner" xpos="17" ypos="17" width="17" height="17" />
+ </widget>
+</skinset> \ No newline at end of file
diff --git a/data/graphics/gui/thickborder.png b/data/graphics/gui/thickborder.png
deleted file mode 100644
index da72c92f..00000000
--- a/data/graphics/gui/thickborder.png
+++ /dev/null
Binary files differ
diff --git a/data/help/commands.txt b/data/help/commands.txt
index 2c6e8299..c4795050 100644
--- a/data/help/commands.txt
+++ b/data/help/commands.txt
@@ -29,9 +29,7 @@
##2H##P hide all non-sticky windows
##2Z##P pick up item
##2Enter##P focus chat window / send message
- ##2Shift##P hold it when attacking to lock target for auto
- attack
-
+
##2MOUSE:
@@ -55,6 +53,8 @@
/whisper "<name>" <message>
+ For further help type /help in the chat console.
+
##2IGNORING COMMUNICATION
diff --git a/data/help/skills.txt b/data/help/skills.txt
index 84d5bc5a..3a075ee0 100644
--- a/data/help/skills.txt
+++ b/data/help/skills.txt
@@ -11,5 +11,7 @@
##2Level 1:##P enables the ability to trade with others
##2Level 2:##P enables the ability to express emotions
##2Level 3:##P enables character to sit
+ ##2Level 5:##P enables a char to join a party.
+ ##2Level 7:##P enables a char to create a party
Other levels are still not implemented.
\ No newline at end of file
diff --git a/docs/FAQ.txt b/docs/FAQ.txt
index 2f1eee8b..b214672e 100644
--- a/docs/FAQ.txt
+++ b/docs/FAQ.txt
@@ -36,15 +36,6 @@ A: Did you read README? Are you really sure? If not go read it and you'll find
README/ingame help is not up to date/wrong, please report it to the
developers.
-Q: I just typed /<command> in the chat window and then I saw "Your account has
- been banished until ..." and TMW closed. Now when I try to log in nothing
- happens?
-
-A: That's because /<commands> are not implemented at the moment of writing.
- Please avoid using such commands (i.e. /help) until they're added.
- Anyway the ban is temp, just wait some minutes and you should be able to
- connect again.
-
Q: I can't recover HP anymore.
A: Check your inventory, if you've got lots of stuff probably you're
@@ -67,7 +58,7 @@ DEVELOPMENT
Q: When will the next version be released?
A: We have scheduled releases. Usually a new release is available every month.
- Check http://wiki.themanaworld.org/index.php/Roadmap for further infos.
+ Check http://themanaworld.org/ for further info.
Q: How can I contribute?
@@ -80,11 +71,11 @@ A: There are a lot of ways:
channel: #themanaworld @ irc.freenode.net.
- You can donate money. Follow the link on the project page:
- http://sourceforge.net/projects/themanaworld.
- - You can be a beta tester. Just play with The Mana World and report every
- error to the tracker. Read for more infos on the project page:
- http://themanaworld.org.
+ http://sourceforge.net/projects/themanaworld/
+
+ - You can be a beta tester. Just play The Mana World and report every
+ error to the tracker or on the forum.
- Play with The Mana World: more players, more fun! Simple as that! ;-)
diff --git a/docs/INSTALL/win32.txt b/docs/INSTALL/win32.txt
index 1a1e527f..fb758c43 100644
--- a/docs/INSTALL/win32.txt
+++ b/docs/INSTALL/win32.txt
@@ -44,7 +44,7 @@ This tutorial is written and tested with the latest beta version, which is
the old stable version, so don't do that. Get Dev-C++ here:
http://www.bloodshed.net/
-
+
After you have fetched it, simply run and install as prompted.
@@ -124,7 +124,7 @@ start compilition with Excute -> Compile. A file called tmw.exe should appear
in the same directory as where you opened the .dev from.
Before you can actually run the executable be sure to copy over the following
-DLLs from your Dev-Cpp/dll directory to the directory containing tmw.exe (or
+DLLs from your Dev-Cpp/dll directory to the directory containing tmw.exe (or
alternatively into your c:\windows\system\ for a more universal solution):
SDL.dll
diff --git a/docs/packages.txt b/docs/packages.txt
index 40ade7f9..3d794a1b 100644
--- a/docs/packages.txt
+++ b/docs/packages.txt
@@ -125,27 +125,27 @@ the data while working on the next package to be released.
The resource management technique is critical to the overall success of the
package management system as a whole. Resources are loaded at runtime as they
-are needed, and unloaded as they become unused. In order to ensure the
-autonomous functioning of this process reference counting is the agreed upon
-technique for managing loaded resources in TMW.
+are needed, and unloaded as they become unused. In order to ensure the
+autonomous functioning of this process reference counting is the agreed upon
+technique for managing loaded resources in TMW.
-For those unfamiliar with the practice of reference counting, it involves
+For those unfamiliar with the practice of reference counting, it involves
every resource object having a variable containing the number of references to
the object. When a reference is added the function addRef() is called and when
-it is removed the function release() is called. When the reference count
-reaches zero the object will automatically delete itself, thus handling the
+it is removed the function release() is called. When the reference count
+reaches zero the object will automatically delete itself, thus handling the
cleanup of resources.
Reference counting will form the core of the resource management system. Each
resource object will have the functionality of a reference counted object. The
-resource manager will hold ResourceEntry objects. The resource entry object
-contains a pointer to the resource as well as the location of the path of the
+resource manager will hold ResourceEntry objects. The resource entry object
+contains a pointer to the resource as well as the location of the path of the
file the resource was loaded from. This would look something like:
/**
* A generic reference counted resource object.
*/
- class Resource {
+ class Resource {
public:
/**
* Loads the resource from the specified path.
@@ -158,17 +158,17 @@ file the resource was loaded from. This would look something like:
* Increments the reference counted of this object.
*/
void addRef() { ++referenceCount; }
-
+
/**
* Decrements the reference count and deletes the object
* if no references are left.
* @return <code>true</code> if the object was deleted
* <code>false</code> otherwise.
*/
- void release() {
+ void release() {
--referenceCount;
- if(!referenceCount)
+ if (!referenceCount)
{
delete this;
return true;
@@ -183,14 +183,14 @@ file the resource was loaded from. This would look something like:
/**
* A resource entry descriptor.
*/
- struct ResourceEntry {
- Resource* resource;
- std::string filePath;
+ struct ResourceEntry {
+ Resource* resource;
+ std::string filePath;
};
...
The resource manager would then hold a mapping containing the resource entry as
-well as the string defining its resource identification path. The resource
+well as the string defining its resource identification path. The resource
manager would thus look something like this:
/**
diff --git a/packaging/windows/make-translations.vbs b/packaging/windows/make-translations.vbs
new file mode 100644
index 00000000..f349b25e
--- /dev/null
+++ b/packaging/windows/make-translations.vbs
@@ -0,0 +1,42 @@
+Set fso = CreateObject("Scripting.FileSystemObject")
+Set WshShell = CreateObject("WScript.Shell")
+Dim s, infile, outfile, command
+
+Function CreateFolderIfNonexistent(folder)
+ if not fso.FolderExists(folder) then
+ fso.CreateFolder(folder)
+ end if
+end Function
+
+'check for existence of msgfmt
+if not fso.FileExists("msgfmt.exe") then
+ WScript.echo "msgfmt.exe not found. Please get gettext for windows from http://gnuwin32.sourceforge.net/packages/gettext.htm and copy the files msgfmt.exe and all dll files from the gettext/bin directory into this directory and run this script again."
+ WScript.Quit(1)
+end if
+
+CreateFolderIfNonexistent("..\..\translations\")
+
+'open translation list
+Set stream = fso.GetFile("..\..\po\LINGUAS").OpenAsTextStream(1, 0)
+
+'iterate contents of translations file
+translations = 0
+do while not stream.AtEndOfStream
+ s = stream.ReadLine()
+ if inStr(s, "#") = false then
+ 'create the output directory
+ CreateFolderIfNonexistent("..\..\translations\" + s)
+ CreateFolderIfNonexistent("..\..\translations\" + s + "\LC_MESSAGES")
+ 'build the translate command
+ infile = "../../po/" + s + ".po"
+ outfile = "../../translations/" + s +"/LC_MESSAGES/tmw.mo"
+ command = "msgfmt -c -o " + outfile + " " + infile
+ 'execute translate command
+ errval = WshShell.run(command, 0, true)
+ if errval = 0 then
+ translations = translations + 1
+ end if
+ end if
+loop
+
+WScript.echo translations, " translations compiled."
diff --git a/packaging/windows/setup.nsi b/packaging/windows/setup.nsi
index ec57051c..e1c1e390 100644
--- a/packaging/windows/setup.nsi
+++ b/packaging/windows/setup.nsi
@@ -43,6 +43,8 @@ SetCompressor /SOLID lzma
!insertmacro MUI_PAGE_LICENSE "${SRCDIR}\COPYING"
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
+; Components page
+!insertmacro MUI_PAGE_COMPONENTS
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
@@ -152,7 +154,6 @@ Section "Core files (required)" SecCore
CreateDirectory "$INSTDIR\data\graphics"
CreateDirectory "$INSTDIR\data\help"
CreateDirectory "$INSTDIR\data\icons"
- CreateDirectory "$INSTDIR\data\music"
CreateDirectory "$INSTDIR\data\graphics\gui"
CreateDirectory "$INSTDIR\data\graphics\images"
CreateDirectory "$INSTDIR\docs"
@@ -170,18 +171,37 @@ Section "Core files (required)" SecCore
File "${SRCDIR}\data\fonts\*.ttf"
SetOutPath "$INSTDIR\data\graphics\gui"
File "${SRCDIR}\data\graphics\gui\*.png"
+ File "${SRCDIR}\data\graphics\gui\*.xml"
SetOutPath "$INSTDIR\data\graphics\images"
File /x minimap_*.png ${SRCDIR}\data\graphics\images\*.png
SetOutPath "$INSTDIR\data\help"
File "${SRCDIR}\data\help\*.txt"
SetOutPath "$INSTDIR\data\icons\"
File "${SRCDIR}\data\icons\tmw.ico"
- SetOutPath "$INSTDIR\data\music"
- File /nonfatal "${SRCDIR}\data\music\*.ogg"
SetOutPath "$INSTDIR\docs"
File "${SRCDIR}\docs\FAQ.txt"
SectionEnd
+Section "Music" SecMusic
+ CreateDirectory "$INSTDIR\data\music"
+ SetOutPath "$INSTDIR\data\music"
+ File /nonfatal "${SRCDIR}\data\music\*.ogg"
+SectionEnd
+
+Section "Translations" SecTrans
+ SetOutPath "$INSTDIR"
+ File /nonfatal /r "${SRCDIR}\translations"
+SectionEnd
+
+;Package descriptions
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+ !insertmacro MUI_DESCRIPTION_TEXT ${SecCore} "The core program files."
+ !insertmacro MUI_DESCRIPTION_TEXT ${SecMusic} "Background music."
+ !insertmacro MUI_DESCRIPTION_TEXT ${SecTrans} "Translations for the user interface into 23 different languages. Uncheck this component to leave it in English."
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+
+
Section -AdditionalIcons
WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
CreateShortCut "$SMPROGRAMS\The Mana World\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4207012b..1b3dea84 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -5,30 +5,58 @@ src/gui/buysell.cpp
src/gui/char_select.cpp
src/gui/char_server.cpp
src/gui/chat.cpp
+src/gui/color.cpp
src/gui/confirm_dialog.cpp
src/gui/connection.cpp
+src/gui/emotecontainer.cpp
+src/gui/emoteshortcutcontainer.cpp
+src/gui/emotewindow.cpp
src/gui/equipmentwindow.cpp
src/gui/help.cpp
src/gui/inventorywindow.cpp
src/gui/item_amount.cpp
+src/gui/itempopup.cpp
src/gui/login.cpp
src/gui/menuwindow.cpp
src/gui/minimap.cpp
+src/gui/npcintegerdialog.cpp
src/gui/npclistdialog.cpp
+src/gui/npcstringdialog.cpp
src/gui/npc_text.cpp
src/gui/ok_dialog.cpp
src/gui/popupmenu.cpp
+src/gui/recorder.cpp
+src/gui/recorder.h
src/gui/register.cpp
src/gui/sell.cpp
src/gui/setup_audio.cpp
src/gui/setup.cpp
+src/gui/setup_colors.cpp
src/gui/setup_joystick.cpp
src/gui/setup_keyboard.cpp
src/gui/setup_players.cpp
src/gui/setup_video.cpp
src/gui/skill.cpp
+src/gui/speechbubble.cpp
src/gui/status.cpp
src/gui/trade.cpp
src/gui/updatewindow.cpp
+src/net/buysellhandler.cpp
+src/net/charserverhandler.cpp
+src/net/chathandler.cpp
+src/net/equipmenthandler.cpp
+src/net/inventoryhandler.cpp
+src/net/loginhandler.cpp
+src/net/maploginhandler.cpp
+src/net/playerhandler.cpp
+src/net/tradehandler.cpp
+src/resources/colordb.cpp
+src/resources/emotedb.cpp
src/resources/itemdb.cpp
+src/resources/monsterdb.cpp
+src/resources/npcdb.cpp
+src/being.cpp
+src/game.cpp
+src/keyboardconfig.cpp
src/main.cpp
+src/party.cpp
diff --git a/po/sv.po b/po/sv.po
index 0c7cd26c..ab0b6f54 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: tmw\n"
"Report-Msgid-Bugs-To: themanaworld-devel@lists.sourceforge.net\n"
"POT-Creation-Date: 2009-01-25 22:01+0100\n"
-"PO-Revision-Date: 2008-05-07 19:04+0000\n"
-"Last-Translator: Kess Vargavind <Unknown>\n"
+"PO-Revision-Date: 2009-01-29 01:20+0100\n"
+"Last-Translator: Kess Vargavind <vargavind@gmail.com>\n"
"Language-Team: Swedish <sv@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -47,9 +47,8 @@ msgid "Effect: %s"
msgstr "Effekt: %s"
#: src/gui/buysell.cpp:31
-#, fuzzy
msgid "Shop"
-msgstr "Stopp"
+msgstr "Affär"
#: src/gui/buysell.cpp:35 src/gui/sell.cpp:48 src/gui/sell.cpp:68
msgid "Sell"
@@ -65,7 +64,7 @@ msgstr "Avbryt"
#: src/gui/char_select.cpp:63
msgid "Confirm Character Delete"
-msgstr ""
+msgstr "Bekräfta borttagning av karaktär"
#: src/gui/char_select.cpp:64
msgid "Are you sure you want to delete this character?"
@@ -111,9 +110,9 @@ msgstr "Nivå: %d"
#: src/gui/char_select.cpp:93 src/gui/char_select.cpp:173
#: src/gui/char_select.cpp:185
-#, fuzzy, c-format
+#, c-format
msgid "Job Level: %d"
-msgstr "Nivå: %d"
+msgstr "Jobbnivå: %d"
#: src/gui/char_select.cpp:94 src/gui/char_select.cpp:186
#, c-format
@@ -123,7 +122,7 @@ msgstr "Pengar: %d"
#: src/gui/char_select.cpp:174
#, c-format
msgid "Gold: %d"
-msgstr ""
+msgstr "Guld: %d"
#: src/gui/char_select.cpp:243
msgid "Create Character"
@@ -146,23 +145,22 @@ msgid "Create"
msgstr "Skapa"
#: src/gui/char_server.cpp:52
-#, fuzzy
msgid "Select Server"
-msgstr "Välj karaktär"
+msgstr "Välj server"
#: src/gui/char_server.cpp:59 src/gui/npclistdialog.cpp:44
#: src/gui/npc_text.cpp:46
msgid "OK"
-msgstr ""
+msgstr "Ok"
#: src/gui/chat.cpp:115
msgid "Global announcement:"
-msgstr ""
+msgstr "Globalt meddelande:"
#: src/gui/chat.cpp:118
#, c-format
msgid "Global announcement from %s:"
-msgstr ""
+msgstr "Globalt meddelande från %s:"
#: src/gui/chat.cpp:133 src/gui/login.cpp:46 src/gui/register.cpp:82
msgid "Server:"
@@ -171,208 +169,210 @@ msgstr "Server:"
#: src/gui/chat.cpp:139
#, c-format
msgid "%s whispers:"
-msgstr ""
+msgstr "%s viskar:"
#: src/gui/chat.cpp:276
#, c-format
msgid "Whispering to %s: %s"
-msgstr ""
+msgstr "Viskar till %s: %s"
#: src/gui/chat.cpp:349
msgid "Unknown command"
-msgstr ""
+msgstr "Okänt kommando"
#: src/gui/chat.cpp:359
msgid "Trade failed!"
-msgstr ""
+msgstr "Byteshandel misslyckades!"
#: src/gui/chat.cpp:362
msgid "Emote failed!"
-msgstr ""
+msgstr "Kan inte visa smiley!"
#: src/gui/chat.cpp:365
msgid "Sit failed!"
-msgstr ""
+msgstr "Kan inte sitta ned!"
#: src/gui/chat.cpp:368
msgid "Chat creating failed!"
-msgstr ""
+msgstr "Kan inte skicka chattmeddelande!"
#: src/gui/chat.cpp:371
msgid "Could not join party!"
-msgstr ""
+msgstr "Kan inte ansluta till gruppen!"
#: src/gui/chat.cpp:374
msgid "Cannot shout!"
-msgstr ""
+msgstr "Kan inte skrika!"
#: src/gui/chat.cpp:382
msgid "You have not yet reached a high enough lvl!"
-msgstr ""
+msgstr "Du har inte nått en tillräckligt hög nivå än!"
#: src/gui/chat.cpp:385
msgid "Insufficient HP!"
-msgstr ""
+msgstr "Otillräckligt med HP!"
#: src/gui/chat.cpp:388
msgid "Insufficient SP!"
-msgstr ""
+msgstr "Otillräckligt med SP!"
#: src/gui/chat.cpp:391
msgid "You have no memos!"
-msgstr ""
+msgstr "Du har inga anteckningar!"
#: src/gui/chat.cpp:394
msgid "You cannot do that right now!"
-msgstr ""
+msgstr "Du kan inte göra det just nu!"
#: src/gui/chat.cpp:397
msgid "Seems you need more Zeny... ;-)"
-msgstr ""
+msgstr "Verkar som att du behöver mer zeny... ;-)"
#: src/gui/chat.cpp:400
msgid "You cannot use this skill with that kind of weapon!"
-msgstr ""
+msgstr "Det går inte att använda den här förmågan med det där vapenslaget!"
#: src/gui/chat.cpp:403
msgid "You need another red gem!"
-msgstr ""
+msgstr "Du behöver en till röd juvel!"
#: src/gui/chat.cpp:406
msgid "You need another blue gem!"
-msgstr ""
+msgstr "Du behöver en till blå juvel!"
#: src/gui/chat.cpp:409
msgid "You're carrying to much to do this!"
-msgstr ""
+msgstr "Du bär på för mycket för att kunna göra det här!"
#: src/gui/chat.cpp:412
msgid "Huh? What's that?"
-msgstr ""
+msgstr "Öh? Vad är det där?"
#: src/gui/chat.cpp:418
msgid "Warp failed..."
-msgstr ""
+msgstr "Kartförflyttning misslyckades..."
#: src/gui/chat.cpp:421
msgid "Could not steal anything..."
-msgstr ""
+msgstr "Kunde inte stjäla något..."
#: src/gui/chat.cpp:424
msgid "Poison had no effect..."
-msgstr ""
+msgstr "Giftet tog inte..."
#: src/gui/chat.cpp:489
msgid "-- Help --"
-msgstr ""
+msgstr "-- Hjälp --"
#: src/gui/chat.cpp:492
msgid "/announce: Global announcement (GM only)"
-msgstr ""
+msgstr "/announce: Globalt meddelande (endast GM)"
#: src/gui/chat.cpp:493
msgid "/clear: Clears this window"
-msgstr ""
+msgstr "/clear: Tömmer det här fönstret på text"
#: src/gui/chat.cpp:494
msgid "/help: Display this help"
-msgstr ""
+msgstr "/help: Visar den här hjälptexten"
#: src/gui/chat.cpp:495
msgid "/where: Display map name"
-msgstr ""
+msgstr "/where: Visar namnet på kartan där du befinner dig"
#: src/gui/chat.cpp:496
msgid "/whisper <nick> <message>: Sends a private <message> to <nick>"
-msgstr ""
+msgstr "/whisper <namn> <text>: Skickar ett privat meddelande till en spelare"
#: src/gui/chat.cpp:498
msgid "/w <nick> <message>: Short form for /whisper"
-msgstr ""
+msgstr "/w <namn> <text>: Kortare variant av /whisper"
#: src/gui/chat.cpp:499
msgid "/who: Display number of online users"
-msgstr ""
+msgstr "/who: Visar antalet inloggade spelare"
#: src/gui/chat.cpp:500
msgid "For more information, type /help <command>"
-msgstr ""
+msgstr "För mer information skriv /help <kommando>"
#: src/gui/chat.cpp:505
msgid "Command: /announce <msg>"
-msgstr ""
+msgstr "Kommando: /announce <text>"
#: src/gui/chat.cpp:506
msgid "*** only available to a GM ***"
-msgstr ""
+msgstr "*** endast en GM kan använda det här kommandot ***"
#: src/gui/chat.cpp:507
msgid "This command sends the message <msg> to all players currently online."
msgstr ""
+"Det här kommandot skickar meddelandet <text> till alla inloggade spelare."
#: src/gui/chat.cpp:513
msgid "Command: /clear"
-msgstr ""
+msgstr "Kommando: /clear"
#: src/gui/chat.cpp:514
msgid "This command clears the chat log of previous chat."
-msgstr ""
+msgstr "Det här kommandot tömmer chattloggen."
#: src/gui/chat.cpp:520
msgid "Command: /help"
-msgstr ""
+msgstr "Kommando: /help"
#: src/gui/chat.cpp:521
msgid "This command displays a list of all commands available."
-msgstr ""
+msgstr "Det här kommandot visar en lista över alla tillgängliga kommandon."
#: src/gui/chat.cpp:523
msgid "Command: /help <command>"
-msgstr ""
+msgstr "Kommando: /help <kommando>"
#: src/gui/chat.cpp:524
msgid "This command displays help on <command>."
-msgstr ""
+msgstr "Det här kommandot ger mer information om <kommando>."
#: src/gui/chat.cpp:529
msgid "Command: /where"
-msgstr ""
+msgstr "Kommando: /where"
#: src/gui/chat.cpp:530
msgid "This command displays the name of the current map."
-msgstr ""
+msgstr "Det här kommandot visar namnet på den karta där du befinner dig."
#: src/gui/chat.cpp:536
msgid "Command: /whisper <nick> <msg>"
-msgstr ""
+msgstr "Kommando: /whisper <namn> <text>"
#: src/gui/chat.cpp:537
msgid "Command: /w <nick> <msg>"
-msgstr ""
+msgstr "Kommando: /w <namn> <text>"
#: src/gui/chat.cpp:538
msgid "This command sends the message <msg> to <nick>."
-msgstr ""
+msgstr "Det här kommandot skickar meddelandet <text> till karaktären <namn>."
#: src/gui/chat.cpp:540
msgid "If the <nick> has spaces in it, enclose it in double quotes (\")."
msgstr ""
+"Om <namn> innehåller mellanslag, måste du sätta citattecken (\") runt det."
#: src/gui/chat.cpp:546
msgid "Command: /who"
-msgstr ""
+msgstr "Kommando: /who"
#: src/gui/chat.cpp:547
msgid "This command displays the number of players currently online."
-msgstr ""
+msgstr "Det här kommandot visar antalet spelare som är inloggade just nu."
#: src/gui/chat.cpp:551
msgid "Unknown command."
-msgstr ""
+msgstr "Okänt kommando."
#: src/gui/chat.cpp:552
msgid "Type /help for a list of commands."
-msgstr ""
+msgstr "Skriv /help för en lista med kommandon."
#: src/gui/confirm_dialog.cpp:35
msgid "Yes"
@@ -392,11 +392,11 @@ msgstr "Utrustning"
#: src/gui/help.cpp:33
msgid "Help"
-msgstr ""
+msgstr "Hjälp"
#: src/gui/help.cpp:41
msgid "Close"
-msgstr ""
+msgstr "Stäng"
#: src/gui/inventorywindow.cpp:46 src/gui/menuwindow.cpp:63
msgid "Inventory"
@@ -414,12 +414,12 @@ msgstr "Släpp"
#: src/gui/inventorywindow.cpp:99
#, c-format
msgid "Weight: %d / %d"
-msgstr ""
+msgstr "Vikt: %d / %d"
#: src/gui/inventorywindow.cpp:104
#, c-format
msgid "Slots used: %d / %d"
-msgstr ""
+msgstr "Utrymme: %d / %d"
#: src/gui/inventorywindow.cpp:225
msgid "Unequip"
@@ -447,7 +447,7 @@ msgstr "Lösenord:"
#: src/gui/login.cpp:50
msgid "Remember Username"
-msgstr ""
+msgstr "Kom ihåg användarnamnet"
#: src/gui/login.cpp:53 src/gui/register.cpp:75 src/gui/register.cpp:89
msgid "Register"
@@ -463,7 +463,7 @@ msgstr "Färdigheter"
#: src/gui/menuwindow.cpp:65
msgid "Shortcut"
-msgstr "Genväg"
+msgstr "Genvägar"
#: src/gui/menuwindow.cpp:66 src/gui/setup.cpp:50 src/main.cpp:716
msgid "Setup"
@@ -502,9 +502,8 @@ msgid "@@pickup|Pick Up %s@@"
msgstr "@@pickup|Plocka upp %s@@"
#: src/gui/popupmenu.cpp:283
-#, fuzzy
msgid "@@use|Unequip@@"
-msgstr "@@use|Utrusta@@"
+msgstr "@@use|Avrusta@@"
#: src/gui/popupmenu.cpp:285
msgid "@@use|Equip@@"
@@ -528,11 +527,11 @@ msgstr "Bekräfta:"
#: src/gui/register.cpp:87
msgid "Male"
-msgstr ""
+msgstr "Man"
#: src/gui/register.cpp:88
msgid "Female"
-msgstr ""
+msgstr "Kvinna"
#: src/gui/register.cpp:159
#, c-format
@@ -596,11 +595,11 @@ msgstr "Joystick"
#: src/gui/setup.cpp:90
msgid "Keyboard"
-msgstr ""
+msgstr "Tangentbord"
#: src/gui/setup.cpp:94
msgid "Players"
-msgstr ""
+msgstr "Spelare"
#: src/gui/setup_joystick.cpp:39 src/gui/setup_joystick.cpp:78
msgid "Press the button to start calibration"
@@ -624,61 +623,59 @@ msgstr "Rotera spaken"
#: src/gui/setup_keyboard.cpp:88
msgid "Assign"
-msgstr ""
+msgstr "Tilldela"
#: src/gui/setup_keyboard.cpp:92
-#, fuzzy
msgid "Default"
-msgstr "Ta bort"
+msgstr "Förval"
#: src/gui/setup_keyboard.cpp:121
msgid "Key Conflict(s) Detected."
-msgstr ""
+msgstr "Samma tangent används på flera ställen."
#: src/gui/setup_keyboard.cpp:122
msgid "Resolve them, or gameplay may result in strange behaviour."
-msgstr ""
+msgstr "Se till att använda olika tangenter, annars kan det bli konstigheter."
#: src/gui/setup_players.cpp:55
-#, fuzzy
msgid "Name"
-msgstr "Namn:"
+msgstr "Namn"
#: src/gui/setup_players.cpp:56
msgid "Relation"
-msgstr ""
+msgstr "Relation"
#: src/gui/setup_players.cpp:60
msgid "Neutral"
-msgstr ""
+msgstr "Neutral"
#: src/gui/setup_players.cpp:61
msgid "Friend"
-msgstr ""
+msgstr "Vän"
#: src/gui/setup_players.cpp:62
msgid "Disregarded"
-msgstr ""
+msgstr "Förbisedd"
#: src/gui/setup_players.cpp:63
msgid "Ignored"
-msgstr ""
+msgstr "Ignorerad"
#: src/gui/setup_players.cpp:217
msgid "Save player list"
-msgstr ""
+msgstr "Kom ihåg spelarlista"
#: src/gui/setup_players.cpp:219
msgid "Allow trading"
-msgstr ""
+msgstr "Tillåt byteshandel"
#: src/gui/setup_players.cpp:221
msgid "Allow whispers"
-msgstr ""
+msgstr "Tillåt viskningar"
#: src/gui/setup_players.cpp:248
msgid "When ignoring:"
-msgstr ""
+msgstr "Vid ignorering:"
#: src/gui/setup_video.cpp:114
msgid "Full screen"
@@ -714,7 +711,7 @@ msgstr "Omgivande FX"
#: src/gui/setup_video.cpp:144
msgid "Particle Detail"
-msgstr ""
+msgstr "Partikeldetaljer"
#: src/gui/setup_video.cpp:198 src/gui/setup_video.cpp:398
msgid "off"
@@ -732,11 +729,11 @@ msgstr "hög"
#: src/gui/setup_video.cpp:215 src/gui/setup_video.cpp:418
msgid "medium"
-msgstr ""
+msgstr "medium"
#: src/gui/setup_video.cpp:221 src/gui/setup_video.cpp:424
msgid "max"
-msgstr ""
+msgstr "maximal"
#: src/gui/setup_video.cpp:296
msgid "Switching to full screen"
@@ -756,107 +753,97 @@ msgstr "Ändringar i OpenGL kräver omstart."
#: src/gui/skill.cpp:79
msgid "Mystery Skill"
-msgstr ""
+msgstr "Mystisk förmåga"
#: src/gui/skill.cpp:132 src/gui/skill.cpp:188
#, c-format
msgid "Skill points: %d"
-msgstr ""
+msgstr "Färdighetspoäng: %d"
#: src/gui/skill.cpp:133
msgid "Up"
-msgstr ""
+msgstr "Upp"
#: src/gui/status.cpp:52 src/gui/status.cpp:235
-#, fuzzy, c-format
+#, c-format
msgid "Job: %d"
-msgstr "Nivå: %d"
+msgstr "Jobb: %d"
#: src/gui/status.cpp:53 src/gui/status.cpp:238
-#, fuzzy, c-format
+#, c-format
msgid "Money: %d GP"
-msgstr "Pengar: %d"
+msgstr "Pengar: %d GP"
#: src/gui/status.cpp:127
-#, fuzzy
msgid "Stats"
-msgstr "Status"
+msgstr "Statistik"
#: src/gui/status.cpp:128
msgid "Total"
-msgstr ""
+msgstr "Totalt"
#: src/gui/status.cpp:129
msgid "Cost"
-msgstr ""
+msgstr "Kostnad"
#: src/gui/status.cpp:132
-#, fuzzy
msgid "Attack:"
-msgstr "Attack %+d"
+msgstr "Attack:"
#: src/gui/status.cpp:133
-#, fuzzy
msgid "Defense:"
-msgstr "Försvar %+d"
+msgstr "Försvar:"
#: src/gui/status.cpp:134
-#, fuzzy
msgid "M.Attack:"
-msgstr "Attack %+d"
+msgstr "M. attack:"
#: src/gui/status.cpp:135
-#, fuzzy
msgid "M.Defense:"
-msgstr "Försvar %+d"
+msgstr "M. försvar:"
#: src/gui/status.cpp:136
-#, c-format
+#, fuzzy, no-c-format
msgid "% Accuracy:"
-msgstr ""
+msgstr "% Precision:"
#: src/gui/status.cpp:137
-#, c-format
+#, fuzzy, no-c-format
msgid "% Evade:"
-msgstr ""
+msgstr "% Undvikan:"
#: src/gui/status.cpp:138
msgid "% Reflex:"
-msgstr ""
+msgstr "% Reflexer:"
#: src/gui/status.cpp:282
-#, fuzzy
msgid "Strength"
-msgstr "Styrka:"
+msgstr "Styrka"
#: src/gui/status.cpp:283
-#, fuzzy
msgid "Agility"
-msgstr "Smidighet:"
+msgstr "Smidighet"
#: src/gui/status.cpp:284
-#, fuzzy
msgid "Vitality"
-msgstr "Hälsa:"
+msgstr "Hälsa"
#: src/gui/status.cpp:285
-#, fuzzy
msgid "Intelligence"
-msgstr "Intelligens:"
+msgstr "Intelligens"
#: src/gui/status.cpp:286
-#, fuzzy
msgid "Dexterity"
-msgstr "Skicklighet:"
+msgstr "Skicklighet"
#: src/gui/status.cpp:287
msgid "Luck"
-msgstr ""
+msgstr "Tur"
#: src/gui/status.cpp:305
#, c-format
msgid "Remaining Status Points: %d"
-msgstr ""
+msgstr "Återstående statuspoäng: %d"
#: src/gui/trade.cpp:61
msgid "Add"
@@ -864,7 +851,7 @@ msgstr "Lägg till"
#: src/gui/trade.cpp:64
msgid "Trade"
-msgstr ""
+msgstr "Byteshandla"
#: src/gui/trade.cpp:80 src/gui/trade.cpp:161 src/gui/trade.cpp:209
#, c-format
@@ -878,39 +865,40 @@ msgstr "Du ger:"
#: src/gui/trade.cpp:290
msgid "Failed adding item. You can not overlap one kind of item on the window."
msgstr ""
+"Kan inte lägga till vald sak. Det går inte att byteshandla med samma slags "
+"sak flera gånger."
#: src/gui/updatewindow.cpp:93
msgid "Updating..."
-msgstr ""
+msgstr "Uppdaterar..."
#: src/gui/updatewindow.cpp:119
msgid "Play"
-msgstr ""
+msgstr "Spela"
#: src/gui/updatewindow.cpp:526
msgid "Completed"
-msgstr ""
+msgstr "Färdig"
#: src/resources/itemdb.cpp:99
msgid "Unnamed"
-msgstr ""
+msgstr "Namnlös"
#: src/main.cpp:769
msgid "Got disconnected from server!"
-msgstr ""
+msgstr "Kopplades från servern!"
#: src/main.cpp:956
-#, fuzzy
msgid "Connecting to map server..."
-msgstr "Ansluter..."
+msgstr "Ansluter till kartservern..."
#: src/main.cpp:964
msgid "Connecting to character server..."
-msgstr ""
+msgstr "Ansluter till karaktärsservern..."
#: src/main.cpp:972
msgid "Connecting to account server..."
-msgstr ""
+msgstr "Ansluter till kontoservern..."
#~ msgid "Unregister"
#~ msgstr "Avregistrera"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 70a58272..c7e3d936 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -49,6 +49,8 @@ MARK_AS_ADVANCED(SDL_INCLUDE_DIR)
MARK_AS_ADVANCED(SDL_LIBRARY)
SET(SRCS
+ gui/widgets/dropdown.cpp
+ gui/widgets/dropdown.h
gui/widgets/resizegrip.cpp
gui/widgets/resizegrip.h
gui/widgets/layout.cpp
@@ -79,12 +81,20 @@ SET(SRCS
gui/chatinput.h
gui/checkbox.cpp
gui/checkbox.h
+ gui/color.cpp
+ gui/color.h
gui/confirm_dialog.cpp
gui/confirm_dialog.h
gui/connection.cpp
gui/connection.h
gui/debugwindow.cpp
gui/debugwindow.h
+ gui/emotecontainer.cpp
+ gui/emotecontainer.h
+ gui/emoteshortcutcontainer.cpp
+ gui/emoteshortcutcontainer.h
+ gui/emotewindow.cpp
+ gui/emotewindow.h
gui/equipmentwindow.cpp
gui/equipmentwindow.h
gui/focushandler.cpp
@@ -101,10 +111,12 @@ SET(SRCS
gui/inventorywindow.h
gui/itemcontainer.cpp
gui/itemcontainer.h
+ gui/itemlinkhandler.cpp
+ gui/itemlinkhandler.h
+ gui/itempopup.cpp
+ gui/itempopup.h
gui/itemshortcutcontainer.cpp
- gui/itemshortcutcontainer.h
- gui/itemshortcutwindow.cpp
- gui/itemshortcutwindow.h
+ gui/itemshortcutcontainer.h\
gui/item_amount.cpp
gui/item_amount.h
gui/linkhandler.h
@@ -138,6 +150,8 @@ SET(SRCS
gui/progressbar.h
gui/radiobutton.cpp
gui/radiobutton.h
+ gui/recorder.cpp
+ gui/recorder.h
gui/register.cpp
gui/register.h
gui/scrollarea.cpp
@@ -146,10 +160,12 @@ SET(SRCS
gui/sdlinput.h
gui/sell.cpp
gui/sell.h
- gui/setup_audio.cpp
- gui/setup_audio.h
gui/setup.cpp
gui/setup.h
+ gui/setup_audio.cpp
+ gui/setup_audio.h
+ gui/setup_colors.cpp
+ gui/setup_colors.h
gui/setup_joystick.cpp
gui/setup_joystick.h
gui/setup_keyboard.cpp
@@ -163,10 +179,16 @@ SET(SRCS
gui/shop.h
gui/shoplistbox.cpp
gui/shoplistbox.h
+ gui/shortcutwindow.cpp
+ gui/shortcutwindow.h
+ gui/shortcutcontainer.cpp
+ gui/shortcutcontainer.h
gui/skill.cpp
gui/skill.h
gui/slider.cpp
gui/slider.h
+ gui/speechbubble.cpp
+ gui/speechbubble.h
gui/status.cpp
gui/status.h
gui/table.cpp
@@ -179,6 +201,8 @@ SET(SRCS
gui/textfield.h
gui/trade.cpp
gui/trade.h
+ gui/truetypefont.cpp
+ gui/truetypefont.h
gui/updatewindow.h
gui/updatewindow.cpp
gui/viewport.cpp
@@ -215,6 +239,8 @@ SET(SRCS
net/network.h
net/npchandler.cpp
net/npchandler.h
+ net/partyhandler.cpp
+ net/partyhandler.h
net/playerhandler.cpp
net/playerhandler.h
net/protocol.cpp
@@ -231,8 +257,12 @@ SET(SRCS
resources/animation.h
resources/buddylist.cpp
resources/buddylist.h
+ resources/colordb.cpp
+ resources/colordb.h
resources/dye.cpp
resources/dye.h
+ resources/emotedb.cpp
+ resources/emotedb.h
resources/image.cpp
resources/image.h
resources/imageloader.cpp
@@ -285,6 +315,10 @@ SET(SRCS
configlistener.h
configuration.cpp
configuration.h
+ effectmanager.cpp
+ effectmanager.h
+ emoteshortcut.cpp
+ emoteshortcut.h
engine.cpp
engine.h
equipment.cpp
@@ -328,9 +362,13 @@ SET(SRCS
openglgraphics.h
particle.cpp
particle.h
+ particlecontainer.cpp
+ particlecontainer.h
particleemitter.cpp
particleemitter.h
particleemitterprop.h
+ party.cpp
+ party.h
player.cpp
player.h
player_relations.cpp
@@ -346,6 +384,10 @@ SET(SRCS
sound.cpp
sound.h
sprite.h
+ text.cpp
+ text.h
+ textmanager.cpp
+ textmanager.h
textparticle.cpp
textparticle.h
tileset.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 358b0b61..8de13464 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,9 @@
AUTOMAKE_OPTIONS = subdir-objects
bin_PROGRAMS = tmw
-tmw_SOURCES = gui/widgets/layout.cpp \
+tmw_SOURCES = gui/widgets/dropdown.cpp \
+ gui/widgets/dropdown.h \
+ gui/widgets/layout.cpp \
gui/widgets/layout.h \
gui/widgets/layouthelper.cpp \
gui/widgets/layouthelper.h \
@@ -13,30 +15,36 @@ tmw_SOURCES = gui/widgets/layout.cpp \
gui/widgets/tabbedarea.h \
gui/browserbox.cpp \
gui/browserbox.h \
- gui/buddywindow.cpp \
- gui/buddywindow.h \
gui/button.cpp \
gui/button.h \
gui/buy.cpp \
gui/buy.h \
gui/buysell.cpp \
gui/buysell.h \
- gui/char_server.cpp \
- gui/char_server.h \
gui/char_select.cpp \
gui/char_select.h \
+ gui/char_server.cpp \
+ gui/char_server.h \
gui/chat.cpp \
gui/chat.h \
gui/chatinput.cpp \
gui/chatinput.h \
gui/checkbox.cpp \
gui/checkbox.h \
+ gui/color.cpp \
+ gui/color.h \
gui/confirm_dialog.cpp \
gui/confirm_dialog.h \
gui/connection.cpp \
gui/connection.h \
gui/debugwindow.cpp \
gui/debugwindow.h \
+ gui/emotecontainer.cpp \
+ gui/emotecontainer.h \
+ gui/emoteshortcutcontainer.cpp \
+ gui/emoteshortcutcontainer.h \
+ gui/emotewindow.cpp \
+ gui/emotewindow.h \
gui/equipmentwindow.cpp \
gui/equipmentwindow.h \
gui/focushandler.cpp \
@@ -53,10 +61,12 @@ tmw_SOURCES = gui/widgets/layout.cpp \
gui/inventorywindow.h \
gui/itemcontainer.cpp \
gui/itemcontainer.h \
+ gui/itemlinkhandler.cpp \
+ gui/itemlinkhandler.h \
+ gui/itempopup.cpp \
+ gui/itempopup.h \
gui/itemshortcutcontainer.cpp \
gui/itemshortcutcontainer.h \
- gui/itemshortcutwindow.cpp \
- gui/itemshortcutwindow.h \
gui/item_amount.cpp \
gui/item_amount.h \
gui/linkhandler.h \
@@ -80,8 +90,6 @@ tmw_SOURCES = gui/widgets/layout.cpp \
gui/npc_text.h \
gui/ok_dialog.cpp \
gui/ok_dialog.h \
- gui/truetypefont.cpp \
- gui/truetypefont.h \
gui/passwordfield.cpp \
gui/passwordfield.h \
gui/playerbox.cpp \
@@ -92,6 +100,8 @@ tmw_SOURCES = gui/widgets/layout.cpp \
gui/progressbar.h \
gui/radiobutton.cpp \
gui/radiobutton.h \
+ gui/recorder.cpp \
+ gui/recorder.h \
gui/register.cpp \
gui/register.h \
gui/scrollarea.cpp \
@@ -100,10 +110,12 @@ tmw_SOURCES = gui/widgets/layout.cpp \
gui/sdlinput.h \
gui/sell.cpp \
gui/sell.h \
- gui/setup_audio.cpp \
- gui/setup_audio.h \
gui/setup.cpp \
gui/setup.h \
+ gui/setup_audio.cpp \
+ gui/setup_audio.h \
+ gui/setup_colors.cpp \
+ gui/setup_colors.h \
gui/setup_joystick.cpp \
gui/setup_joystick.h \
gui/setup_keyboard.cpp \
@@ -117,22 +129,30 @@ tmw_SOURCES = gui/widgets/layout.cpp \
gui/shop.h \
gui/shoplistbox.cpp \
gui/shoplistbox.h \
+ gui/shortcutwindow.cpp \
+ gui/shortcutwindow.h \
+ gui/shortcutcontainer.cpp \
+ gui/shortcutcontainer.h \
gui/skill.cpp \
gui/skill.h \
gui/slider.cpp \
gui/slider.h \
+ gui/speechbubble.cpp \
+ gui/speechbubble.h \
gui/status.cpp \
gui/status.h \
- gui/table.h \
gui/table.cpp \
- gui/table_model.h \
+ gui/table.h \
gui/table_model.cpp \
+ gui/table_model.h \
gui/textbox.cpp \
gui/textbox.h \
gui/textfield.cpp \
gui/textfield.h \
gui/trade.cpp \
gui/trade.h \
+ gui/truetypefont.cpp \
+ gui/truetypefont.h \
gui/updatewindow.h \
gui/updatewindow.cpp \
gui/viewport.cpp \
@@ -169,6 +189,8 @@ tmw_SOURCES = gui/widgets/layout.cpp \
net/network.h \
net/npchandler.cpp \
net/npchandler.h \
+ net/partyhandler.cpp \
+ net/partyhandler.h \
net/playerhandler.cpp \
net/playerhandler.h \
net/protocol.cpp \
@@ -183,8 +205,14 @@ tmw_SOURCES = gui/widgets/layout.cpp \
resources/ambientoverlay.h \
resources/animation.cpp \
resources/animation.h \
+ resources/buddylist.cpp \
+ resources/buddylist.h \
+ resources/colordb.cpp \
+ resources/colordb.h \
resources/dye.cpp \
resources/dye.h \
+ resources/emotedb.cpp \
+ resources/emotedb.h \
resources/image.cpp \
resources/image.h \
resources/imageloader.cpp \
@@ -215,8 +243,6 @@ tmw_SOURCES = gui/widgets/layout.cpp \
resources/soundeffect.cpp \
resources/spritedef.h \
resources/spritedef.cpp \
- resources/buddylist.h \
- resources/buddylist.cpp \
utils/base64.cpp \
utils/base64.h \
utils/dtor.h \
@@ -240,6 +266,10 @@ tmw_SOURCES = gui/widgets/layout.cpp \
configlistener.h \
configuration.cpp \
configuration.h \
+ effectmanager.cpp \
+ effectmanager.h \
+ emoteshortcut.cpp \
+ emoteshortcut.h \
engine.cpp \
engine.h \
equipment.cpp \
@@ -283,11 +313,13 @@ tmw_SOURCES = gui/widgets/layout.cpp \
openglgraphics.h \
particle.cpp \
particle.h \
+ particlecontainer.cpp \
+ particlecontainer.h \
particleemitter.cpp \
particleemitter.h \
particleemitterprop.h \
- particlecontainer.cpp \
- particlecontainer.h \
+ party.cpp \
+ party.h \
player.cpp \
player.h \
player_relations.cpp \
@@ -318,5 +350,5 @@ tmw_SOURCES = gui/widgets/layout.cpp \
# set the include path found by configure
INCLUDES = \
$(all_includes) \
- -DTMW_DATADIR=\""$(pkgdatadir)/"\" \
+ -DPKG_DATADIR=\""$(pkgdatadir)/"\" \
-DLOCALEDIR=\""$(localedir)"\"
diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp
index 25a9df6c..aa2fb4ee 100644
--- a/src/animatedsprite.cpp
+++ b/src/animatedsprite.cpp
@@ -20,7 +20,6 @@
*/
#include "animatedsprite.h"
-
#include "graphics.h"
#include "log.h"
diff --git a/src/animationparticle.cpp b/src/animationparticle.cpp
index ca4f4d31..9c1f7ccb 100644
--- a/src/animationparticle.cpp
+++ b/src/animationparticle.cpp
@@ -20,7 +20,6 @@
*/
#include "animationparticle.h"
-
#include "graphics.h"
#include "simpleanimation.h"
diff --git a/src/being.cpp b/src/being.cpp
index 7036b8cd..0ccf675c 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -22,52 +22,68 @@
#include "being.h"
#include "animatedsprite.h"
-#include "equipment.h"
+#include "configuration.h"
+#include "effectmanager.h"
#include "game.h"
#include "graphics.h"
+#include "localplayer.h"
#include "log.h"
#include "map.h"
#include "particle.h"
#include "sound.h"
-#include "localplayer.h"
#include "text.h"
#include "statuseffect.h"
-#include "resources/itemdb.h"
-#include "resources/resourcemanager.h"
+#include "gui/speechbubble.h"
+
+#include "resources/colordb.h"
+
+#include "resources/emotedb.h"
+#include "resources/image.h"
#include "resources/imageset.h"
+#include "resources/itemdb.h"
#include "resources/iteminfo.h"
+#include "resources/resourcemanager.h"
#include "gui/gui.h"
+#include "gui/speechbubble.h"
#include "utils/dtor.h"
+#include "utils/gettext.h"
#include "utils/tostring.h"
-
+#include "utils/trim.h"
#include "utils/xml.h"
#include <cassert>
+#include <cmath>
#define BEING_EFFECTS_FILE "effects.xml"
#define HAIR_FILE "hair.xml"
int Being::instances = 0;
-ImageSet *Being::emotionSet = NULL;
+int Being::mNumberOfHairstyles = 1;
+std::vector<AnimatedSprite*> Being::emotionSet;
static const int X_SPEECH_OFFSET = 18;
static const int Y_SPEECH_OFFSET = 60;
+static const int DEFAULT_WIDTH = 32;
+static const int DEFAULT_HEIGHT = 32;
+
Being::Being(int id, int job, Map *map):
mJob(job),
mX(0), mY(0),
- mAction(0),
+ mAction(STAND),
mWalkTime(0),
mEmotion(0), mEmotionTime(0),
mAttackSpeed(350),
- mEquipment(new Equipment()),
mId(id),
mWalkSpeed(150),
mDirection(DOWN),
mMap(NULL),
+ mName(""),
+ mIsGM(false),
+ mParticleEffects(config.getValue("particleeffects", 1)),
mEquippedWeapon(NULL),
mHairStyle(1), mHairColor(0),
mGender(GENDER_UNSPECIFIED),
@@ -83,16 +99,33 @@ Being::Being(int id, int job, Map *map):
{
setMap(map);
+ mSpeechBubble = new SpeechBubble();
+
if (instances == 0)
{
- // Load the emotion set
- ResourceManager *rm = ResourceManager::getInstance();
- emotionSet = rm->getImageSet("graphics/gui/emotions.png", 30, 32);
- if (!emotionSet) logger->error("Unable to load emotions!");
+ // Setup emote sprites
+ for (int i = 0; i <= EmoteDB::getLast(); i++)
+ {
+ EmoteInfo info = EmoteDB::get(i);
+
+ std::string file = "graphics/sprites/" + info.sprites.front()->sprite;
+ int variant = info.sprites.front()->variant;
+ emotionSet.push_back(AnimatedSprite::load(file, variant));
+ }
+
+ // Hairstyles are encoded as negative numbers. Count how far negative we can go.
+ int hairstyles = 1;
+ while (ItemDB::get(-hairstyles).getSprite(GENDER_MALE) != "error.xml")
+ {
+ hairstyles++;
+ }
+ mNumberOfHairstyles = hairstyles;
}
instances++;
- mSpeech = 0;
+ mSpeech = "";
+ mNameColor = 0x202020;
+ mText = 0;
}
Being::~Being()
@@ -106,11 +139,11 @@ Being::~Being()
if (instances == 0)
{
- emotionSet->decRef();
- emotionSet = NULL;
+ delete_all(emotionSet);
}
- delete mSpeech;
+ delete mSpeechBubble;
+ delete mText;
}
void Being::setDestination(Uint16 destX, Uint16 destY)
@@ -139,8 +172,8 @@ void Being::setPath(const Path &path)
void Being::setHairStyle(int style, int color)
{
- mHairStyle = style < 0 ? mHairStyle : style % getHairStylesNr();
- mHairColor = color < 0 ? mHairColor : color % getHairColorsNr();
+ mHairStyle = style < 0 ? mHairStyle : style % mNumberOfHairstyles;
+ mHairColor = color < 0 ? mHairColor : color % ColorDB::size();
}
void Being::setSprite(int slot, int id, std::string color)
@@ -152,13 +185,44 @@ void Being::setSprite(int slot, int id, std::string color)
void Being::setSpeech(const std::string &text, Uint32 time)
{
- // don't introduce a memory leak
- delete mSpeech;
+ mSpeech = text;
+
+ // Trim whitespace
+ trim(mSpeech);
+
+ // check for links
+ std::string::size_type start = mSpeech.find('[');
+ std::string::size_type end = mSpeech.find(']', start);
+
+ while (start != std::string::npos && end != std::string::npos)
+ {
+ // Catch multiple embeds and ignore them so it doesn't crash the client.
+ while ((mSpeech.find('[', start + 1) != std::string::npos) &&
+ (mSpeech.find('[', start + 1) < end))
+ {
+ start = mSpeech.find('[', start + 1);
+ }
- mSpeech = new Text(text, mPx + X_SPEECH_OFFSET, mPy - Y_SPEECH_OFFSET,
- gcn::Graphics::CENTER,
- gcn::Color(255, 255, 255), true);
- mSpeechTime = 500;
+ std::string::size_type position = mSpeech.find('|');
+ if (mSpeech[start + 1] == '@' && mSpeech[start + 2] == '@')
+ {
+ mSpeech.erase(end, 1);
+ mSpeech.erase(start, (position - start) + 1);
+ }
+ position = mSpeech.find('@');
+
+ while (position != std::string::npos)
+ {
+ mSpeech.erase(position, 2);
+ position = mSpeech.find('@');
+ }
+
+ start = mSpeech.find('[', start + 1);
+ end = mSpeech.find(']', start);
+ }
+
+ if (!mSpeech.empty())
+ mSpeechTime = time <= SPEECH_MAX_TIME ? time : SPEECH_MAX_TIME;
}
void Being::takeDamage(int amount)
@@ -173,10 +237,6 @@ void Being::takeDamage(int amount)
}
else
{
- // Hit particle effect
- controlParticle(particleEngine->addEffect(
- "graphics/particles/hit.particle.xml", 0, 0));
-
if (getType() == MONSTER)
{
font = hitBlueFont;
@@ -192,6 +252,26 @@ void Being::takeDamage(int amount)
mPx + 16, mPy + 16);
}
+void Being::showCrit()
+{
+ gcn::Font *font;
+ std::string text = "crit!";
+
+ // Selecting the right color
+ if (getType() == MONSTER)
+ {
+ font = hitBlueFont;
+ }
+ else
+ {
+ font = hitRedFont;
+ }
+
+ // Show crit notice
+ particleEngine->addTextSplashEffect(text, 255, 255, 255, font,
+ mPx + 16, mPy + 16);
+}
+
void Being::handleAttack(Being *victim, int damage)
{
setAction(Being::ATTACK);
@@ -225,9 +305,10 @@ void Being::controlParticle(Particle *particle)
mChildParticleEffects.addLocally(particle);
}
-void Being::setAction(Uint8 action)
+void Being::setAction(Action action)
{
SpriteAction currentAction = ACTION_INVALID;
+
switch (action)
{
case WALK:
@@ -241,7 +322,8 @@ void Being::setAction(Uint8 action)
{
currentAction = mEquippedWeapon->getAttackType();
}
- else {
+ else
+ {
currentAction = ACTION_ATTACK;
}
for (int i = 0; i < VECTOREND_SPRITE; i++)
@@ -278,16 +360,18 @@ void Being::setAction(Uint8 action)
}
}
-
void Being::setDirection(Uint8 direction)
{
+ if (mDirection == direction)
+ return;
+
mDirection = direction;
SpriteDirection dir = getSpriteDirection();
for (int i = 0; i < VECTOREND_SPRITE; i++)
{
- if (mSprites[i] != NULL)
- mSprites[i]->setDirection(dir);
+ if (mSprites[i])
+ mSprites[i]->setDirection(dir);
}
}
@@ -307,8 +391,9 @@ SpriteDirection Being::getSpriteDirection() const
{
dir = DIRECTION_RIGHT;
}
- else {
- dir = DIRECTION_LEFT;
+ else
+ {
+ dir = DIRECTION_LEFT;
}
return dir;
@@ -352,28 +437,28 @@ void Being::nextStep()
void Being::logic()
{
// Reduce the time that speech is still displayed
- if (mSpeechTime > 0 && mSpeech)
+ if (mSpeechTime > 0)
+ mSpeechTime--;
+
+ // Remove text if speech boxes aren't being used
+ if (mSpeechTime == 0 && mText)
{
- if (--mSpeechTime == 0)
- {
- delete mSpeech;
- mSpeech = 0;
- }
+ delete mText;
+ mText = 0;
}
int oldPx = mPx;
int oldPy = mPy;
+
// Update pixel coordinates
mPx = mX * 32 + getXOffset();
mPy = mY * 32 + getYOffset();
+
if (mPx != oldPx || mPy != oldPy)
{
- if (mSpeech)
- {
- mSpeech->adviseXY(mPx + X_SPEECH_OFFSET, mPy - Y_SPEECH_OFFSET);
- }
updateCoords();
}
+
if (mEmotion != 0)
{
mEmotionTime--;
@@ -385,7 +470,7 @@ void Being::logic()
// Update sprite animations
for (int i = 0; i < VECTOREND_SPRITE; i++)
{
- if (mSprites[i] != NULL)
+ if (mSprites[i])
{
mSprites[i]->update(tick_time * 10);
}
@@ -415,7 +500,7 @@ void Being::draw(Graphics *graphics, int offsetX, int offsetY) const
for (int i = 0; i < VECTOREND_SPRITE; i++)
{
- if (mSprites[i] != NULL)
+ if (mSprites[i])
{
mSprites[i]->draw(graphics, px, py);
}
@@ -431,8 +516,47 @@ void Being::drawEmotion(Graphics *graphics, int offsetX, int offsetY)
const int py = mPy + offsetY - 60;
const int emotionIndex = mEmotion - 1;
- if (emotionIndex >= 0 && emotionIndex < (int) emotionSet->size())
- graphics->drawImage(emotionSet->get(emotionIndex), px, py);
+ if (emotionIndex >= 0 && emotionIndex <= EmoteDB::getLast())
+ emotionSet[emotionIndex]->draw(graphics, px, py);
+}
+
+void Being::drawSpeech(int offsetX, int offsetY)
+{
+ int px = mPx + offsetX;
+ int py = mPy + offsetY;
+
+ // Draw speech above this being
+ if (mSpeechTime > 0 && config.getValue("speechbubble", 1))
+ {
+ if (mText)
+ {
+ delete mText;
+ mText = 0;
+ }
+
+ mSpeechBubble->setCaption(mName, mNameColor);
+
+ // Not quite centered, but close enough. However, it's not too important to get
+ // it right right now, as it doesn't take bubble collision into account yet.
+ mSpeechBubble->setText(mSpeech);
+ mSpeechBubble->setPosition(px - (mSpeechBubble->getWidth() * 4 / 11), py - 70 -
+ (mSpeechBubble->getNumRows()*14));
+ mSpeechBubble->setVisible(true);
+ }
+ else if (mSpeechTime > 0 && !config.getValue("speechbubble", 1))
+ {
+ mSpeechBubble->setVisible(false);
+ // don't introduce a memory leak
+ if (mText)
+ delete mText;
+
+ mText = new Text(mSpeech, mPx + X_SPEECH_OFFSET, mPy - Y_SPEECH_OFFSET,
+ gcn::Graphics::CENTER, gcn::Color(255, 255, 255));
+ }
+ else if (mSpeechTime == 0)
+ {
+ mSpeechBubble->setVisible(false);
+ }
}
Being::Type Being::getType() const
@@ -455,9 +579,11 @@ void Being::handleStatusEffect(StatusEffect *effect, int effectId)
if (!effect)
return;
- SpriteAction action = effect->getAction();
- if (action != ACTION_INVALID)
- setAction(action);
+ // TODO: Find out how this is meant to be used
+ // (SpriteAction != Being::Action)
+ //SpriteAction action = effect->getAction();
+ //if (action != ACTION_INVALID)
+ // setAction(action);
Particle *particle = effect->getParticle();
@@ -497,7 +623,8 @@ void Being::setStatusEffect(int index, bool active)
int Being::getOffset(char pos, char neg) const
{
// Check whether we're walking in the requested direction
- if (mAction != WALK || !(mDirection & (pos | neg))) {
+ if (mAction != WALK || !(mDirection & (pos | neg)))
+ {
return 0;
}
@@ -505,27 +632,32 @@ int Being::getOffset(char pos, char neg) const
// We calculate the offset _from_ the _target_ location
offset -= 32;
- if (offset > 0) {
+ if (offset > 0)
+ {
offset = 0;
}
// Going into negative direction? Invert the offset.
- if (mDirection & pos) {
+ if (mDirection & pos)
+ {
offset = -offset;
}
return offset;
}
-
int Being::getWidth() const
{
if (mSprites[BASE_SPRITE])
{
- return mSprites[BASE_SPRITE]->getWidth();
+ const int width = mSprites[BASE_SPRITE]->getWidth() > DEFAULT_WIDTH ?
+ mSprites[BASE_SPRITE]->getWidth() :
+ DEFAULT_WIDTH;
+ return width;
}
- else {
- return 0;
+ else
+ {
+ return DEFAULT_WIDTH;
}
}
@@ -534,10 +666,14 @@ int Being::getHeight() const
{
if (mSprites[BASE_SPRITE])
{
- return mSprites[BASE_SPRITE]->getHeight();
+ const int height = mSprites[BASE_SPRITE]->getHeight() > DEFAULT_HEIGHT ?
+ mSprites[BASE_SPRITE]->getHeight() :
+ DEFAULT_HEIGHT;
+ return height;
}
- else {
- return 0;
+ else
+ {
+ return DEFAULT_HEIGHT;
}
}
@@ -620,14 +756,14 @@ void Being::internalTriggerEffect(int effectId, bool sfx, bool gfx)
return;
}
- if (gfx && ed->mGFXEffect != "") {
+ if (gfx && !ed->mGFXEffect.empty()) {
Particle *selfFX;
selfFX = particleEngine->addEffect(ed->mGFXEffect, 0, 0);
controlParticle(selfFX);
}
- if (sfx && ed->mSFXEffect != "") {
+ if (sfx && !ed->mSFXEffect.empty()) {
sound.playSfx(ed->mSFXEffect);
}
}
@@ -695,7 +831,7 @@ static void initializeHair()
int index = atoi(XML::getProperty(node, "id", "-1").c_str());
std::string value = XML::getProperty(node, "value", "");
- if (index >= 0 && value != "") {
+ if (index >= 0 && !value.empty()) {
if (index >= hairColorsNr) {
hairColorsNr = index + 1;
hairColors.resize(hairColorsNr, "#000000");
@@ -706,7 +842,7 @@ static void initializeHair()
}
} // done initializing
- if (hairColorsNr == 0) { // No colours -> black only
+ if (hairColorsNr == 0) { // No colors -> black only
hairColorsNr = 1;
hairColors.resize(hairColorsNr, "#000000");
}
diff --git a/src/being.h b/src/being.h
index 7d5ed989..3c3a9b73 100644
--- a/src/being.h
+++ b/src/being.h
@@ -22,34 +22,44 @@
#ifndef BEING_H
#define BEING_H
-#include <list>
-#include <memory>
-#include <string>
+#include <guichan/color.hpp>
+
#include <SDL_types.h>
+
#include <set>
+#include <string>
+#include <vector>
+#include "particlecontainer.h"
#include "position.h"
#include "sprite.h"
-#include "map.h"
-#include "animatedsprite.h"
-#include "particlecontainer.h"
+
+#include "resources/spritedef.h"
#define FIRST_IGNORE_EMOTE 14
#define STATUS_EFFECTS 32
+#define SPEECH_TIME 500
+#define SPEECH_MAX_TIME 1000
+
class AnimatedSprite;
-class Equipment;
+class Image;
class ItemInfo;
class Item;
class Map;
class Graphics;
-class ImageSet;
class Particle;
+class Position;
+class SpeechBubble;
class Text;
class StatusEffect;
-enum Gender {
+typedef std::list<Sprite*> Sprites;
+typedef Sprites::iterator SpriteIterator;
+
+enum Gender
+{
GENDER_MALE = 0,
GENDER_FEMALE = 1,
GENDER_UNSPECIFIED = 2
@@ -58,7 +68,8 @@ enum Gender {
class Being : public Sprite
{
public:
- enum Type {
+ enum Type
+ {
UNKNOWN,
PLAYER,
NPC,
@@ -68,7 +79,8 @@ class Being : public Sprite
/**
* Action the being is currently performing.
*/
- enum Action {
+ enum Action
+ {
STAND,
WALK,
ATTACK,
@@ -77,7 +89,8 @@ class Being : public Sprite
HURT
};
- enum Sprite {
+ enum Sprite
+ {
BASE_SPRITE = 0,
SHOE_SPRITE,
BOTTOMCLOTHES_SPRITE,
@@ -93,7 +106,8 @@ class Being : public Sprite
VECTOREND_SPRITE
};
- enum TargetCursorSize {
+ enum TargetCursorSize
+ {
TC_SMALL = 0,
TC_MEDIUM,
TC_LARGE,
@@ -107,13 +121,13 @@ class Being : public Sprite
Uint16 mJob; /**< Job (player job, npc, monster, ) */
Uint16 mX, mY; /**< Tile coordinates */
- Uint8 mAction; /**< Action the being is performing */
- Uint8 mFrame;
+ Action mAction; /**< Action the being is performing */
+ Uint16 mFrame;
Uint16 mWalkTime;
Uint8 mEmotion; /**< Currently showing emotion */
Uint8 mEmotionTime; /**< Time until emotion disappears */
- Uint16 mAttackSpeed; /**< Attack speed */
+ Uint16 mAttackSpeed; /**< Attack speed */
/**
* Constructor.
@@ -142,7 +156,7 @@ class Being : public Sprite
* @param text The text that should appear.
* @param time The amount of time the text should stay in milliseconds.
*/
- void setSpeech(const std::string &text, Uint32 time);
+ void setSpeech(const std::string &text, Uint32 time = 500);
/**
* Puts a damage bubble above this being.
@@ -152,6 +166,11 @@ class Being : public Sprite
virtual void takeDamage(int amount);
/**
+ * Puts a crit notification bubble above this being.
+ */
+ virtual void showCrit();
+
+ /**
* Handles an attack of another being by this being.
*
* @param victim The attacked being.
@@ -186,6 +205,11 @@ class Being : public Sprite
{ return mHairStyle; }
/**
+ * Get the number of hairstyles implemented
+ */
+ static int getNumOfHairstyles() { return mNumberOfHairstyles; }
+
+ /**
* Sets the hair style and color for this being.
*/
virtual void setHairStyle(int style, int color);
@@ -211,11 +235,24 @@ class Being : public Sprite
virtual void nextStep();
/**
+ * Triggers whether or not to show the name as a GM name.
+ * NOTE: This doesn't mean that just anyone can use this.
+ * If the server doesn't acknowlege you, you won't be shown
+ * as a GM on other people's clients.
+ */
+ virtual void setGM() { mIsGM = true; }
+
+ /**
* Performs being logic.
*/
virtual void logic();
/**
+ * Draws the speech text above the being.
+ */
+ void drawSpeech(int offsetX, int offsetY);
+
+ /**
* Draws the emotion picture above the being.
*/
void drawEmotion(Graphics *graphics, int offsetX, int offsetY);
@@ -253,7 +290,7 @@ class Being : public Sprite
/**
* Sets the current action.
*/
- virtual void setAction(Uint8 action);
+ virtual void setAction(Action action);
/**
* Returns the current direction.
@@ -266,6 +303,16 @@ class Being : public Sprite
void setDirection(Uint8 direction);
/**
+ * Gets the current action.
+ */
+ int getWalkTime() { return mWalkTime; }
+
+ /**
+ * Returns the direction the being is facing.
+ */
+ SpriteDirection getSpriteDirection() const;
+
+ /**
* Draws this being to the given graphics context.
*
* @see Sprite::draw(Graphics, int, int)
@@ -317,6 +364,8 @@ class Being : public Sprite
*/
void controlParticle(Particle *particle);
+ AnimatedSprite* getEmote(int index) { return emotionSet[index]; }
+
void setEmote(Uint8 emotion, Uint8 emote_time)
{
mEmotion = emotion;
@@ -356,8 +405,8 @@ class Being : public Sprite
internalTriggerEffect(effectId, false, true);
}
- const std::auto_ptr<Equipment> mEquipment;
-
+ // Target cursor being used by the being
+ Image *mTargetCursor;
static int getHairColorsNr();
@@ -365,6 +414,9 @@ class Being : public Sprite
static std::string getHairColor(int index);
+ virtual AnimatedSprite* getSprite(int index) const
+ { return mSprites[index]; }
+
protected:
/**
* Sets the new path for this being.
@@ -377,11 +429,6 @@ class Being : public Sprite
virtual void updateCoords() {}
/**
- * Returns the sprite direction of this being.
- */
- SpriteDirection getSpriteDirection() const;
-
- /**
* Trigger visual effect, with components
*
* \param effectId ID of the effect to trigger
@@ -416,12 +463,17 @@ class Being : public Sprite
Map *mMap; /**< Map on which this being resides */
std::string mName; /**< Name of character */
SpriteIterator mSpriteIterator;
+ bool mIsGM;
+ bool mParticleEffects; /**< Whether to display particles or not */
/** Engine-related infos about weapon. */
const ItemInfo* mEquippedWeapon;
+ static int mNumberOfHairstyles; /** Number of hair styles in use */
+
Path mPath;
- Text *mSpeech;
+ std::string mSpeech;
+ Text *mText;
Uint16 mHairStyle, mHairColor;
Gender mGender;
Uint32 mSpeechTime;
@@ -429,6 +481,8 @@ class Being : public Sprite
Uint16 mStunMode; /**< Stun mode; zero if not stunned */
std::set<int> mStatusEffects; /**< set of active status effects */
+ gcn::Color mNameColor;
+
std::vector<AnimatedSprite*> mSprites;
std::vector<int> mSpriteIDs;
std::vector<std::string> mSpriteColors;
@@ -443,9 +497,14 @@ class Being : public Sprite
*/
int getOffset(char pos, char neg) const;
- static int instances; /**< Number of Being instances */
- static ImageSet *emotionSet; /**< Emoticons used by beings */
- bool mMustResetParticles; /**< Reset particle status effects on next redraw? */
+ /** Reset particle status effects on next redraw? */
+ bool mMustResetParticles;
+
+ // Speech Bubble components
+ SpeechBubble *mSpeechBubble;
+
+ static int instances; /**< Number of Being instances */
+ static std::vector<AnimatedSprite*> emotionSet; /**< Emoticons used by beings */
};
#endif
diff --git a/src/beingmanager.cpp b/src/beingmanager.cpp
index 551820da..3c8edf86 100644
--- a/src/beingmanager.cpp
+++ b/src/beingmanager.cpp
@@ -31,6 +31,8 @@
#include "utils/dtor.h"
+#include <cassert>
+
class FindBeingFunctor
{
public:
@@ -128,12 +130,16 @@ Being* BeingManager::findBeingByPixel(Uint16 x, Uint16 y)
for (; itr != itr_end; ++itr)
{
Being *being = (*itr);
+
+ int xtol = being->getWidth();
+ int uptol = being->getHeight() / 2;
+
if ((being->mAction != Being::DEAD) &&
(being != player_node) &&
(being->getPixelX() <= x) &&
- (being->getPixelX() + being->getWidth() >= x) &&
- (being->getPixelY() <= y) &&
- (being->getPixelY() + being->getHeight() >= y))
+ (being->getPixelX() + xtol >= x) &&
+ (being->getPixelY() - uptol <= y) &&
+ (being->getPixelY() + uptol >= y))
{
return being;
}
@@ -155,8 +161,6 @@ Being* BeingManager::findBeingByName(std::string name, Being::Type type)
return NULL;
}
-
-
Beings& BeingManager::getAll()
{
return mBeings;
@@ -204,9 +208,12 @@ Being* BeingManager::findNearestLivingBeing(Uint16 x, Uint16 y, int maxdist,
Being *closestBeing = NULL;
int dist = 0;
- for (BeingIterator i = mBeings.begin(); i != mBeings.end(); i++)
+ BeingIterator itr = mBeings.begin();
+ BeingIterator itr_end = mBeings.end();
+
+ for (; itr != itr_end; ++itr)
{
- Being *being = (*i);
+ Being *being = (*itr);
int d = abs(being->mX - x) + abs(being->mY - y);
if ((being->getType() == type || type == Being::UNKNOWN)
diff --git a/src/beingmanager.h b/src/beingmanager.h
index 017de22e..11721709 100644
--- a/src/beingmanager.h
+++ b/src/beingmanager.h
@@ -49,7 +49,7 @@ class BeingManager
/**
* Create a being and add it to the list of beings.
*/
- Being* createBeing(Uint32 id, Uint16 job);
+ Being *createBeing(Uint32 id, Uint16 job);
/**
* Remove a Being.
@@ -60,33 +60,36 @@ class BeingManager
* Return a specific id Being.
*/
Being* findBeing(Uint32 id);
+ Being* findBeingByPixel(Uint16 x, Uint16 y);
/**
- * Return a being at specific coordinates.
+ * Returns a being at specific coordinates.
*/
Being* findBeing(Uint16 x, Uint16 y, Being::Type type = Being::UNKNOWN);
- Being* findBeingByPixel(Uint16 x, Uint16 y);
- /**
- * Return a being nearest to specific coordinates.
- *
- * \param maxdist maximal distance. If minimal distance is larger,
- * no being is returned
- */
+ /**
+ * Returns a being nearest to specific coordinates.
+ *
+ * @param x X coordinate.
+ * @param y Y coordinate.
+ * @param maxdist Maximal distance. If minimal distance is larger,
+ * no being is returned.
+ * @param type The type of being to look for.
+ */
Being* findNearestLivingBeing(Uint16 x, Uint16 y, int maxdist,
Being::Type type = Being::UNKNOWN);
- /**
- * Finds a being by name and (optionally) by type.
- */
+ /**
+ * Finds a being by name and (optionally) by type.
+ */
Being* findBeingByName(std::string name, Being::Type type = Being::UNKNOWN);
- /**
- * Return a being nearest to another being.
- *
- * \param maxdist maximal distance. If minimal distance is larger,
- * no being is returned
- */
+ /**
+ * Returns a being nearest to another being.
+ *
+ * \param maxdist maximal distance. If minimal distance is larger,
+ * no being is returned
+ */
Being* findNearestLivingBeing(Being *aroundBeing, int maxdist,
Being::Type type = Being::UNKNOWN);
diff --git a/src/configlistener.h b/src/configlistener.h
index 009a4830..ec7d6a2c 100644
--- a/src/configlistener.h
+++ b/src/configlistener.h
@@ -22,8 +22,7 @@
#ifndef CONFIGLISTENER_H
#define CONFIGLISTENER_H
-#include <iosfwd>
-
+#include <string>
/**
* The listener interface for receiving notifications about changes to
diff --git a/src/configuration.cpp b/src/configuration.cpp
index 04839777..6815ea03 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -19,12 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-
-#include "configuration.h"
-
-#include <libxml/xmlwriter.h>
-
#include "configlistener.h"
+#include "configuration.h"
#include "log.h"
#include "utils/tostring.h"
@@ -90,7 +86,6 @@ void ConfigurationObject::clear()
mOptions.clear();
}
-
ConfigurationObject::~ConfigurationObject()
{
clear();
@@ -193,7 +188,6 @@ void ConfigurationObject::writeToXML(xmlTextWriterPtr writer)
}
}
-
void Configuration::write()
{
// Do not attempt to write to file that cannot be opened for writing
diff --git a/src/configuration.h b/src/configuration.h
index 9f97e221..4d28008d 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -22,11 +22,12 @@
#ifndef CONFIGURATION_H
#define CONFIGURATION_H
-#include <map>
+#include <libxml/xmlwriter.h>
+
+#include <cassert>
#include <list>
+#include <map>
#include <string>
-#include <cassert>
-#include <libxml/xmlwriter.h>
class ConfigListener;
class ConfigurationObject;
diff --git a/src/effectmanager.cpp b/src/effectmanager.cpp
new file mode 100644
index 00000000..f004a450
--- /dev/null
+++ b/src/effectmanager.cpp
@@ -0,0 +1,104 @@
+/*
+ * An effects manager
+ * Copyright (C) 2008 Fate <fate.tmw@googlemail.com>
+ * Copyright (C) 2008 Chuck Miller <shadowmil@gmail.com>
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "being.h"
+#include "effectmanager.h"
+#include "log.h"
+#include "particle.h"
+#include "sound.h"
+
+#include "utils/xml.h"
+
+EffectManager::EffectManager()
+{
+ XML::Document doc("effects.xml");
+ xmlNodePtr root = doc.rootNode();
+
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "being-effects"))
+ {
+ logger->log("Error loading being effects file: effects.xml");
+ return;
+ }
+ else
+ {
+ logger->log("Effects are now loading");
+ }
+
+ for_each_xml_child_node(node, root)
+ {
+ //int id;
+
+ if (xmlStrEqual(node->name, BAD_CAST "effect"))
+ {
+ EffectDescription ed;
+ ed.id = XML::getProperty(node, "id", -1);
+ ed.GFX = XML::getProperty(node, "particle", "");
+ ed.SFX = XML::getProperty(node, "audio", "");
+ mEffects.push_back(ed);
+ }
+ }
+}
+
+EffectManager::~EffectManager()
+{
+
+}
+
+bool EffectManager::trigger(int id, Being* being)
+{
+ bool rValue = false;
+ for (std::list<EffectDescription>::iterator i = mEffects.begin(); i != mEffects.end(); ++i)
+ {
+ if ((*i).id == id)
+ {
+ rValue = true;
+ if (!(*i).GFX.empty())
+ {
+ Particle *selfFX;
+ selfFX = particleEngine->addEffect((*i).GFX, 0, 0);
+ being->controlParticle(selfFX);
+ }
+ if (!(*i).SFX.empty())
+ sound.playSfx((*i).SFX);
+ break;
+ }
+ }
+ return rValue;
+}
+
+bool EffectManager::trigger(int id, int x, int y)
+{
+ bool rValue = false;
+ for (std::list<EffectDescription>::iterator i = mEffects.begin(); i != mEffects.end(); ++i)
+ {
+ if ((*i).id == id)
+ {
+ rValue = true;
+ if (!(*i).GFX.empty())
+ particleEngine->addEffect((*i).GFX, x, y);
+ if (!(*i).SFX.empty())
+ sound.playSfx((*i).SFX);
+ break;
+ }
+ }
+ return rValue;
+}
diff --git a/src/effectmanager.h b/src/effectmanager.h
new file mode 100644
index 00000000..01c5a6b8
--- /dev/null
+++ b/src/effectmanager.h
@@ -0,0 +1,62 @@
+/*
+ * An effects manager
+ * Copyright (C) 2008 Fate <fate.tmw@googlemail.com>
+ * Copyright (C) 2008 Chuck Miller <shadowmil@gmail.com>
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EFFECT_MANAGER_H
+#define EFFECT_MANAGER_H
+
+#include <list>
+#include <string>
+
+class Being;
+
+class EffectManager
+{
+ public:
+ struct EffectDescription
+ {
+ int id;
+ std::string GFX;
+ std::string SFX;
+ };
+
+ EffectManager();
+ ~EffectManager();
+
+ /**
+ * Triggers a effect with the id, at
+ * the specified being.
+ */
+ bool trigger(int id, Being* being);
+
+ /**
+ * Triggers a effect with the id, at
+ * the specified x and y coordinate.
+ */
+ bool trigger(int id, int x, int y);
+
+ private:
+ std::list<EffectDescription> mEffects;
+};
+
+extern EffectManager *effectManager;
+
+#endif // EFFECT_MANAGER_H
diff --git a/src/emoteshortcut.cpp b/src/emoteshortcut.cpp
new file mode 100644
index 00000000..807fa3a2
--- /dev/null
+++ b/src/emoteshortcut.cpp
@@ -0,0 +1,77 @@
+/*
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "emoteshortcut.h"
+
+#include "configuration.h"
+#include "localplayer.h"
+
+#include "utils/tostring.h"
+
+EmoteShortcut::EmoteShortcut *emoteShortcut;
+
+EmoteShortcut::EmoteShortcut():
+ mEmoteSelected(0)
+{
+ for (int i = 0; i < SHORTCUT_EMOTES; i++)
+ {
+ mEmotes[i] = i + 1;
+ }
+ load();
+}
+
+EmoteShortcut::~EmoteShortcut()
+{
+ save();
+}
+
+void EmoteShortcut::load()
+{
+ for (int i = 0; i < SHORTCUT_EMOTES; i++)
+ {
+ int emoteId = (int) config.getValue("emoteshortcut" + toString(i), i + 1);
+
+ if (emoteId)
+ {
+ mEmotes[i] = emoteId;
+ }
+ }
+}
+
+void EmoteShortcut::save()
+{
+ for (int i = 0; i < SHORTCUT_EMOTES; i++)
+ {
+ const int emoteId = mEmotes[i] ? mEmotes[i] : 0;
+ config.setValue("emoteshortcut" + toString(i), emoteId);
+ }
+}
+
+void EmoteShortcut::useEmote(int index)
+{
+ if ((index > 0) && (index <= SHORTCUT_EMOTES))
+ {
+ if (mEmotes[index - 1] > 0)
+ {
+ player_node->emote(mEmotes[index - 1]);
+ }
+ }
+}
diff --git a/src/emoteshortcut.h b/src/emoteshortcut.h
new file mode 100644
index 00000000..ceb51a9b
--- /dev/null
+++ b/src/emoteshortcut.h
@@ -0,0 +1,125 @@
+/*
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EMOTESHORTCUT_H
+#define EMOTESHORTCUT_H
+
+#define SHORTCUT_EMOTES 12
+
+/**
+ * The class which keeps track of the emote shortcuts.
+ */
+class EmoteShortcut
+{
+ public:
+ /**
+ * Constructor.
+ */
+ EmoteShortcut();
+
+ /**
+ * Destructor.
+ */
+ ~EmoteShortcut();
+
+ /**
+ * Load the configuration information.
+ */
+ void load();
+
+ /**
+ * Returns the shortcut Emote ID specified by the index.
+ *
+ * @param index Index of the shortcut Emote.
+ */
+ int getEmote(int index) const
+ { return mEmotes[index]; }
+
+ /**
+ * Returns the amount of shortcut Emotes.
+ */
+ int getEmoteCount() const
+ { return SHORTCUT_EMOTES; }
+
+ /**
+ * Returns the emote ID that is currently selected.
+ */
+ int getEmoteSelected() const
+ { return mEmoteSelected; }
+
+ /**
+ * Adds the selected emote ID to the emotes specified by the index.
+ *
+ * @param index Index of the emotes.
+ */
+ void setEmote(int index)
+ { mEmotes[index] = mEmoteSelected; }
+
+ /**
+ * Adds a emoticon to the emotes store specified by the index.
+ *
+ * @param index Index of the emote.
+ * @param emoteId ID of the emote.
+ */
+ void setEmotes(int index, int emoteId)
+ { mEmotes[index] = emoteId; }
+
+ /**
+ * Set the Emote that is selected.
+ *
+ * @param emoteId The ID of the emote that is to be assigned.
+ */
+ void setEmoteSelected(int emoteId)
+ { mEmoteSelected = emoteId; }
+
+ /**
+ * A flag to check if the Emote is selected.
+ */
+ bool isEmoteSelected()
+ { return mEmoteSelected; }
+
+ /**
+ * Remove a Emote from the shortcut.
+ */
+ void removeEmote(int index)
+ { mEmotes[index] = 0; }
+
+ /**
+ * Try to use the Emote specified by the index.
+ *
+ * @param index Index of the emote shortcut.
+ */
+ void useEmote(int index);
+
+ private:
+ /**
+ * Save the configuration information.
+ */
+ void save();
+
+ int mEmotes[SHORTCUT_EMOTES]; /**< The emote stored. */
+ int mEmoteSelected; /**< The emote held by cursor. */
+
+};
+
+extern EmoteShortcut *emoteShortcut;
+
+#endif
diff --git a/src/engine.cpp b/src/engine.cpp
index 7a76e1b0..39b9b3ec 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -19,19 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "engine.h"
-
-#include <list>
-
-#include "being.h"
#include "beingmanager.h"
-#include "configuration.h"
+#include "engine.h"
#include "flooritemmanager.h"
#include "game.h"
-#include "graphics.h"
#include "localplayer.h"
#include "log.h"
-#include "main.h"
#include "map.h"
#include "particle.h"
#include "sound.h"
@@ -44,14 +37,10 @@
#include "net/protocol.h"
#include "resources/mapreader.h"
-#include "resources/monsterdb.h"
#include "resources/resourcemanager.h"
-#include "utils/dtor.h"
#include "utils/tostring.h"
-extern Minimap *minimap;
-
char itemCurrenyQ[10] = "0";
Engine::Engine(Network *network):
@@ -82,28 +71,40 @@ void Engine::changeMap(const std::string &mapPath)
map_path = "maps/" + mapPath.substr(0, mapPath.rfind(".")) + ".tmx";
ResourceManager *resman = ResourceManager::getInstance();
if (!resman->exists(map_path))
- {
map_path += ".gz";
- }
// Attempt to load the new map
Map *newMap = MapReader::readMap(map_path);
- if (!newMap) {
+ if (!newMap)
logger->error("Could not find map file");
- }
// Notify the minimap and beingManager about the map change
Image *mapImage = NULL;
if (newMap->hasProperty("minimap"))
{
mapImage = resman->getImage(newMap->getProperty("minimap"));
- }
- if (newMap->hasProperty("name"))
- {
- minimap->setCaption(newMap->getProperty("name"));
- } else {
- minimap->setCaption("Map");
+
+ // Set the title for the Minimap
+ if (newMap->hasProperty("mapname"))
+ minimap->setCaption(newMap->getProperty("mapname"));
+ else if (newMap->hasProperty("name"))
+ minimap->setCaption(newMap->getProperty("name"));
+ else
+ {
+ minimap->setCaption("Unknown");
+ logger->log("WARNING: Map file '%s' defines a minimap image but "
+ "does not define a 'mapname' property",
+ map_path.c_str());
+ }
+
+ // How many pixels equal one tile. .5 (which is the TMW default) is
+ // 2 tiles to a pixel, while 1 is 1 tile to 1 pixel
+ if (newMap->hasProperty("minimapproportion"))
+ minimap->setProportion(atof(
+ newMap->getProperty("minimapproportion").c_str()));
+ else
+ minimap->setProportion(0.5);
}
minimap->setMapImage(mapImage);
beingManager->setMap(newMap);
@@ -116,16 +117,16 @@ void Engine::changeMap(const std::string &mapPath)
// Start playing new music file when necessary
std::string oldMusic = "";
- if (mCurrentMap) {
+ if (mCurrentMap)
+ {
oldMusic = mCurrentMap->getProperty("music");
delete mCurrentMap;
}
std::string newMusic = newMap->getProperty("music");
- if (newMusic != oldMusic) {
+ if (newMusic != oldMusic)
sound.playMusic(newMusic, -1);
- }
mCurrentMap = newMap;
mMapName = mapPath;
diff --git a/src/engine.h b/src/engine.h
index f2852351..7ad6d894 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -22,7 +22,6 @@
#ifndef _ENGINE_H
#define _ENGINE_H
-#include <iosfwd>
#include <string>
class Map;
@@ -52,7 +51,6 @@ class Engine
const std::string &getCurrentMapName() { return mMapName; }
-
/**
* Sets the currently active map.
*/
diff --git a/src/equipment.cpp b/src/equipment.cpp
index b93beed4..cb7acd44 100644
--- a/src/equipment.cpp
+++ b/src/equipment.cpp
@@ -24,19 +24,16 @@
#include "inventory.h"
#include "localplayer.h"
-#include <algorithm>
-
Equipment::Equipment():
mArrows(0)
{
std::fill_n(mEquipment, EQUIPMENT_SIZE, 0);
}
-void
-Equipment::setEquipment(int index, int inventoryIndex)
+void Equipment::setEquipment(int index, int inventoryIndex)
{
mEquipment[index] = inventoryIndex;
Item* item = player_node->getInventory()->getItem(inventoryIndex);
if (item)
- item->setEquipped(true);
+ item->setEquipped(true);
}
diff --git a/src/floor_item.cpp b/src/floor_item.cpp
index e96b3652..fbe606b4 100644
--- a/src/floor_item.cpp
+++ b/src/floor_item.cpp
@@ -20,9 +20,12 @@
*/
#include "floor_item.h"
-
+#include "graphics.h"
+#include "item.h"
#include "map.h"
+#include "resources/image.h"
+
FloorItem::FloorItem(unsigned int id,
unsigned int itemId,
unsigned short x,
@@ -47,3 +50,15 @@ FloorItem::~FloorItem()
delete mItem;
}
+
+unsigned int FloorItem::getItemId() const
+{
+ return mItem->getId();
+}
+
+void FloorItem::draw(Graphics *graphics, int offsetX, int offsetY) const
+{
+ graphics->drawImage(mItem->getImage(),
+ mX * 32 + offsetX,
+ mY * 32 + offsetY);
+}
diff --git a/src/floor_item.h b/src/floor_item.h
index e0a67eca..444c756a 100644
--- a/src/floor_item.h
+++ b/src/floor_item.h
@@ -22,11 +22,16 @@
#ifndef FLOORITEM_H
#define FLOORITEM_H
-#include "graphics.h"
-#include "item.h"
-#include "map.h"
+#include <list>
+
#include "sprite.h"
-#include "resources/image.h"
+
+class Graphics;
+class Image;
+class Item;
+class Map;
+
+typedef std::list<Sprite*> Sprites;
/**
* An item lying on the floor.
@@ -51,47 +56,36 @@ class FloorItem : public Sprite
/**
* Returns instance id of this item.
*/
- unsigned int
- getId() const { return mId; }
+ unsigned int getId() const { return mId; }
/**
* Returns the item id.
*/
- unsigned int
- getItemId() const { return mItem->getId(); }
+ unsigned int getItemId() const;
/**
* Returns the x coordinate.
*/
- unsigned short
- getX() const { return mX; }
+ unsigned short getX() const { return mX; }
/**
* Returns the y coordinate.
*/
- unsigned short
- getY() const { return mY; }
+ unsigned short getY() const { return mY; }
/**
* Returns the pixel y coordinate.
*
* @see Sprite::getPixelY()
*/
- int
- getPixelY() const { return mY * 32; }
+ int getPixelY() const { return mY * 32; }
/**
* Draws this floor item to the given graphics context.
*
* @see Sprite::draw(Graphics, int, int)
*/
- void
- draw(Graphics *graphics, int offsetX, int offsetY) const
- {
- graphics->drawImage(mItem->getImage(),
- mX * 32 + offsetX,
- mY * 32 + offsetY);
- }
+ void draw(Graphics *graphics, int offsetX, int offsetY) const;
private:
unsigned int mId;
diff --git a/src/flooritemmanager.cpp b/src/flooritemmanager.cpp
index 836bbe8d..65556abb 100644
--- a/src/flooritemmanager.cpp
+++ b/src/flooritemmanager.cpp
@@ -19,9 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "flooritemmanager.h"
-
#include "floor_item.h"
+#include "flooritemmanager.h"
#include "utils/dtor.h"
diff --git a/src/game.cpp b/src/game.cpp
index 1c4bb538..5b701fc1 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -19,8 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "game.h"
-
#include <fstream>
#include <physfs.h>
#include <sstream>
@@ -30,8 +28,11 @@
#include "beingmanager.h"
#include "configuration.h"
+#include "effectmanager.h"
+#include "emoteshortcut.h"
#include "engine.h"
#include "flooritemmanager.h"
+#include "game.h"
#include "graphics.h"
#include "itemshortcut.h"
#include "joystick.h"
@@ -47,11 +48,14 @@
#include "gui/chat.h"
#include "gui/confirm_dialog.h"
#include "gui/debugwindow.h"
+#include "gui/emoteshortcutcontainer.h"
+#include "gui/emotewindow.h"
#include "gui/equipmentwindow.h"
#include "gui/gui.h"
#include "gui/help.h"
#include "gui/inventorywindow.h"
-#include "gui/itemshortcutwindow.h"
+#include "gui/shortcutwindow.h"
+#include "gui/itemshortcutcontainer.h"
#include "gui/menuwindow.h"
#include "gui/minimap.h"
#include "gui/ministatus.h"
@@ -68,23 +72,23 @@
#include "gui/trade.h"
#include "gui/viewport.h"
-#include "net/protocol.h"
#include "net/beinghandler.h"
#include "net/buysellhandler.h"
#include "net/chathandler.h"
#include "net/equipmenthandler.h"
#include "net/inventoryhandler.h"
#include "net/itemhandler.h"
+#include "net/messageout.h"
#include "net/network.h"
#include "net/npchandler.h"
#include "net/playerhandler.h"
+#include "net/protocol.h"
#include "net/skillhandler.h"
#include "net/tradehandler.h"
-#include "net/messageout.h"
#include "resources/imagewriter.h"
-extern Graphics *graphics;
+#include "utils/gettext.h"
class Map;
@@ -93,6 +97,7 @@ std::string map_path;
bool done = false;
volatile int tick_time;
volatile int fps = 0, frame = 0;
+
Engine *engine = NULL;
Joystick *joystick = NULL;
@@ -109,6 +114,7 @@ BuyDialog *buyDialog;
SellDialog *sellDialog;
BuySellDialog *buySellDialog;
InventoryWindow *inventoryWindow;
+EmoteWindow *emoteWindow;
NpcIntegerDialog *npcIntegerDialog;
NpcListDialog *npcListDialog;
NpcTextDialog *npcTextDialog;
@@ -118,19 +124,20 @@ Setup* setupWindow;
Minimap *minimap;
EquipmentWindow *equipmentWindow;
TradeWindow *tradeWindow;
-//BuddyWindow *buddyWindow;
HelpWindow *helpWindow;
DebugWindow *debugWindow;
-ItemShortcutWindow *itemShortcutWindow;
+ShortcutWindow *itemShortcutWindow;
+ShortcutWindow *emoteShortcutWindow;
BeingManager *beingManager = NULL;
FloorItemManager *floorItemManager = NULL;
Particle* particleEngine = NULL;
+EffectManager *effectManager = NULL;
const int MAX_TIME = 10000;
/**
- * Listener used for exitting handling.
+ * Listener used for exiting handling.
*/
namespace {
struct ExitListener : public gcn::ActionListener
@@ -163,15 +170,18 @@ Uint32 nextSecond(Uint32 interval, void *param)
{
fps = frame;
frame = 0;
+
return interval;
}
int get_elapsed_time(int start_time)
{
- if (start_time <= tick_time) {
+ if (start_time <= tick_time)
+ {
return (tick_time - start_time) * 10;
}
- else {
+ else
+ {
return (tick_time + (MAX_TIME - start_time)) * 10;
}
}
@@ -190,6 +200,7 @@ void createGuiWindows(Network *network)
sellDialog = new SellDialog(network);
buySellDialog = new BuySellDialog();
inventoryWindow = new InventoryWindow();
+ emoteWindow = new EmoteWindow();
npcTextDialog = new NpcTextDialog();
npcIntegerDialog = new NpcIntegerDialog();
npcListDialog = new NpcListDialog();
@@ -197,22 +208,18 @@ void createGuiWindows(Network *network)
skillDialog = new SkillDialog();
setupWindow = new Setup();
minimap = new Minimap();
- equipmentWindow = new EquipmentWindow(player_node->mEquipment.get());
+ equipmentWindow = new EquipmentWindow();
tradeWindow = new TradeWindow(network);
- //buddyWindow = new BuddyWindow();
helpWindow = new HelpWindow();
debugWindow = new DebugWindow();
- itemShortcutWindow = new ItemShortcutWindow();
-
- // Initialize window positions
- //buddyWindow->setPosition(10, minimap->getHeight() + 30);
+ itemShortcutWindow = new ShortcutWindow("ItemShortcut",new ItemShortcutContainer);
+ emoteShortcutWindow = new ShortcutWindow("emoteShortcut",new EmoteShortcutContainer);
// Set initial window visibility
chatWindow->setVisible((bool) config.getValue(
chatWindow->getWindowName() + "Visible", true));
miniStatusWindow->setVisible((bool) config.getValue(
- miniStatusWindow->getWindowName() + "Visible",
- true));
+ miniStatusWindow->getWindowName() + "Visible", true));
buyDialog->setVisible(false);
sellDialog->setVisible(false);
minimap->setVisible((bool) config.getValue(
@@ -222,11 +229,10 @@ void createGuiWindows(Network *network)
menuWindow->getWindowName() + "Visible", true));
itemShortcutWindow->setVisible((bool) config.getValue(
itemShortcutWindow->getWindowName() + "Visible", true));
-
- if (config.getValue("logToChat", 0))
- {
- logger->setChatWindow(chatWindow);
- }
+ emoteShortcutWindow->setVisible((bool) config.getValue(
+ emoteShortcutWindow->getWindowName() + "Visible", true));
+ minimap->setVisible((bool) config.getValue(
+ minimap->getWindowName() + "Visible", true));
}
/**
@@ -243,6 +249,7 @@ void destroyGuiWindows()
delete sellDialog;
delete buySellDialog;
delete inventoryWindow;
+ delete emoteWindow;
delete npcIntegerDialog;
delete npcListDialog;
delete npcTextDialog;
@@ -252,10 +259,10 @@ void destroyGuiWindows()
delete minimap;
delete equipmentWindow;
delete tradeWindow;
- //delete buddyWindow;
delete helpWindow;
delete debugWindow;
delete itemShortcutWindow;
+ delete emoteShortcutWindow;
}
Game::Game(Network *network):
@@ -276,6 +283,8 @@ Game::Game(Network *network):
beingManager = new BeingManager(network);
floorItemManager = new FloorItemManager();
+ effectManager = new EffectManager();
+
particleEngine = new Particle(NULL);
particleEngine->setupEngine();
@@ -310,17 +319,13 @@ Game::Game(Network *network):
network->registerHandler(mTradeHandler.get());
/*
- * THIS IS A TEMPORARY WORKAROUND!
- *
- * To prevent the server from sending data before the client has
- * initialized, it's been modified to wait for a "ping" from the client to
- * complete its initialization.
- *
- * The real fix is to make sure we are not throwing away messages in the
- * network buffer due to not having registered the handlers above straight
- * after receiving a login success from the map server.
+ * To prevent the server from sending data before the client
+ * has initialized, I've modified it to wait for a "ping"
+ * from the client to complete its initialization
*
- * The response from eAthena on this packet is ignored by the client.
+ * Note: This only affects the latest eAthena version. This
+ * packet is handled by the older version, but its response
+ * is ignored by the client
*/
MessageOut msg(mNetwork);
msg.writeInt16(CMSG_CLIENT_PING);
@@ -379,12 +384,12 @@ static bool saveScreenshot()
if (success)
{
std::stringstream chatlogentry;
- chatlogentry << "Screenshot saved to ~/" << filenameSuffix.str();
+ chatlogentry << _("Screenshot saved to ~/") << filenameSuffix.str();
chatWindow->chatLog(chatlogentry.str(), BY_SERVER);
}
else
{
- chatWindow->chatLog("Saving screenshot failed!", BY_SERVER);
+ chatWindow->chatLog(_("Saving screenshot failed!"), BY_SERVER);
logger->log("Error: could not save screenshot.");
}
@@ -430,7 +435,7 @@ void Game::logic()
// Draw a frame if either frames are not limited or enough time has
// passed since the last frame.
if (!mMinFrameTime ||
- get_elapsed_time(mDrawTime / 10) > mMinFrameTime)
+ get_elapsed_time(mDrawTime / 10) > mMinFrameTime)
{
frame++;
gui->draw();
@@ -460,9 +465,9 @@ void Game::logic()
{
if (!disconnectedDialog)
{
- disconnectedDialog = new OkDialog("Network Error",
- "The connection to the server was lost, "
- "the program will now quit");
+ disconnectedDialog = new OkDialog(_("Network Error"),
+ _("The connection to the server was lost, "
+ "the program will now quit"));
disconnectedDialog->addActionListener(&exitListener);
disconnectedDialog->requestMoveToTop();
}
@@ -487,114 +492,100 @@ void Game::handleInput()
gcn::Window *requestedWindow = NULL;
if (setupWindow->isVisible() &&
- keyboard.getNewKeyIndex() > keyboard.KEY_NO_VALUE)
+ keyboard.getNewKeyIndex() > keyboard.KEY_NO_VALUE)
{
keyboard.setNewKey((int) event.key.keysym.sym);
keyboard.callbackNewKey();
keyboard.setNewKeyIndex(keyboard.KEY_NO_VALUE);
return;
}
- // Keys pressed together with Alt/Meta
- // Emotions and some internal gui windows
- #ifndef __APPLE__
- if (event.key.keysym.mod & KMOD_LALT)
- #else
- if (event.key.keysym.mod & KMOD_LMETA)
- #endif
- {
- switch (event.key.keysym.sym)
- {
- case SDLK_p:
- // Screenshot (picture, hence the p)
- saveScreenshot();
- used = true;
- break;
-
- default:
- break;
-
- case SDLK_f:
- // Find path to mouse (debug purpose)
- viewport->toggleDebugPath();
- used = true;
- break;
-
- case SDLK_t:
- // Toggle accepting of incoming trade requests
- {
- unsigned int deflt = player_relations.getDefault();
- if (deflt & PlayerRelation::TRADE) {
- chatWindow->chatLog(
- "Ignoring incoming trade requests",
- BY_SERVER);
- deflt &= ~PlayerRelation::TRADE;
- } else {
- chatWindow->chatLog(
- "Accepting incoming trade requests",
- BY_SERVER);
- deflt |= PlayerRelation::TRADE;
- }
-
- player_relations.setDefault(deflt);
- }
- used = true;
- break;
- }
- }
- // Smilie
- if (keyboard.isKeyActive(keyboard.KEY_SMILIE))
+ // Mode switch to emotes
+ if (keyboard.isKeyActive(keyboard.KEY_EMOTE))
{
// Emotions
- Uint8 emotion;
- switch (event.key.keysym.sym)
- {
- case SDLK_1: emotion = 1; break;
- case SDLK_2: emotion = 2; break;
- case SDLK_3: emotion = 3; break;
- case SDLK_4: emotion = 4; break;
- case SDLK_5: emotion = 5; break;
- case SDLK_6: emotion = 6; break;
- case SDLK_7: emotion = 7; break;
- case SDLK_8: emotion = 8; break;
- case SDLK_9: emotion = 9; break;
- case SDLK_0: emotion = 10; break;
- case SDLK_MINUS: emotion = 11; break;
- case SDLK_EQUALS: emotion = 12; break;
- default: emotion = 0; break;
- }
-
+ int emotion = keyboard.getKeyEmoteOffset(event.key.keysym.sym);
if (emotion)
{
- player_node->emote(emotion);
+ emoteShortcut->useEmote(emotion);
used = true;
return;
}
}
- switch (event.key.keysym.sym)
+
+ if (keyboard.isKeyActive(keyboard.KEY_TOGGLE_CHAT) ||
+ keyboard.isKeyActive(keyboard.KEY_OK))
+ {
+ // Input chat window
+ if (!(chatWindow->isInputFocused() ||
+ deathNotice ||
+ weightNotice))
+ {
+ // Quit by pressing Enter if the exit confirm is there
+ if (exitConfirm &&
+ keyboard.isKeyActive(keyboard.KEY_TOGGLE_CHAT))
+ done = true;
+ // Close the Browser if opened
+ else if (helpWindow->isVisible() &&
+ keyboard.isKeyActive(keyboard.KEY_TOGGLE_CHAT))
+ helpWindow->setVisible(false);
+ // Close the config window, cancelling changes if opened
+ else if (setupWindow->isVisible() &&
+ keyboard.isKeyActive(keyboard.KEY_TOGGLE_CHAT))
+ setupWindow->action(gcn::ActionEvent(NULL, "cancel"));
+ // Submits the text and proceeds to the next dialog
+ else if (npcStringDialog->isVisible() &&
+ keyboard.isKeyActive(keyboard.KEY_OK))
+ npcStringDialog->action(gcn::ActionEvent(NULL, "ok"));
+ // Proceed to the next dialog option, or close the window
+ else if (npcTextDialog->isVisible() &&
+ keyboard.isKeyActive(keyboard.KEY_OK))
+ npcTextDialog->action(gcn::ActionEvent(NULL, "ok"));
+ // Choose the currently highlighted dialogue option
+ else if (npcListDialog->isVisible() &&
+ keyboard.isKeyActive(keyboard.KEY_OK))
+ npcListDialog->action(gcn::ActionEvent(NULL, "ok"));
+ // Submits the text and proceeds to the next dialog
+ else if (npcIntegerDialog->isVisible() &&
+ keyboard.isKeyActive(keyboard.KEY_OK))
+ npcIntegerDialog->action(gcn::ActionEvent(NULL, "ok"));
+ else if (!(keyboard.getKeyValue(
+ KeyboardConfig::KEY_TOGGLE_CHAT) ==
+ keyboard.getKeyValue(
+ KeyboardConfig::KEY_OK) &&
+ (npcStringDialog->isVisible() ||
+ npcTextDialog->isVisible() ||
+ npcListDialog->isVisible() ||
+ npcIntegerDialog->isVisible())))
+ {
+ chatWindow->requestChatFocus();
+ used = true;
+ }
+ }
+ }
+
+ const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
+ switch (tKey)
{
- case SDLK_PAGEUP:
+ case KeyboardConfig::KEY_SCROLL_CHAT_UP:
if (chatWindow->isVisible())
{
chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL);
used = true;
}
break;
-
- case SDLK_PAGEDOWN:
+ case KeyboardConfig::KEY_SCROLL_CHAT_DOWN:
if (chatWindow->isVisible())
{
chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL);
used = true;
+ return;
}
break;
-
- case SDLK_F1:
+ case KeyboardConfig::KEY_WINDOW_HELP:
// In-game Help
if (helpWindow->isVisible())
- {
helpWindow->setVisible(false);
- }
else
{
helpWindow->loadHelp("index");
@@ -602,95 +593,48 @@ void Game::handleInput()
}
used = true;
break;
-
- case SDLK_RETURN:
- // Input chat window
- if (chatWindow->isInputFocused() ||
- deathNotice != NULL ||
- weightNotice != NULL)
- {
- break;
- }
-
- // Quit by pressing Enter if the exit confirm is there
- if (exitConfirm)
+ // Quitting confirmation dialog
+ case KeyboardConfig::KEY_QUIT:
+ if (!exitConfirm)
{
- done = true;
- }
- // Close the Browser if opened
- else if (helpWindow->isVisible())
- {
- helpWindow->setVisible(false);
- }
- // Close the config window, cancelling changes if opened
- else if (setupWindow->isVisible())
- {
- setupWindow->action(gcn::ActionEvent(NULL, "cancel"));
- }
- // Submits the text and proceeds to the next dialog
- else if (npcStringDialog->isVisible())
- {
- npcStringDialog->action(gcn::ActionEvent(NULL, "ok"));
- }
- // Proceed to the next dialog option, or close the window
- else if (npcTextDialog->isVisible())
- {
- npcTextDialog->action(gcn::ActionEvent(NULL, "ok"));
- }
- // Choose the currently highlighted dialogue option
- else if (npcListDialog->isVisible())
- {
- npcListDialog->action(gcn::ActionEvent(NULL, "ok"));
- }
- // Submits the text and proceeds to the next dialog
- else if (npcIntegerDialog->isVisible())
- {
- npcIntegerDialog->action(gcn::ActionEvent(NULL, "ok"));
- }
- // Else, open the chat edit box
- else
- {
- chatWindow->requestChatFocus();
- used = true;
- }
- break;
- // Quitting confirmation dialog
- case SDLK_ESCAPE:
- if (!exitConfirm) {
- exitConfirm = new ConfirmDialog(
- "Quit", "Are you sure you want to quit?");
+ exitConfirm = new ConfirmDialog(_("Quit"),
+ _("Are you sure you "
+ "want to quit?"));
exitConfirm->addActionListener(&exitListener);
exitConfirm->requestMoveToTop();
}
else
{
- exitConfirm->action(gcn::ActionEvent(NULL, "no"));
+ exitConfirm->action(gcn::ActionEvent(NULL, _("no")));
}
break;
-
default:
break;
}
if (keyboard.isEnabled() && !chatWindow->isInputFocused()
- && !npcStringDialog->isInputFocused())
+ && !npcStringDialog->isInputFocused())
{
const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
+
// Do not activate shortcuts if tradewindow is visible
if (!tradeWindow->isVisible())
{
// Checks if any item shortcut is pressed.
- for (int i = KeyboardConfig::KEY_SHORTCUT_0;
- i <= KeyboardConfig::KEY_SHORTCUT_9;
- i++)
+ for (int i = KeyboardConfig::KEY_SHORTCUT_1;
+ i <= KeyboardConfig::KEY_SHORTCUT_12;
+ i++)
{
- if (tKey == i && !used) {
+ if (tKey == i && !used)
+ {
itemShortcut->useItem(
- i - KeyboardConfig::KEY_SHORTCUT_0);
+ i - KeyboardConfig::KEY_SHORTCUT_1);
break;
}
}
}
- switch (tKey) {
+
+ switch (tKey)
+ {
case KeyboardConfig::KEY_PICKUP:
{
FloorItem *item =
@@ -699,7 +643,8 @@ void Game::handleInput()
// If none below the player, try the tile in front
// of the player
- if (!item) {
+ if (!item)
+ {
Uint16 x = player_node->mX;
Uint16 y = player_node->mY;
if (player_node->getDirection() & Being::UP)
@@ -727,11 +672,12 @@ void Game::handleInput()
used = true;
break;
case KeyboardConfig::KEY_HIDE_WINDOWS:
- // Hide certain windows
+ // Hide certain windows
if (!chatWindow->isInputFocused())
{
statusWindow->setVisible(false);
inventoryWindow->setVisible(false);
+ emoteWindow->setVisible(false);
skillDialog->setVisible(false);
setupWindow->setVisible(false);
equipmentWindow->setVisible(false);
@@ -739,7 +685,6 @@ void Game::handleInput()
debugWindow->setVisible(false);
}
break;
-
case KeyboardConfig::KEY_WINDOW_STATUS:
requestedWindow = statusWindow;
break;
@@ -753,6 +698,7 @@ void Game::handleInput()
requestedWindow = skillDialog;
break;
case KeyboardConfig::KEY_WINDOW_MINIMAP:
+ minimap->toggle();
requestedWindow = minimap;
break;
case KeyboardConfig::KEY_WINDOW_CHAT:
@@ -767,6 +713,44 @@ void Game::handleInput()
case KeyboardConfig::KEY_WINDOW_DEBUG:
requestedWindow = debugWindow;
break;
+ case KeyboardConfig::KEY_WINDOW_EMOTE:
+ requestedWindow = emoteWindow;
+ break;
+ case KeyboardConfig::KEY_WINDOW_EMOTE_SHORTCUT:
+ requestedWindow = emoteShortcutWindow;
+ break;
+ case KeyboardConfig::KEY_SCREENSHOT:
+ // Screenshot (picture, hence the p)
+ saveScreenshot();
+ used = true;
+ break;
+ case KeyboardConfig::KEY_PATHFIND:
+ // Find path to mouse (debug purpose)
+ viewport->toggleDebugPath();
+ used = true;
+ break;
+ case KeyboardConfig::KEY_TRADE:
+ // Toggle accepting of incoming trade requests
+ unsigned int deflt = player_relations.getDefault();
+ if (deflt & PlayerRelation::TRADE)
+ {
+ chatWindow->chatLog(
+ _("Ignoring incoming trade requests"),
+ BY_SERVER);
+ deflt &= ~PlayerRelation::TRADE;
+ }
+ else
+ {
+ chatWindow->chatLog(
+ _("Accepting incoming trade requests"),
+ BY_SERVER);
+ deflt |= PlayerRelation::TRADE;
+ }
+
+ player_relations.setDefault(deflt);
+
+ used = true;
+ break;
}
}
@@ -774,14 +758,10 @@ void Game::handleInput()
{
requestedWindow->setVisible(!requestedWindow->isVisible());
if (requestedWindow->isVisible())
- {
requestedWindow->requestMoveToTop();
- }
used = true;
}
-
}
-
// Quit event
else if (event.type == SDL_QUIT)
{
@@ -801,7 +781,6 @@ void Game::handleInput()
logger->log("Warning: guichan input exception: %s", err);
}
}
-
} // End while
// If the user is configuring the keys then don't respond.
@@ -810,8 +789,7 @@ void Game::handleInput()
// Moving player around
if (player_node->mAction != Being::DEAD &&
- current_npc == 0 &&
- !chatWindow->isInputFocused())
+ current_npc == 0 && !chatWindow->isInputFocused())
{
// Get the state of the keyboard keys
keyboard.refreshActiveKeys();
@@ -822,23 +800,23 @@ void Game::handleInput()
// Translate pressed keys to movement and direction
if (keyboard.isKeyActive(keyboard.KEY_MOVE_UP) ||
- (joystick && joystick->isUp()))
+ (joystick && joystick->isUp()))
{
direction |= Being::UP;
}
else if (keyboard.isKeyActive(keyboard.KEY_MOVE_DOWN) ||
- (joystick && joystick->isDown()))
+ (joystick && joystick->isDown()))
{
direction |= Being::DOWN;
}
if (keyboard.isKeyActive(keyboard.KEY_MOVE_LEFT) ||
- (joystick && joystick->isLeft()))
+ (joystick && joystick->isLeft()))
{
direction |= Being::LEFT;
}
else if (keyboard.isKeyActive(keyboard.KEY_MOVE_RIGHT) ||
- (joystick && joystick->isRight()))
+ (joystick && joystick->isRight()))
{
direction |= Being::RIGHT;
}
@@ -847,60 +825,92 @@ void Game::handleInput()
// Attacking monsters
if (keyboard.isKeyActive(keyboard.KEY_ATTACK) ||
- (joystick && joystick->buttonPressed(0)))
+ (joystick && joystick->buttonPressed(0)))
{
- Being *target = NULL;
- bool newTarget = keyboard.isKeyActive(keyboard.KEY_TARGET);
+ Being *target = beingManager->findNearestLivingBeing(x, y, 20,
+ Being::MONSTER);
+
+ bool newTarget = !keyboard.isKeyActive(keyboard.KEY_TARGET);
// A set target has highest priority
if (newTarget || !player_node->getTarget())
{
Uint16 targetX = x, targetY = y;
- if (player_node->getDirection() & Being::UP)
- targetY--;
- if (player_node->getDirection() & Being::DOWN)
- targetY++;
- if (player_node->getDirection() & Being::LEFT)
- targetX--;
- if (player_node->getDirection() & Being::RIGHT)
- targetX++;
+ switch (player_node->getSpriteDirection())
+ {
+ case DIRECTION_UP : --targetY; break;
+ case DIRECTION_DOWN : ++targetY; break;
+ case DIRECTION_LEFT : --targetX; break;
+ case DIRECTION_RIGHT: ++targetX; break;
+ default: break;
+ }
// Attack priorioty is: Monster, Player, auto target
- target = beingManager->findBeing(
- targetX, targetY, Being::MONSTER);
+ target = beingManager->findBeing(targetX, targetY, Being::MONSTER);
if (!target)
- target = beingManager->findBeing(
- targetX, targetY, Being::PLAYER);
+ target = beingManager->findBeing(targetX, targetY, Being::PLAYER);
}
player_node->attack(target, newTarget);
}
- // Target the nearest player
- if (keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER))
+ // Target the nearest player if 'q' is pressed
+ if ( keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER) &&
+ !keyboard.isKeyActive(keyboard.KEY_TARGET) )
{
- Being *target = beingManager->findNearestLivingBeing(
- player_node, 20, Being::PLAYER);
+ Being *target = beingManager->findNearestLivingBeing(player_node, 20, Being::PLAYER);
- if (target)
- {
- player_node->setTarget(target);
- }
+ player_node->setTarget(target);
}
- // Target the nearest monster
- if (keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST)
- || (joystick && joystick->buttonPressed(3)))
+ // Target the nearest monster if 'a' pressed
+ if ((keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) ||
+ (joystick && joystick->buttonPressed(3))) &&
+ !keyboard.isKeyActive(keyboard.KEY_TARGET))
{
Being *target = beingManager->findNearestLivingBeing(
x, y, 20, Being::MONSTER);
- if (target)
+ player_node->setTarget(target);
+ }
+
+ // Target the nearest npc if 'n' pressed
+ if ( keyboard.isKeyActive(keyboard.KEY_TARGET_NPC) &&
+ !keyboard.isKeyActive(keyboard.KEY_TARGET) )
+ {
+ Being *target = beingManager->findNearestLivingBeing(
+ x, y, 20, Being::NPC);
+
+ player_node->setTarget(target);
+ }
+
+ // Talk to the nearest NPC if 't' pressed
+ if ( keyboard.isKeyActive(keyboard.KEY_TALK) )
+ {
+ if (!npcTextDialog->isVisible() && !npcListDialog->isVisible())
{
- player_node->setTarget(target);
+ Being *target = player_node->getTarget();
+
+ if (!target)
+ {
+ target = beingManager->findNearestLivingBeing(
+ x, y, 20, Being::NPC);
+ }
+
+ if (target)
+ {
+ if (target->getType() == Being::NPC)
+ dynamic_cast<NPC*>(target)->talk();
+ }
}
}
+ // Stop attacking if shift is pressed
+ if (keyboard.isKeyActive(keyboard.KEY_TARGET))
+ {
+ player_node->stopAttack();
+ }
+
if (joystick)
{
if (joystick->buttonPressed(1))
diff --git a/src/game.h b/src/game.h
index fd824a2a..d7d2a562 100644
--- a/src/game.h
+++ b/src/game.h
@@ -19,17 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef GAME_
-#define GAME_
+#ifndef GAME_H
+#define GAME_H
-#include <iosfwd>
#include <memory>
#include "configlistener.h"
-#define SPEECH_TIME 80
-#define SPEECH_MAX_TIME 100
-
class MessageHandler;
class Network;
diff --git a/src/graphics.cpp b/src/graphics.cpp
index bbe4221e..4af7b723 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -42,6 +42,8 @@ bool Graphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel)
logger->log("Setting video mode %dx%d %s",
w, h, fs ? "fullscreen" : "windowed");
+ logger->log("Bits per pixel: %d", bpp);
+
int displayFlags = SDL_ANYFORMAT;
mFullscreen = fs;
@@ -69,7 +71,7 @@ bool Graphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel)
logger->log("Using video driver: %s", videoDriverName);
}
else {
- logger->log("Using video driver: unkown");
+ logger->log("Using video driver: unknown");
}
const SDL_VideoInfo *vi = SDL_GetVideoInfo();
@@ -176,13 +178,12 @@ void Graphics::drawImagePattern(Image *image, int x, int y, int w, int h)
}
}
-void
-Graphics::drawImageRect(int x, int y, int w, int h,
- Image *topLeft, Image *topRight,
- Image *bottomLeft, Image *bottomRight,
- Image *top, Image *right,
- Image *bottom, Image *left,
- Image *center)
+void Graphics::drawImageRect(int x, int y, int w, int h,
+ Image *topLeft, Image *topRight,
+ Image *bottomLeft, Image *bottomRight,
+ Image *top, Image *right,
+ Image *bottom, Image *left,
+ Image *center)
{
pushClipArea(gcn::Rectangle(x, y, w, h));
@@ -220,9 +221,8 @@ Graphics::drawImageRect(int x, int y, int w, int h,
popClipArea();
}
-void
-Graphics::drawImageRect(int x, int y, int w, int h,
- const ImageRect &imgRect)
+void Graphics::drawImageRect(int x, int y, int w, int h,
+ const ImageRect &imgRect)
{
drawImageRect(x, y, w, h,
imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8],
diff --git a/src/graphics.h b/src/graphics.h
index 4a695a7a..172032dc 100644
--- a/src/graphics.h
+++ b/src/graphics.h
@@ -46,14 +46,16 @@ struct SDL_Surface;
* Sections 0, 2, 6 and 8 will remain as is. 1, 3, 4, 5 and 7 will be
* repeated to fit the size of the widget.
*/
-struct ImageRect {
+struct ImageRect
+{
Image *grid[9];
};
/**
* A central point of control for graphics.
*/
-class Graphics : public gcn::SDLGraphics {
+class Graphics : public gcn::SDLGraphics
+{
public:
/**
* Constructor.
@@ -95,17 +97,15 @@ class Graphics : public gcn::SDLGraphics {
* @return <code>true</code> if the image was blitted properly
* <code>false</code> otherwise.
*/
- virtual bool
- drawImage(Image *image,
- int srcX, int srcY,
- int dstX, int dstY,
- int width, int height,
- bool useColor = false);
-
- virtual void
- drawImagePattern(Image *image,
- int x, int y,
- int w, int h);
+ virtual bool drawImage(Image *image,
+ int srcX, int srcY,
+ int dstX, int dstY,
+ int width, int height,
+ bool useColor = false);
+
+ virtual void drawImagePattern(Image *image,
+ int x, int y,
+ int w, int h);
/**
* Draws a rectangle using images. 4 corner images, 4 side images and 1
@@ -153,4 +153,6 @@ class Graphics : public gcn::SDLGraphics {
bool mFullscreen, mHWAccel;
};
+extern Graphics *graphics;
+
#endif
diff --git a/src/gui/browserbox.cpp b/src/gui/browserbox.cpp
index 2d805b9c..a06b9a6e 100644
--- a/src/gui/browserbox.cpp
+++ b/src/gui/browserbox.cpp
@@ -21,15 +21,17 @@
#include <algorithm>
-#include "browserbox.h"
+#include <guichan/graphics.hpp>
+#include "browserbox.h"
+#include "color.h"
#include "linkhandler.h"
#include "truetypefont.h"
-BrowserBox::BrowserBox(unsigned int mode):
+BrowserBox::BrowserBox(unsigned int mode, bool opaque):
gcn::Widget(),
mMode(mode), mHighMode(UNDERLINE | BACKGROUND),
- mOpaque(true),
+ mOpaque(opaque),
mUseLinksAndUserColors(true),
mSelectedLink(-1),
mMaxRows(0)
@@ -98,12 +100,12 @@ void BrowserBox::addRow(const std::string &row)
mLinks.push_back(bLink);
- newRow += "##L" + bLink.caption;
+ newRow += "##<" + bLink.caption;
tmp.erase(0, idx3 + 2);
- if(tmp != "")
+ if (!tmp.empty())
{
- newRow += "##P";
+ newRow += "##>";
}
idx1 = tmp.find("@@");
}
@@ -122,7 +124,18 @@ void BrowserBox::addRow(const std::string &row)
//discard older rows when a row limit has been set
if (mMaxRows > 0)
{
- while (mTextRows.size() > mMaxRows) mTextRows.pop_front();
+ while (mTextRows.size() > mMaxRows)
+ {
+ mTextRows.pop_front();
+ for (unsigned int i = 0; i < mLinks.size(); i++)
+ {
+ mLinks[i].y1 -= font->getHeight();
+ mLinks[i].y2 -= font->getHeight();
+
+ if (mLinks[i].y1 < 0)
+ mLinks.erase(mLinks.begin() + i);
+ }
+ }
}
// Auto size mode
@@ -210,8 +223,7 @@ struct MouseOverLink
int mX, mY;
};
-void
-BrowserBox::mousePressed(gcn::MouseEvent &event)
+void BrowserBox::mousePressed(gcn::MouseEvent &event)
{
LinkIterator i = find_if(mLinks.begin(), mLinks.end(),
MouseOverLink(event.getX(), event.getY()));
@@ -221,8 +233,7 @@ BrowserBox::mousePressed(gcn::MouseEvent &event)
}
}
-void
-BrowserBox::mouseMoved(gcn::MouseEvent &event)
+void BrowserBox::mouseMoved(gcn::MouseEvent &event)
{
LinkIterator i = find_if(mLinks.begin(), mLinks.end(),
MouseOverLink(event.getX(), event.getY()));
@@ -230,8 +241,7 @@ BrowserBox::mouseMoved(gcn::MouseEvent &event)
mSelectedLink = (i != mLinks.end()) ? (i - mLinks.begin()) : -1;
}
-void
-BrowserBox::draw(gcn::Graphics *graphics)
+void BrowserBox::draw(gcn::Graphics *graphics)
{
if (mOpaque)
{
@@ -241,9 +251,10 @@ BrowserBox::draw(gcn::Graphics *graphics)
if (mSelectedLink >= 0)
{
+ bool valid;
if ((mHighMode & BACKGROUND))
{
- graphics->setColor(gcn::Color(HIGHLIGHT));
+ graphics->setColor(gcn::Color(textColor->getColor('H', valid)));
graphics->fillRectangle(gcn::Rectangle(
mLinks[mSelectedLink].x1,
mLinks[mSelectedLink].y1,
@@ -254,7 +265,7 @@ BrowserBox::draw(gcn::Graphics *graphics)
if ((mHighMode & UNDERLINE))
{
- graphics->setColor(gcn::Color(LINK));
+ graphics->setColor(gcn::Color(textColor->getColor('<', valid)));
graphics->drawLine(
mLinks[mSelectedLink].x1,
mLinks[mSelectedLink].y2,
@@ -265,6 +276,7 @@ BrowserBox::draw(gcn::Graphics *graphics)
int x = 0, y = 0;
int wrappedLines = 0;
+ int link = 0;
TrueTypeFont *font = static_cast<TrueTypeFont*>(getFont());
graphics->setColor(BLACK);
@@ -311,57 +323,36 @@ BrowserBox::draw(gcn::Graphics *graphics)
// Check for color change in format "##x", x = [L,P,0..9]
if (row.find("##", start) == start && row.size() > start + 2)
{
- switch (row.at(start + 2))
+ char c = row.at(start + 2);
+ if (c == '>')
{
- case 'L': // Link color
- prevColor = selColor;
- selColor = LINK;
- break;
- case 'P': // Previous color
- selColor = prevColor;
- break;
- case '1':
- prevColor = selColor;
- selColor = RED;
- break;
- case '2':
- prevColor = selColor;
- selColor = GREEN;
- break;
- case '3':
- prevColor = selColor;
- selColor = BLUE;
- break;
- case '4':
- prevColor = selColor;
- selColor = ORANGE;
- break;
- case '5':
- prevColor = selColor;
- selColor = YELLOW;
- break;
- case '6':
- prevColor = selColor;
- selColor = PINK;
- break;
- case '7':
- prevColor = selColor;
- selColor = PURPLE;
- break;
- case '8':
- prevColor = selColor;
- selColor = GRAY;
- break;
- case '9':
- prevColor = selColor;
- selColor = BROWN;
- break;
- case '0':
- default:
+ selColor = prevColor;
+ }
+ else
+ {
+ bool valid;
+ int rgb = textColor->getColor(c, valid);
+ if (c == '<')
+ {
+ const int size = mLinks[link].x2 - mLinks[link].x1;
+ mLinks[link].x1 = x;
+ mLinks[link].y1 = y;
+ mLinks[link].x2 = mLinks[link].x1 + size;
+ mLinks[link].y2 = y + font->getHeight();
+ link++;
prevColor = selColor;
- selColor = BLACK;
+ }
+ if (valid)
+ {
+ selColor = rgb;
+ }
}
start += 3;
+
+ if (start == row.size())
+ {
+ break;
+ }
}
graphics->setColor(gcn::Color(selColor));
}
@@ -424,3 +415,4 @@ BrowserBox::draw(gcn::Graphics *graphics)
setHeight((mTextRows.size() + wrappedLines) * font->getHeight());
}
}
+
diff --git a/src/gui/browserbox.h b/src/gui/browserbox.h
index 4dc41e3d..5dde402e 100644
--- a/src/gui/browserbox.h
+++ b/src/gui/browserbox.h
@@ -22,15 +22,12 @@
#ifndef BROWSERBOX_H
#define BROWSERBOX_H
-#include <iosfwd>
+#include <list>
#include <vector>
#include <guichan/mouselistener.hpp>
#include <guichan/widget.hpp>
-#include "../guichanfwd.h"
-#include "../main.h"
-
class LinkHandler;
struct BROWSER_LINK {
@@ -49,7 +46,7 @@ class BrowserBox : public gcn::Widget, public gcn::MouseListener
/**
* Constructor.
*/
- BrowserBox(unsigned int mode = AUTO_SIZE);
+ BrowserBox(unsigned int mode = AUTO_SIZE, bool opaque = true);
/**
* Destructor.
@@ -165,3 +162,4 @@ class BrowserBox : public gcn::Widget, public gcn::MouseListener
};
#endif
+
diff --git a/src/gui/buddywindow.cpp b/src/gui/buddywindow.cpp
deleted file mode 100644
index 0927ddf8..00000000
--- a/src/gui/buddywindow.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * The Mana World
- * Copyright (C) 2004 The Mana World Development Team
- *
- * This file is part of The Mana World.
- *
- * 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
- * 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; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "buddywindow.h"
-
-#include <guichan/widgets/listbox.hpp>
-
-#include "button.h"
-#include "chat.h"
-#include "scrollarea.h"
-
-#include "../resources/buddylist.h"
-
-extern ChatWindow *chatWindow;
-
-BuddyWindow::BuddyWindow():
- Window("Buddy")
-{
- setContentSize(124, 202);
-
- mBuddyList = new BuddyList();
-
- mListbox = new gcn::ListBox();
- mListbox->setListModel(mBuddyList);
-
- ScrollArea *scrollArea = new ScrollArea(mListbox);
- scrollArea->setDimension(gcn::Rectangle(
- 7, 5, 110, 170));
- add(scrollArea);
-
- Button *talk = new Button("Talk", "Talk", this);
- Button *remove = new Button("Remove", "Remove", this);
- Button *cancel = new Button("Cancel", "Cancel", this);
-
- talk->setPosition(2,180);
- remove->setPosition(talk->getWidth()+2,180);
- cancel->setPosition(talk->getWidth()+remove->getWidth()+2,180);
-
- add(talk);
- add(remove);
- add(cancel);
-}
-
-void BuddyWindow::action(const gcn::ActionEvent &event)
-{
- if (event.getId() == "Talk") {
- int selected = mListbox->getSelected();
- if ( selected > -1 )
- {
- std::string who = mBuddyList->getElementAt(selected);
- chatWindow->setInputText(who +": ");
- }
- }
- else if (event.getId() == "Remove") {
- int selected = mListbox->getSelected();
- if ( selected > -1 )
- {
- std::string who = mBuddyList->getElementAt(selected);
- mBuddyList->removeBuddy(who);
- }
- }
- else if (event.getId() == "Cancel") {
- setVisible(false);
- }
-}
diff --git a/src/gui/button.cpp b/src/gui/button.cpp
index caf93b94..1d3a04e4 100644
--- a/src/gui/button.cpp
+++ b/src/gui/button.cpp
@@ -19,8 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <guichan/exception.hpp>
+#include <guichan/font.hpp>
+
#include "button.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
@@ -28,13 +32,8 @@
#include "../utils/dtor.h"
-#include <guichan/exception.hpp>
-#include <guichan/graphics.hpp>
-#include <guichan/font.hpp>
-
-#include <algorithm>
-
int Button::mInstances = 0;
+float Button::mAlpha = config.getValue("guialpha", 0.8);
enum{
BUTTON_STANDARD, // 0
@@ -100,6 +99,7 @@ void Button::init()
data[x].gridX, data[y].gridY,
data[x + 1].gridX - data[x].gridX + 1,
data[y + 1].gridY - data[y].gridY + 1);
+ button[mode].grid[a]->setAlpha(mAlpha);
a++;
}
}
@@ -122,22 +122,29 @@ Button::~Button()
}
}
-void
-Button::draw(gcn::Graphics *graphics)
+void Button::draw(gcn::Graphics *graphics)
{
int mode;
- if (!isEnabled()) {
+ if (!isEnabled())
mode = BUTTON_DISABLED;
- }
- else if (isPressed() || mIsLogged) {
+ else if (isPressed() || mIsLogged)
mode = BUTTON_PRESSED;
- }
- else if (mHasMouse || isFocused()) {
+ else if (mHasMouse || isFocused())
mode = BUTTON_HIGHLIGHTED;
- }
- else {
+ else
mode = BUTTON_STANDARD;
+
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ for (int a = 0; a < 9; a++)
+ {
+ button[BUTTON_DISABLED].grid[a]->setAlpha(mAlpha);
+ button[BUTTON_PRESSED].grid[a]->setAlpha(mAlpha);
+ button[BUTTON_HIGHLIGHTED].grid[a]->setAlpha(mAlpha);
+ button[BUTTON_STANDARD].grid[a]->setAlpha(mAlpha);
+ }
}
static_cast<Graphics*>(graphics)->
@@ -148,7 +155,8 @@ Button::draw(gcn::Graphics *graphics)
int textX;
int textY = getHeight() / 2 - getFont()->getHeight() / 2;
- switch (getAlignment()) {
+ switch (getAlignment())
+ {
case gcn::Graphics::LEFT:
textX = 4;
break;
@@ -164,10 +172,8 @@ Button::draw(gcn::Graphics *graphics)
graphics->setFont(getFont());
- if (isPressed()) {
+ if (isPressed())
graphics->drawText(getCaption(), textX + 1, textY + 1, getAlignment());
- }
- else {
+ else
graphics->drawText(getCaption(), textX, textY, getAlignment());
- }
}
diff --git a/src/gui/button.h b/src/gui/button.h
index 0ec99245..abaf5c43 100644
--- a/src/gui/button.h
+++ b/src/gui/button.h
@@ -22,8 +22,6 @@
#ifndef BUTTON_H
#define BUTTON_H
-#include <iosfwd>
-
#include <guichan/widgets/button.hpp>
class ImageRect;
@@ -69,6 +67,7 @@ class Button : public gcn::Button
static ImageRect button[4]; /**< Button state graphics */
static int mInstances; /**< Number of button instances */
+ static float mAlpha;
bool mIsLogged; /**< Makes the button appear pressed all the time */
};
diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp
index 49dd52af..0c8c4d9d 100644
--- a/src/gui/buy.cpp
+++ b/src/gui/buy.cpp
@@ -19,11 +19,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "buy.h"
-
#include <guichan/widgets/label.hpp>
#include "button.h"
+#include "buy.h"
#include "scrollarea.h"
#include "shop.h"
#include "shoplistbox.h"
@@ -43,7 +42,7 @@ BuyDialog::BuyDialog(Network *network):
Window(_("Buy")), mNetwork(network),
mMoney(0), mAmountItems(0), mMaxItems(0)
{
- setWindowName("Buy");
+ setWindowName(_("Buy"));
setResizable(true);
setMinWidth(260);
setMinHeight(230);
diff --git a/src/gui/buy.h b/src/gui/buy.h
index 37a39890..0f1cfede 100644
--- a/src/gui/buy.h
+++ b/src/gui/buy.h
@@ -25,9 +25,9 @@
#include <guichan/actionlistener.hpp>
#include <guichan/selectionlistener.hpp>
-#include "window.h"
+#include <SDL_types.h>
-#include "../guichanfwd.h"
+#include "window.h"
class Network;
class ShopItems;
@@ -40,7 +40,7 @@ class ListBox;
* \ingroup Interface
*/
class BuyDialog : public Window, public gcn::ActionListener,
- gcn::SelectionListener
+ public gcn::SelectionListener
{
public:
/**
@@ -111,9 +111,9 @@ class BuyDialog : public Window, public gcn::ActionListener,
ShopItems *mShopItems;
- int mMoney;
- int mAmountItems;
- int mMaxItems;
+ Uint32 mMoney;
+ Uint32 mAmountItems;
+ Uint32 mMaxItems;
};
#endif
diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp
index cdab0855..d060db85 100644
--- a/src/gui/buysell.cpp
+++ b/src/gui/buysell.cpp
@@ -19,9 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "buysell.h"
-
#include "button.h"
+#include "buysell.h"
#include "../npc.h"
diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp
index df57f969..8de4f5a7 100644
--- a/src/gui/char_select.cpp
+++ b/src/gui/char_select.cpp
@@ -19,13 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "char_select.h"
-
#include <string>
+#include <guichan/font.hpp>
+
#include <guichan/widgets/label.hpp>
#include "button.h"
+#include "char_select.h"
#include "confirm_dialog.h"
#include "ok_dialog.h"
#include "playerbox.h"
@@ -40,6 +41,8 @@
#include "../net/charserverhandler.h"
#include "../net/messageout.h"
+#include "../resources/colordb.h"
+
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
#include "../utils/trim.h"
@@ -69,7 +72,8 @@ CharDeleteConfirm::CharDeleteConfirm(CharSelectDialog *m):
void CharDeleteConfirm::action(const gcn::ActionEvent &event)
{
//ConfirmDialog::action(event);
- if (event.getId() == "yes") {
+ if (event.getId() == "yes")
+ {
master->attemptCharDelete();
}
ConfirmDialog::action(event);
@@ -81,38 +85,42 @@ CharSelectDialog::CharSelectDialog(Network *network,
Window(_("Select Character")), mNetwork(network),
mCharInfo(charInfo), mGender(gender), mCharSelected(false)
{
- mSelectButton = new Button(_("Ok"), "ok", this);
- mCancelButton = new Button(_("Cancel"), "cancel", this);
- mNewCharButton = new Button(_("New"), "new", this);
- mDelCharButton = new Button(_("Delete"), "delete", this);
- mPreviousButton = new Button(_("Previous"), "previous", this);
- mNextButton = new Button(_("Next"), "next", this);
+ // Control that shows the Player
+ mPlayerBox = new PlayerBox;
+ mPlayerBox->setWidth(74);
mNameLabel = new gcn::Label(strprintf(_("Name: %s"), ""));
mLevelLabel = new gcn::Label(strprintf(_("Level: %d"), 0));
mJobLevelLabel = new gcn::Label(strprintf(_("Job Level: %d"), 0));
mMoneyLabel = new gcn::Label(strprintf(_("Money: %d"), 0));
- // Control that shows the Player
- mPlayerBox = new PlayerBox;
- mPlayerBox->setWidth(74);
+ const std::string tempString = getFont()->getWidth(_("New")) <
+ getFont()->getWidth(_("Delete")) ?
+ _("Delete") : _("New");
+
+ mPreviousButton = new Button(_("Previous"), "previous", this);
+ mNextButton = new Button(_("Next"), "next", this);
+ mNewDelCharButton = new Button(tempString, "newdel", this);
+ mSelectButton = new Button(_("Ok"), "ok", this);
+ mCancelButton = new Button(_("Cancel"), "cancel", this);
ContainerPlacer place;
place = getPlacer(0, 0);
+
place(0, 0, mPlayerBox, 1, 6).setPadding(3);
- place(1, 0, mNameLabel, 3);
- place(1, 1, mLevelLabel, 3);
- place(1, 2, mJobLevelLabel, 3);
- place(1, 3, mMoneyLabel, 3);
- place(1, 4, mPreviousButton);
- place(2, 4, mNextButton);
- place(1, 5, mNewCharButton);
- place(2, 5, mDelCharButton);
- place.getCell().matchColWidth(1, 2);
+ place(1, 0, mNewDelCharButton);
+ place(1, 1, mNameLabel, 5);
+ place(1, 2, mLevelLabel, 5);
+ place(1, 3, mJobLevelLabel, 5);
+ place(1, 4, mMoneyLabel, 5);
+ place.getCell().matchColWidth(1, 4);
place = getPlacer(0, 2);
- place(0, 0, mSelectButton);
- place(1, 0, mCancelButton);
- reflowLayout(265, 0);
+ place(0, 0, mPreviousButton);
+ place(1, 0, mNextButton);
+ place(4, 0, mCancelButton);
+ place(5, 0, mSelectButton);
+
+ reflowLayout(250, 0);
setLocationRelativeTo(getParent());
setVisible(true);
@@ -125,8 +133,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "ok" && n_character > 0)
{
// Start game
- mNewCharButton->setEnabled(false);
- mDelCharButton->setEnabled(false);
+ mNewDelCharButton->setEnabled(false);
mSelectButton->setEnabled(false);
mPreviousButton->setEnabled(false);
mNextButton->setEnabled(false);
@@ -137,20 +144,21 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
{
state = EXIT_STATE;
}
- else if (event.getId() == "new" && n_character <= MAX_SLOT)
+ else if (event.getId() == "newdel")
{
- // Start new character dialog
- CharCreateDialog *charCreateDialog =
- new CharCreateDialog(this, mCharInfo->getPos(), mNetwork, mGender);
- charServerHandler.setCharCreateDialog(charCreateDialog);
- }
- else if (event.getId() == "delete")
- {
- // Delete character
- if (mCharInfo->getEntry())
+ // Check for a character
+ if (mCharInfo->getEntry() && n_character <= MAX_SLOT )
{
new CharDeleteConfirm(this);
}
+ else
+ {
+ // Start new character dialog
+ CharCreateDialog *charCreateDialog =
+ new CharCreateDialog(this, mCharInfo->getPos(),
+ mNetwork, mGender);
+ charServerHandler.setCharCreateDialog(charCreateDialog);
+ }
}
else if (event.getId() == "previous")
{
@@ -174,18 +182,17 @@ void CharSelectDialog::updatePlayerInfo()
mMoneyLabel->setCaption(strprintf(_("Gold: %d"), pi->mGp));
if (!mCharSelected)
{
- mNewCharButton->setEnabled(false);
- mDelCharButton->setEnabled(true);
+ mNewDelCharButton->setCaption(_("Delete"));
mSelectButton->setEnabled(true);
}
}
- else {
+ else
+ {
mNameLabel->setCaption(strprintf(_("Name: %s"), ""));
mLevelLabel->setCaption(strprintf(_("Level: %d"), 0));
mJobLevelLabel->setCaption(strprintf(_("Job Level: %d"), 0));
mMoneyLabel->setCaption(strprintf(_("Money: %d"), 0));
- mNewCharButton->setEnabled(true);
- mDelCharButton->setEnabled(false);
+ mNewDelCharButton->setCaption(_("New"));
mSelectButton->setEnabled(false);
}
@@ -224,7 +231,8 @@ bool CharSelectDialog::selectByName(const std::string &name)
unsigned int oldPos = mCharInfo->getPos();
mCharInfo->select(0);
- do {
+ do
+ {
LocalPlayer *player = mCharInfo->getEntry();
if (player && player->getName() == name)
@@ -244,7 +252,10 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network,
{
mPlayer = new Player(0, 0, NULL);
mPlayer->setGender(gender);
- mPlayer->setHairStyle(rand() % Being::getHairStylesNr(), rand() % Being::getHairColorsNr());
+
+ int numberOfHairColors = ColorDB::size();
+
+ mPlayer->setHairStyle(rand() % mPlayer->getNumOfHairstyles(), rand() % numberOfHairColors);
mNameField = new TextField("");
mNameLabel = new gcn::Label(_("Name:"));
@@ -258,41 +269,29 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network,
mCancelButton = new Button(_("Cancel"), "cancel", this);
mPlayerBox = new PlayerBox(mPlayer);
+ mPlayerBox->setWidth(74);
+
mNameField->setActionEventId("create");
+ mNameField->addActionListener(this);
- int w = 200;
- int h = 150;
- setContentSize(w, h);
- mPlayerBox->setDimension(gcn::Rectangle(80, 30, 110, 85));
- mNameLabel->setPosition(5, 5);
- mNameField->setDimension(
- gcn::Rectangle(45, 5, w - 45 - 7, mNameField->getHeight()));
- mPrevHairColorButton->setPosition(90, 35);
- mNextHairColorButton->setPosition(165, 35);
- mHairColorLabel->setPosition(5, 40);
- mPrevHairStyleButton->setPosition(90, 64);
- mNextHairStyleButton->setPosition(165, 64);
- mHairStyleLabel->setPosition(5, 70);
- mCancelButton->setPosition(
- w - 5 - mCancelButton->getWidth(),
- h - 5 - mCancelButton->getHeight());
- mCreateButton->setPosition(
- mCancelButton->getX() - 5 - mCreateButton->getWidth(),
- h - 5 - mCancelButton->getHeight());
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
- mNameField->addActionListener(this);
+ place(0, 0, mNameLabel, 1);
+ place(1, 0, mNameField, 6);
+ place(0, 1, mHairStyleLabel, 1);
+ place(1, 1, mPrevHairStyleButton);
+ place(2, 1, mPlayerBox, 1, 8).setPadding(3);
+ place(3, 1, mNextHairStyleButton);
+ place(0, 2, mHairColorLabel, 1);
+ place(1, 2, mPrevHairColorButton);
+ place(3, 2, mNextHairColorButton);
+ place.getCell().matchColWidth(0, 2);
+ place = getPlacer(0, 2);
+ place(4, 0, mCancelButton);
+ place(5, 0, mCreateButton);
- add(mPlayerBox);
- add(mNameField);
- add(mNameLabel);
- add(mNextHairColorButton);
- add(mPrevHairColorButton);
- add(mHairColorLabel);
- add(mNextHairStyleButton);
- add(mPrevHairStyleButton);
- add(mHairStyleLabel);
- add(mCreateButton);
- add(mCancelButton);
+ reflowLayout(225, 0);
setLocationRelativeTo(getParent());
setVisible(true);
@@ -307,53 +306,54 @@ CharCreateDialog::~CharCreateDialog()
charServerHandler.setCharCreateDialog(0);
}
-void
-CharCreateDialog::action(const gcn::ActionEvent &event)
+void CharCreateDialog::action(const gcn::ActionEvent &event)
{
- if (event.getId() == "create") {
- if (getName().length() >= 4) {
+ int numberOfColors = ColorDB::size();
+ if (event.getId() == "create")
+ {
+ if (getName().length() >= 4)
+ {
// Attempt to create the character
mCreateButton->setEnabled(false);
attemptCharCreate();
}
- else {
+ else
+ {
new OkDialog("Error",
"Your name needs to be at least 4 characters.", this);
}
}
- else if (event.getId() == "cancel") {
+ else if (event.getId() == "cancel")
scheduleDelete();
- }
- else if (event.getId() == "nextcolor") {
- mPlayer->setHairStyle(-1, mPlayer->getHairColor() + 1);
- }
- else if (event.getId() == "prevcolor") {
- mPlayer->setHairStyle(-1, mPlayer->getHairColor() + Being::getHairColorsNr() - 1);
- }
- else if (event.getId() == "nextstyle") {
- mPlayer->setHairStyle(mPlayer->getHairStyle() + 1, -1);
- }
- else if (event.getId() == "prevstyle") {
- mPlayer->setHairStyle(mPlayer->getHairStyle() + Being::getHairStylesNr() - 1, -1);
- }
+ else if (event.getId() == "nextcolor")
+ mPlayer->setHairStyle(mPlayer->getHairStyle(),
+ (mPlayer->getHairColor() + 1) % numberOfColors);
+ else if (event.getId() == "prevcolor")
+ mPlayer->setHairStyle(mPlayer->getHairStyle(),
+ (mPlayer->getHairColor() + numberOfColors - 1) %
+ numberOfColors);
+ else if (event.getId() == "nextstyle")
+ mPlayer->setHairStyle(mPlayer->getHairStyle() + 1,
+ mPlayer->getHairColor());
+ else if (event.getId() == "prevstyle")
+ mPlayer->setHairStyle(mPlayer->getHairStyle() +
+ mPlayer->getNumOfHairstyles() - 1,
+ mPlayer->getHairColor());
}
-std::string
-CharCreateDialog::getName()
+std::string CharCreateDialog::getName()
{
std::string name = mNameField->getText();
trim(name);
return name;
}
-void
-CharCreateDialog::unlock()
+void CharCreateDialog::unlock()
{
mCreateButton->setEnabled(true);
}
-void
-CharCreateDialog::attemptCharCreate()
+void CharCreateDialog::attemptCharCreate()
{
// Send character infos
MessageOut outMsg(mNetwork);
diff --git a/src/gui/char_select.h b/src/gui/char_select.h
index 74745788..23de061d 100644
--- a/src/gui/char_select.h
+++ b/src/gui/char_select.h
@@ -22,17 +22,16 @@
#ifndef _CHAR_SELECT_H
#define _CHAR_SELECT_H
+#include <guichan/actionlistener.hpp>
+
#include "window.h"
-#include "../guichanfwd.h"
-#include "../lockedarray.h"
#include "../being.h"
+#include "../lockedarray.h"
-#include <guichan/actionlistener.hpp>
-
-class Player;
class LocalPlayer;
class Network;
+class Player;
class PlayerBox;
/**
@@ -65,8 +64,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener
gcn::Button *mSelectButton;
gcn::Button *mCancelButton;
- gcn::Button *mNewCharButton;
- gcn::Button *mDelCharButton;
+ gcn::Button *mNewDelCharButton;
gcn::Button *mPreviousButton;
gcn::Button *mNextButton;
@@ -110,14 +108,12 @@ class CharCreateDialog : public Window, public gcn::ActionListener
*/
~CharCreateDialog();
- void
- action(const gcn::ActionEvent &event);
+ void action(const gcn::ActionEvent &event);
/**
* Unlocks the dialog, enabling the create character button again.
*/
- void
- unlock();
+ void unlock();
private:
/**
diff --git a/src/gui/char_server.cpp b/src/gui/char_server.cpp
index 7be2441d..bc096379 100644
--- a/src/gui/char_server.cpp
+++ b/src/gui/char_server.cpp
@@ -19,9 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "char_server.h"
-
#include "button.h"
+#include "char_server.h"
#include "listbox.h"
#include "scrollarea.h"
@@ -29,10 +28,7 @@
#include "../main.h"
#include "../serverinfo.h"
-#include "../net/network.h" // TODO this is just for iptostring, move that?
-
#include "../utils/gettext.h"
-#include "../utils/strprintf.h"
#include "../utils/tostring.h"
extern SERVER_INFO **server_info;
@@ -40,7 +36,8 @@ extern SERVER_INFO **server_info;
/**
* The list model for the server list.
*/
-class ServerListModel : public gcn::ListModel {
+class ServerListModel : public gcn::ListModel
+{
public:
virtual ~ServerListModel() {};
@@ -81,13 +78,12 @@ ServerSelectDialog::ServerSelectDialog(LoginData *loginData, int nextState):
add(mOkButton);
add(mCancelButton);
- if (n_server == 0) {
+ if (n_server == 0)
// Disable Ok button
mOkButton->setEnabled(false);
- } else {
+ else
// Select first server
mServerList->setSelected(1);
- }
setLocationRelativeTo(getParent());
setVisible(true);
@@ -99,31 +95,27 @@ ServerSelectDialog::~ServerSelectDialog()
delete mServerListModel;
}
-void
-ServerSelectDialog::action(const gcn::ActionEvent &event)
+void ServerSelectDialog::action(const gcn::ActionEvent &event)
{
- if (event.getId() == "ok") {
+ if (event.getId() == "ok")
+ {
mOkButton->setEnabled(false);
const SERVER_INFO *si = server_info[mServerList->getSelected()];
mLoginData->hostname = iptostring(si->address);
mLoginData->port = si->port;
mLoginData->updateHost = si->updateHost;
-
state = mNextState;
}
- else if (event.getId() == "cancel") {
+ else if (event.getId() == "cancel")
state = LOGIN_STATE;
- }
}
-int
-ServerListModel::getNumberOfElements()
+int ServerListModel::getNumberOfElements()
{
return n_server;
}
-std::string
-ServerListModel::getElementAt(int i)
+std::string ServerListModel::getElementAt(int i)
{
const SERVER_INFO *si = server_info[i];
return si->name + " (" + toString(si->online_users) + ")";
diff --git a/src/gui/char_server.h b/src/gui/char_server.h
index 9419c92d..49a5b47b 100644
--- a/src/gui/char_server.h
+++ b/src/gui/char_server.h
@@ -27,8 +27,6 @@
#include "window.h"
-#include "../guichanfwd.h"
-
class LoginData;
class ServerListModel;
diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp
index 87d843a0..2845691a 100644
--- a/src/gui/chat.cpp
+++ b/src/gui/chat.cpp
@@ -19,57 +19,61 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <algorithm>
-#include <sstream>
-
#include <guichan/focushandler.hpp>
-#include "chat.h"
-
#include "browserbox.h"
+#include "chat.h"
#include "chatinput.h"
+#include "itemlinkhandler.h"
+#include "recorder.h"
#include "scrollarea.h"
#include "sdlinput.h"
#include "windowcontainer.h"
#include "widgets/layout.h"
+#include "../beingmanager.h"
#include "../configuration.h"
#include "../game.h"
#include "../localplayer.h"
+#include "../party.h"
#include "../net/messageout.h"
#include "../net/protocol.h"
+#include "../resources/iteminfo.h"
+#include "../resources/itemdb.h"
+
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
+#include "../utils/tostring.h"
#include "../utils/trim.h"
-ChatWindow::ChatWindow(Network *network):
- Window(""),
- mNetwork(network),
- mTmpVisible(false)
+ChatWindow::ChatWindow(Network * network):
+Window(""), mNetwork(network), mTmpVisible(false)
{
- setWindowName("Chat");
+ setWindowName(_("Chat"));
setResizable(true);
setDefaultSize(0, windowContainer->getHeight() - 123, 600, 123);
setMinWidth(150);
setMinHeight(90);
+ mItemLinkHandler = new ItemLinkHandler();
+
mChatInput = new ChatInput;
mChatInput->setActionEventId("chatinput");
mChatInput->addActionListener(this);
mTextOutput = new BrowserBox(BrowserBox::AUTO_WRAP);
mTextOutput->setOpaque(false);
- mTextOutput->disableLinksAndUserColors();
mTextOutput->setMaxRow((int) config.getValue("ChatLogLength", 0));
+ mTextOutput->setLinkHandler(mItemLinkHandler);
+
mScrollArea = new ScrollArea(mTextOutput);
- mScrollArea->setPosition(
- mScrollArea->getFrameSize(), mScrollArea->getFrameSize());
- mScrollArea->setScrollPolicy(
- gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_ALWAYS);
+ mScrollArea->setScrollPolicy(gcn::ScrollArea::SHOW_NEVER,
+ gcn::ScrollArea::SHOW_ALWAYS);
+ mScrollArea->setScrollAmount(0, 1);
mScrollArea->setOpaque(false);
place(0, 0, mScrollArea, 5, 5).setPadding(0);
@@ -84,23 +88,48 @@ ChatWindow::ChatWindow(Network *network):
// Add key listener to chat input to be able to respond to up/down
mChatInput->addKeyListener(this);
mCurHist = mHistory.end();
+
+ // Read the party prefix
+ std::string partyPrefix = config.getValue("PartyPrefix", "$");
+ mPartyPrefix = (partyPrefix.empty() ? '$' : partyPrefix.at(0));
+ mReturnToggles = config.getValue("ReturnToggles", "0") == "1";
+ mRecorder = new Recorder(this);
+ mParty = new Party(this, mNetwork);
+
+ // If the player had @assert on in the last session, ask the server to
+ // run the @assert command for the player again. Convenience for GMs.
+ if (config.getValue(player_node->getName() + "GMassert", 0))
+ chatSend(player_node->getName(), "@assert");
+}
+
+ChatWindow::~ChatWindow()
+{
+ char partyPrefix[2] = ".";
+ *partyPrefix = mPartyPrefix;
+ config.setValue("PartyPrefix", partyPrefix);
+ config.setValue("ReturnToggles", mReturnToggles ? "1" : "0");
+ delete mRecorder;
}
-void ChatWindow::chatLog(std::string line, int own)
+void ChatWindow::chatLog(std::string line, int own, bool ignoreRecord)
{
// Trim whitespace
trim(line);
CHATLOG tmp;
- tmp.own = own;
+ tmp.own = own;
tmp.nick = "";
tmp.text = line;
+
std::string::size_type pos = line.find(" : ");
- if (pos != std::string::npos) {
+ if (pos != std::string::npos)
+ {
tmp.nick = line.substr(0, pos);
tmp.text = line.substr(pos + 3);
- } else {
+ }
+ else
+ {
// Fix the owner of welcome message.
if (line.substr(0, 7) == "Welcome")
{
@@ -108,77 +137,99 @@ void ChatWindow::chatLog(std::string line, int own)
}
}
- std::string lineColor = "##0"; // Equiv. to BrowserBox::BLACK
- switch (own) {
+ std::string lineColor = "##C";
+ switch (own)
+ {
case BY_GM:
- if (tmp.nick.empty()) {
- tmp.nick = _("Global announcement:");
+ if (tmp.nick.empty())
+ {
+ tmp.nick = std::string(_("Global announcement:"));
tmp.nick += " ";
- } else {
+ lineColor = "##G";
+ }
+ else
+ {
tmp.nick = strprintf(_("Global announcement from %s:"),
tmp.nick.c_str());
tmp.nick += " ";
+ lineColor = "##1"; // Equiv. to BrowserBox::RED
}
- lineColor = "##1"; // Equiv. to BrowserBox::RED
break;
case BY_PLAYER:
tmp.nick += CAT_NORMAL;
- lineColor = "##2"; // Equiv. to BrowserBox::GREEN
+ lineColor = "##Y";
break;
case BY_OTHER:
tmp.nick += CAT_NORMAL;
- lineColor = "##0"; // Equiv. to BrowserBox::BLACK
+ lineColor = "##C";
break;
case BY_SERVER:
tmp.nick = _("Server:");
tmp.nick += " ";
tmp.text = line;
- lineColor = "##7"; // Equiv. to BrowserBox::PINK
+ lineColor = "##S";
+ break;
+ case BY_PARTY:
+ tmp.nick += CAT_NORMAL;
+ lineColor = "##P";
break;
case ACT_WHISPER:
tmp.nick = strprintf(_("%s whispers:"), tmp.nick.c_str());
tmp.nick += " ";
- lineColor = "##3"; // Equiv. to BrowserBox::BLUE
+ lineColor = "##W";
break;
case ACT_IS:
tmp.nick += CAT_IS;
- lineColor = "##5"; // Equiv. to BrowserBox::YELLOW
+ lineColor = "##I";
break;
case BY_LOGGER:
tmp.nick = "";
tmp.text = line;
- lineColor = "##8"; // Equiv. to BrowserBox::GREY
+ lineColor = "##L";
break;
}
+ if (tmp.nick == ": ")
+ {
+ tmp.nick = "";
+ lineColor = "##S";
+ }
+
+ if (tmp.nick.empty() && tmp.text.substr(0, 17) == "Visible GM status")
+ {
+ player_node->setGM();
+ }
+
// Get the current system time
time_t t;
time(&t);
// Format the time string properly
std::stringstream timeStr;
- timeStr << "["
- << ((((t / 60) / 60) % 24 < 10) ? "0" : "")
- << (int)(((t / 60) / 60) % 24)
- << ":"
- << (((t / 60) % 60 < 10) ? "0" : "")
- << (int)((t / 60) % 60)
- << "] ";
+ timeStr << "[" << ((((t / 60) / 60) % 24 < 10) ? "0" : "")
+ << (int) (((t / 60) / 60) % 24)
+ << ":" << (((t / 60) % 60 < 10) ? "0" : "")
+ << (int) ((t / 60) % 60)
+ << "] ";
line = lineColor + timeStr.str() + tmp.nick + tmp.text;
// We look if the Vertical Scroll Bar is set at the max before
// adding a row, otherwise the max will always be a row higher
// at comparison.
- if (mScrollArea->getVerticalScrollAmount() == mScrollArea->getVerticalMaxScroll())
+ if (mScrollArea->getVerticalScrollAmount() ==
+ mScrollArea->getVerticalMaxScroll())
{
mTextOutput->addRow(line);
- mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll());
+ mScrollArea->setVerticalScrollAmount(mScrollArea->
+ getVerticalMaxScroll());
}
else
{
mTextOutput->addRow(line);
}
+
+ mRecorder->record(line.substr(3));
}
void ChatWindow::chatLog(CHATSKILL act)
@@ -192,12 +243,13 @@ void ChatWindow::action(const gcn::ActionEvent &event)
{
std::string message = mChatInput->getText();
- if (!message.empty()) {
+ if (!message.empty())
+ {
// If message different from previous, put it in the history
- if (mHistory.empty() || message != mHistory.back()) {
+ if (mHistory.empty() || message != mHistory.back())
+ {
mHistory.push_back(message);
}
-
// Reset history iterator
mCurHist = mHistory.end();
@@ -208,13 +260,15 @@ void ChatWindow::action(const gcn::ActionEvent &event)
mChatInput->setText("");
}
- // Remove focus and hide input
- mFocusHandler->focusNone();
+ if (message.empty() || !mReturnToggles)
+ {
+ // Remove focus and hide input
+ mFocusHandler->focusNone();
- // If the chatWindow is shown up because you want to send a message
- // It should hide now
- if (mTmpVisible) {
- setVisible(false);
+ // If the chatWindow is shown up because you want to send a message
+ // It should hide now
+ if (mTmpVisible)
+ setVisible(false);
}
}
}
@@ -244,16 +298,15 @@ bool ChatWindow::isInputFocused()
return mChatInput->isFocused();
}
-void ChatWindow::whisper(const std::string &nick, std::string msg,
- int prefixlen)
+void ChatWindow::whisper(const std::string &nick, std::string msg)
{
std::string recvnick = "";
- msg.erase(0, prefixlen + 1);
if (msg.substr(0, 1) == "\"")
{
const std::string::size_type pos = msg.find('"', 1);
- if (pos != std::string::npos) {
+ if (pos != std::string::npos)
+ {
recvnick = msg.substr(1, pos - 1);
msg.erase(0, pos + 2);
}
@@ -261,7 +314,8 @@ void ChatWindow::whisper(const std::string &nick, std::string msg,
else
{
const std::string::size_type pos = msg.find(" ");
- if (pos != std::string::npos) {
+ if (pos != std::string::npos)
+ {
recvnick = msg.substr(0, pos);
msg.erase(0, pos + 1);
}
@@ -274,8 +328,8 @@ void ChatWindow::whisper(const std::string &nick, std::string msg,
outMsg.writeString(msg, msg.length());
chatLog(strprintf(_("Whispering to %s: %s"),
- recvnick.c_str(), msg.c_str()),
- BY_PLAYER);
+ recvnick.c_str(), msg.c_str()),
+ BY_PLAYER);
}
void ChatWindow::chatSend(const std::string &nick, std::string msg)
@@ -284,8 +338,68 @@ void ChatWindow::chatSend(const std::string &nick, std::string msg)
* require server handling by proper packet. Probably
* those if elses should be replaced by protocol calls */
+ trim(msg);
+
+ if (msg.compare("") == 0)
+ return;
+
+ // Send party message
+ if (msg.at(0) == mPartyPrefix)
+ {
+ msg.erase(0, 1);
+ std::size_t length = msg.length() + 1;
+
+ if (length == 0)
+ {
+ chatLog(_("Trying to send a blank party message."), BY_SERVER);
+ return;
+ }
+ MessageOut outMsg(mNetwork);
+
+ outMsg.writeInt16(CMSG_PARTY_MESSAGE);
+ outMsg.writeInt16(length + 4);
+ outMsg.writeString(msg, length);
+ return;
+ }
+
+ // check for item link
+ std::string::size_type start = msg.find('[');
+ while (start != std::string::npos && msg[start+1] != '@')
+ {
+ std::string::size_type end = msg.find(']', start);
+ if (end != std::string::npos)
+ {
+ // Catch multiple embeds and ignore them so it doesn't crash the client.
+ while ((msg.find('[', start + 1) != std::string::npos) &&
+ (msg.find('[', start + 1) < end))
+ {
+ start = msg.find('[', start + 1);
+ }
+
+ std::string temp = msg.substr(start+1, end - start - 1);
+
+ trim(temp);
+
+ for (unsigned int i = 0; i < temp.size(); i++)
+ {
+ temp[i] = (char) tolower(temp[i]);
+ }
+
+ const ItemInfo itemInfo = ItemDB::get(temp);
+ if (itemInfo.getName() != _("Unknown item"))
+ {
+ msg.insert(end, "@@");
+ msg.insert(start+1, "|");
+ msg.insert(start+1, toString(itemInfo.getId()));
+ msg.insert(start+1, "@@");
+ }
+ }
+ start = msg.find('[', start + 1);
+ }
+
// Prepare ordinary message
- if (msg.substr(0, 1) != "/") {
+ if (msg.substr(0, 1) != "/")
+ {
msg = nick + " : " + msg;
MessageOut outMsg(mNetwork);
@@ -293,21 +407,38 @@ void ChatWindow::chatSend(const std::string &nick, std::string msg)
// Added + 1 in order to let eAthena parse admin commands correctly
outMsg.writeInt16(msg.length() + 4 + 1);
outMsg.writeString(msg, msg.length() + 1);
+ return;
+ }
+
+ msg.erase(0, 1);
+ trim(msg);
+
+ std::size_t space = msg.find(" ");
+ std::string command = msg.substr(0, space);
+
+ if (space == std::string::npos)
+ {
+ msg = "";
}
- else if (msg.substr(0, IS_ANNOUNCE_LENGTH) == IS_ANNOUNCE)
+ else
+ {
+ msg = msg.substr(space);
+ trim(msg);
+ }
+
+ if (command == "announce")
{
- msg.erase(0, IS_ANNOUNCE_LENGTH);
MessageOut outMsg(mNetwork);
outMsg.writeInt16(0x0099);
outMsg.writeInt16(msg.length() + 4);
outMsg.writeString(msg, msg.length());
}
- else if (msg.substr(0, IS_HELP_LENGTH) == IS_HELP)
+ else if (command == "help")
{
- msg.erase(0, IS_HELP_LENGTH + 1);
trim(msg);
std::size_t space = msg.find(" ");
std::string msg1;
+
if (space == std::string::npos)
{
msg1 = "";
@@ -317,33 +448,155 @@ void ChatWindow::chatSend(const std::string &nick, std::string msg)
msg1 = msg.substr(space + 1, msg.length());
msg = msg.substr(0, space);
}
- if (msg != "" && msg.at(0) == '/')
+
+ if (!msg.empty() && msg.at(0) == '/')
{
msg.erase(0, 1);
}
+
trim(msg1);
help(msg, msg1);
}
- else if (msg.substr(0, IS_WHERE_LENGTH) == IS_WHERE)
+ else if (command == "where")
{
// Display the current map, X, and Y
std::ostringstream where;
where << map_path << " " << player_node->mX << "," << player_node->mY;
chatLog(where.str(), BY_SERVER);
}
- else if (msg.substr(0, IS_WHO_LENGTH) == IS_WHO)
+ else if (command == "who")
{
MessageOut outMsg(mNetwork);
outMsg.writeInt16(0x00c1);
}
- else if (msg.substr(0, IS_CLEAR_LENGTH) == IS_CLEAR)
- {
+ else if (command == "clear")
mTextOutput->clearRows();
+ else if (command == "whisper" || command == "msg" || command == "w")
+ whisper(nick, msg);
+ else if (command == "record")
+ mRecorder->changeRecordingStatus(msg);
+ else if (command == "toggle")
+ {
+ if (msg.empty())
+ {
+ chatLog(mReturnToggles ? _("Return toggles chat.")
+ : _("Message closes chat."), BY_SERVER);
+ return;
+ }
+
+ msg = msg.substr(0, 1);
+
+ if (msg == "1" ||
+ msg == "y" || msg == "Y" ||
+ msg == "t" || msg == "T")
+ {
+ chatLog(_("Return now toggles chat."), BY_SERVER);
+ mReturnToggles = true;
+ return;
+ }
+ else if (msg == "0" ||
+ msg == "n" || msg == "N" ||
+ msg == "f" || msg == "F")
+ {
+ chatLog(_("Message now closes chat."), BY_SERVER);
+ mReturnToggles = false;
+ return;
+ }
+ else
+ chatLog(_("Options to /toggle are \"yes\", \"no\", \"true\", "
+ "\"false\", \"1\", \"0\"."), BY_SERVER);
+ }
+ else if (command == "party")
+ {
+ if (msg.empty())
+ {
+ chatLog(_("Unknown party command... Type \"/help\" party for more "
+ "information."), BY_SERVER);
+ return;
+ }
+
+ const std::string::size_type space = msg.find(" ");
+ std::string rest = (space == std::string::npos ? ""
+ : msg.substr(space + 1, msg.length()));
+
+ if (!rest.empty())
+ {
+ msg = msg.substr(0, space);
+ trim(msg);
+ }
+
+ party(msg, rest);
+ return;
+ }
+ else if (command == "cast")
+ {
+ /*
+ * This will eventually be replaced by a GUI, so
+ * we don't need to get too sophisticated
+ */
+ MessageOut outMsg(mNetwork);
+ if (msg == "heal")
+ {
+ outMsg.writeInt16(0x03f3);
+ outMsg.writeInt16(0x01);
+ outMsg.writeInt32(0);
+ outMsg.writeInt8(0);
+ outMsg.writeInt8(0);
+ outMsg.writeString("", 24);
+ }
+ else if (msg == "gather")
+ {
+ outMsg.writeInt16(0x03f3);
+ outMsg.writeInt16(0x02);
+ outMsg.writeInt32(0);
+ outMsg.writeInt8(0);
+ outMsg.writeInt8(0);
+ outMsg.writeString("", 24);
+ }
+ else
+ chatLog(_("No such spell!"), BY_SERVER);
+ }
+ else if (command == "present")
+ {
+ Beings & beings = beingManager->getAll();
+ std::string response = "";
+
+ for (BeingIterator bi = beings.begin(), be = beings.end();
+ bi != be; ++bi)
+ {
+ if ((*bi)->getType() == Being::PLAYER)
+ {
+ if (!response.empty())
+ {
+ response += ", ";
+ }
+ response += (*bi)->getName();
+ }
+ }
+
+ if (mRecorder->isRecording())
+ {
+ // Get the current system time
+ time_t t;
+ time(&t);
+
+ // Format the time string properly
+ std::stringstream timeStr;
+ timeStr << "[" << ((((t / 60) / 60) % 24 < 10) ? "0" : "")
+ << (int) (((t / 60) / 60) % 24)
+ << ":" << (((t / 60) % 60 < 10) ? "0" : "")
+ << (int) ((t / 60) % 60)
+ << "] ";
+
+
+ mRecorder->record(timeStr.str() + _("Present: ") + response + ".");
+ chatLog(_("Attendance written to record log."), BY_SERVER, true);
+ }
+ else
+ {
+ chatLog(_("Present: ") + response, BY_SERVER);
+ }
}
- else if (msg.substr(0, IS_WHISPER_LENGTH) == IS_WHISPER)
- whisper(nick, msg, IS_WHISPER_LENGTH);
- else if (msg.substr(0, IS_SHORT_WHISPER_LENGTH) == IS_SHORT_WHISPER)
- whisper(nick, msg, IS_SHORT_WHISPER_LENGTH);
else
{
chatLog(_("Unknown command"), BY_SERVER);
@@ -353,8 +606,10 @@ void ChatWindow::chatSend(const std::string &nick, std::string msg)
std::string ChatWindow::const_msg(CHATSKILL act)
{
std::string msg;
- if (act.success == SKILL_FAILED && act.skill == SKILL_BASIC) {
- switch (act.bskill) {
+ if (act.success == SKILL_FAILED && act.skill == SKILL_BASIC)
+ {
+ switch (act.bskill)
+ {
case BSKILL_TRADE:
msg = _("Trade failed!");
break;
@@ -377,7 +632,8 @@ std::string ChatWindow::const_msg(CHATSKILL act)
msg += " ";
- switch (act.reason) {
+ switch (act.reason)
+ {
case RFAIL_SKILLDEP:
msg += _("You have not yet reached a high enough lvl!");
break;
@@ -412,8 +668,11 @@ std::string ChatWindow::const_msg(CHATSKILL act)
msg += _("Huh? What's that?");
break;
}
- } else {
- switch (act.skill) {
+ }
+ else
+ {
+ switch (act.skill)
+ {
case SKILL_WARP :
msg = _("Warp failed...");
break;
@@ -448,11 +707,14 @@ void ChatWindow::keyPressed(gcn::KeyEvent &event)
{
// Move forward through the history
HistoryIterator prevHist = mCurHist++;
- if (mCurHist != mHistory.end()) {
+
+ if (mCurHist != mHistory.end())
+ {
mChatInput->setText(*mCurHist);
mChatInput->setCaretPosition(mChatInput->getText().length());
}
- else {
+ else
+ {
mCurHist = prevHist;
}
}
@@ -468,10 +730,18 @@ void ChatWindow::keyPressed(gcn::KeyEvent &event)
void ChatWindow::setInputText(std::string input_str)
{
- mChatInput->setText(input_str + " ");
+ mChatInput->setText(mChatInput->getText() + input_str + " ");
requestChatFocus();
}
+void ChatWindow::addItemText(const std::string &item)
+{
+ std::ostringstream text;
+ text << "[" << item << "] ";
+ mChatInput->setText(mChatInput->getText() + text.str());
+ requestChatFocus();
+}
+
void ChatWindow::setVisible(bool isVisible)
{
Window::setVisible(isVisible);
@@ -484,70 +754,137 @@ void ChatWindow::setVisible(bool isVisible)
mTmpVisible = false;
}
-void ChatWindow::help(const std::string &msg1, const std::string &msg2)
+void ChatWindow::party(const std::string & command, const std::string & rest)
+{
+ if (command == "prefix")
+ {
+ if (rest.empty())
+ {
+ char temp[2] = ".";
+ *temp = mPartyPrefix;
+ chatLog(_("The current party prefix is ") + std::string(temp),
+ BY_SERVER);
+ }
+ else if (rest.length() != 1)
+ {
+ chatLog(_("Party prefix must be one character long."), BY_SERVER);
+ }
+ else
+ {
+ if (rest == "/")
+ {
+ chatLog(_("Cannot use a '/' as the prefix."), BY_SERVER);
+ }
+ else
+ {
+ mPartyPrefix = rest.at(0);
+ chatLog(_("Changing prefix to ") + rest, BY_SERVER);
+ }
+ }
+ }
+ else
+ mParty->respond(command, rest);
+}
+
+void ChatWindow::help(const std::string & msg1, const std::string & msg2)
{
chatLog(_("-- Help --"), BY_SERVER);
- if (msg1 == "")
+ if (msg1.empty())
{
chatLog(_("/announce: Global announcement (GM only)"), BY_SERVER);
chatLog(_("/clear: Clears this window"), BY_SERVER);
chatLog(_("/help: Display this help"), BY_SERVER);
+ chatLog(_("/party <command> <params>: Party commands."), BY_SERVER);
+ chatLog(_("/msg <nick> <message>: Alternate form for /whisper"), BY_SERVER);
+ chatLog(_("/present: Get list of players present"), BY_SERVER);
+ chatLog(_("/record <filename>: Start recording the chat to an"
+ " external file."), BY_SERVER);
+ chatLog(_("/toggle: Determine whether <return> toggles the chat log."),
+ BY_SERVER);
chatLog(_("/where: Display map name"), BY_SERVER);
+ chatLog(_("/w <nick> <message>: Short form for /whisper"), BY_SERVER);
chatLog(_("/whisper <nick> <message>: Sends a private <message>"
" to <nick>"), BY_SERVER);
- chatLog(_("/w <nick> <message>: Short form for /whisper"), BY_SERVER);
chatLog(_("/who: Display number of online users"), BY_SERVER);
chatLog(_("For more information, type /help <command>"), BY_SERVER);
- return;
}
- if (msg1 == "announce")
+ else if (msg1 == "announce")
{
chatLog(_("Command: /announce <msg>"), BY_SERVER);
chatLog(_("*** only available to a GM ***"), BY_SERVER);
chatLog(_("This command sends the message <msg> to "
"all players currently online."), BY_SERVER);
- return;
}
- if (msg1 == "clear")
+ else if (msg1 == "clear")
{
chatLog(_("Command: /clear"), BY_SERVER);
chatLog(_("This command clears the chat log of previous chat."),
BY_SERVER);
- return;
}
- if (msg1 == "help")
+ else if (msg1 == "help")
{
chatLog(_("Command: /help"), BY_SERVER);
chatLog(_("This command displays a list of all commands available."),
BY_SERVER);
chatLog(_("Command: /help <command>"), BY_SERVER);
chatLog(_("This command displays help on <command>."), BY_SERVER);
- return;
}
- if (msg1 == "where")
+ else if (msg1 == "party")
+ {
+ mParty->help(msg2);
+ }
+ else if (msg1 == "present")
+ {
+ chatLog(_("Command: /present"), BY_SERVER);
+ chatLog(_("This command gets a list of players within hearing and "
+ "sends it to either the record log if recording, or the chat "
+ "log otherwise."), BY_SERVER);
+ }
+ else if (msg1 == "record")
+ {
+ chatLog(_("Command: /record <filename>"), BY_SERVER);
+ chatLog(_("This command starts recording the chat log to the file "
+ "<filename>."), BY_SERVER);
+ chatLog(_("Command: /record"), BY_SERVER);
+ chatLog(_("This command finishes a recording session."), BY_SERVER);
+ }
+ else if (msg1 == "toggle")
+ {
+ chatLog(_("Command: /toggle <state>"), BY_SERVER);
+ chatLog(_("This command sets whether the return key should toggle the"
+ "chat log, or whether the chat log turns off automatically."),
+ BY_SERVER);
+ chatLog(_("<state> can be one of \"1\", \"yes\", \"true\" to "
+ "turn the toggle on, or \"0\", \"no\", \"false\" to turn the "
+ "toggle off."), BY_SERVER);
+ chatLog(_("Command: /toggle"), BY_SERVER);
+ chatLog(_("This command displays the return toggle status."), BY_SERVER);
+ }
+ else if (msg1 == "where")
{
chatLog(_("Command: /where"), BY_SERVER);
chatLog(_("This command displays the name of the current map."),
BY_SERVER);
- return;
}
- if (msg1 == "whisper" || msg1 == "w")
+ else if (msg1 == "whisper" || msg1 == "msg" || msg1 == "w")
{
+ chatLog(_("Command: /msg <nick> <msg>"), BY_SERVER);
chatLog(_("Command: /whisper <nick> <msg>"), BY_SERVER);
chatLog(_("Command: /w <nick> <msg>"), BY_SERVER);
chatLog(_("This command sends the message <msg> to <nick>."),
BY_SERVER);
chatLog(_("If the <nick> has spaces in it, enclose it in "
- "double quotes (\")."), BY_SERVER);
- return;
+ "double quotes (\")."), BY_SERVER);
}
- if (msg1 == "who")
+ else if (msg1 == "who")
{
chatLog(_("Command: /who"), BY_SERVER);
chatLog(_("This command displays the number of players currently "
- "online."), BY_SERVER);
- return;
+ "online."), BY_SERVER);
+ }
+ else
+ {
+ chatLog(_("Unknown command."), BY_SERVER);
+ chatLog(_("Type /help for a list of commands."), BY_SERVER);
}
- chatLog(_("Unknown command."), BY_SERVER);
- chatLog(_("Type /help for a list of commands."), BY_SERVER);
}
diff --git a/src/gui/chat.h b/src/gui/chat.h
index ad89c8dc..2fadb014 100644
--- a/src/gui/chat.h
+++ b/src/gui/chat.h
@@ -30,36 +30,23 @@
#include "window.h"
-#include "../guichanfwd.h"
-
class BrowserBox;
class Network;
+class Recorder;
+class Party;
class ScrollArea;
+class ItemLinkHandler;
#define BY_GM 0 // those should be self-explanatory =)
#define BY_PLAYER 1
#define BY_OTHER 2
#define BY_SERVER 3
+#define BY_PARTY 4
+
+#define ACT_WHISPER 5 // getting whispered at
+#define ACT_IS 6 // equivalent to "/me" on IRC
-#define ACT_WHISPER 4 // getting whispered at
-#define ACT_IS 5 // equivalent to "/me" on IRC
-
-#define BY_LOGGER 6
-
-#define IS_ANNOUNCE "/announce "
-#define IS_ANNOUNCE_LENGTH 10
-#define IS_HELP "/help"
-#define IS_HELP_LENGTH 5
-#define IS_WHERE "/where"
-#define IS_WHERE_LENGTH 6
-#define IS_WHO "/who"
-#define IS_WHO_LENGTH 4
-#define IS_CLEAR "/clear"
-#define IS_CLEAR_LENGTH 6
-#define IS_WHISPER "/whisper"
-#define IS_WHISPER_LENGTH 8
-#define IS_SHORT_WHISPER "/w"
-#define IS_SHORT_WHISPER_LENGTH 2
+#define BY_LOGGER 7
/**
* gets in between usernick and message text depending on
@@ -127,14 +114,19 @@ class ChatWindow : public Window, public gcn::ActionListener,
ChatWindow(Network *network);
/**
+ * Destructor: used to write back values to the config file
+ */
+ ~ChatWindow();
+
+ /**
* Adds a line of text to our message list. Parameters:
*
* @param line Text message.
* @parem own Type of message (usually the owner-type).
*/
- void chatLog(std::string line, int own);
+ void chatLog(std::string line, int own, bool ignoreRecord = false);
- /*
+ /**
* Calls original chat_log() after processing the packet.
*/
void chatLog(CHATSKILL);
@@ -186,6 +178,9 @@ class ChatWindow : public Window, public gcn::ActionListener,
/** Called to set current text */
void setInputText(std::string input_str);
+ /** Called to add item to chat */
+ void addItemText(const std::string &item);
+
/** Override to reset mTmpVisible */
void setVisible(bool visible);
@@ -199,6 +194,14 @@ class ChatWindow : public Window, public gcn::ActionListener,
void scroll(int amount);
/**
+ * party implements the partying chat commands
+ *
+ * @param command is the party command to perform
+ * @param msg is the remainder of the message
+ */
+ void party(const std::string &command, const std::string &msg);
+
+ /**
* help implements the /help command
*
* @param msg1 is the command that the player needs help on
@@ -207,10 +210,11 @@ class ChatWindow : public Window, public gcn::ActionListener,
void help(const std::string &msg1, const std::string &msg2);
private:
+
Network *mNetwork;
bool mTmpVisible;
- void whisper(const std::string &nick, std::string msg, int prefixlen);
+ void whisper(const std::string &nick, std::string msg);
/** One item in the chat log */
struct CHATLOG
@@ -226,13 +230,19 @@ class ChatWindow : public Window, public gcn::ActionListener,
gcn::TextField *mChatInput; /**< Input box for typing chat messages */
BrowserBox *mTextOutput; /**< Text box for displaying chat history */
ScrollArea *mScrollArea; /**< Scroll area around text output */
-
+ ItemLinkHandler *mItemLinkHandler; /** Used for showing item popup on
+ clicking links **/
typedef std::list<std::string> History;
typedef History::iterator HistoryIterator;
History mHistory; /**< Command history */
HistoryIterator mCurHist; /**< History iterator */
+ Recorder *mRecorder; /**< Recording class */
+ char mPartyPrefix; /**< Messages beginning with the prefix are sent to
+ the party */
+ bool mReturnToggles; /**< Marks whether <Return> toggles the chat log
+ or not */
+ Party *mParty;
};
-
extern ChatWindow *chatWindow;
#endif
diff --git a/src/gui/chatinput.h b/src/gui/chatinput.h
index 07144c5b..a4a50502 100644
--- a/src/gui/chatinput.h
+++ b/src/gui/chatinput.h
@@ -22,10 +22,10 @@
#ifndef CHATINPUT_H
#define CHATINPUT_H
-#include "textfield.h"
-
#include <guichan/focuslistener.hpp>
+#include "textfield.h"
+
/**
* The chat input hides when it loses focus. It is also invisible by default.
*/
diff --git a/src/gui/checkbox.cpp b/src/gui/checkbox.cpp
index b8fca2b8..511ed34c 100644
--- a/src/gui/checkbox.cpp
+++ b/src/gui/checkbox.cpp
@@ -21,12 +21,14 @@
#include "checkbox.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
int CheckBox::instances = 0;
+float CheckBox::mAlpha = config.getValue("guialpha", 0.8);
Image *CheckBox::checkBoxNormal;
Image *CheckBox::checkBoxChecked;
Image *CheckBox::checkBoxDisabled;
@@ -43,6 +45,13 @@ CheckBox::CheckBox(const std::string& caption, bool selected):
checkBoxChecked = checkBox->getSubImage(9, 0, 9, 10);
checkBoxDisabled = checkBox->getSubImage(18, 0, 9, 10);
checkBoxDisabledChecked = checkBox->getSubImage(27, 0, 9, 10);
+ if (config.getValue("opengl", 0))
+ {
+ checkBoxNormal->setAlpha(mAlpha);
+ checkBoxChecked->setAlpha(mAlpha);
+ checkBoxDisabled->setAlpha(mAlpha);
+ checkBoxDisabledChecked->setAlpha(mAlpha);
+ }
checkBox->decRef();
}
@@ -66,16 +75,26 @@ void CheckBox::drawBox(gcn::Graphics* graphics)
{
Image *box;
- if (isSelected()) {
- if (isEnabled()) {
+ if (isSelected())
+ {
+ if (isEnabled())
box = checkBoxChecked;
- } else {
+ else
box = checkBoxDisabledChecked;
- }
- } else if (isEnabled()) {
+ }
+ else if (isEnabled())
box = checkBoxNormal;
- } else {
+ else
box = checkBoxDisabled;
+
+ if (config.getValue("guialpha", 0.8) != mAlpha &&
+ config.getValue("opengl", 0))
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ checkBoxNormal->setAlpha(mAlpha);
+ checkBoxChecked->setAlpha(mAlpha);
+ checkBoxDisabled->setAlpha(mAlpha);
+ checkBoxDisabledChecked->setAlpha(mAlpha);
}
static_cast<Graphics*>(graphics)->drawImage(box, 2, 2);
diff --git a/src/gui/checkbox.h b/src/gui/checkbox.h
index 4b312d22..20adb43c 100644
--- a/src/gui/checkbox.h
+++ b/src/gui/checkbox.h
@@ -22,8 +22,6 @@
#ifndef CHECKBOX_H
#define CHECKBOX_H
-#include <iosfwd>
-
#include <guichan/widgets/checkbox.hpp>
class Image;
@@ -33,7 +31,8 @@ class Image;
*
* \ingroup GUI
*/
-class CheckBox : public gcn::CheckBox {
+class CheckBox : public gcn::CheckBox
+{
public:
/**
* Constructor.
@@ -52,6 +51,7 @@ class CheckBox : public gcn::CheckBox {
private:
static int instances;
+ static float mAlpha;
static Image *checkBoxNormal;
static Image *checkBoxChecked;
static Image *checkBoxDisabled;
diff --git a/src/gui/color.cpp b/src/gui/color.cpp
new file mode 100644
index 00000000..e37affda
--- /dev/null
+++ b/src/gui/color.cpp
@@ -0,0 +1,146 @@
+/*
+ * Configurable text colors
+ * Copyright (C) 2008 Douglas Boffey <dougaboffey@netscape.net>
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "color.h"
+
+#include "../configuration.h"
+
+#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+Color::Color()
+{
+ addColor('C', 0x000000, _("Chat"));
+ addColor('G', 0xff0000, _("GM"));
+ addColor('H', 0xebc873, _("Highlight"));
+ addColor('Y', 0x1fa052, _("Player"));
+ addColor('W', 0x0000ff, _("Whisper"));
+ addColor('I', 0xf1dc27, _("Is"));
+ addColor('P', 0xff00d8, _("Party"));
+ addColor('S', 0x8415e2, _("Server"));
+ addColor('L', 0x919191, _("Logger"));
+ addColor('<', 0xe50d0d, _("Hyperlink"));
+ commit();
+}
+
+Color::~Color()
+{
+ for (ColVector::iterator col = mColVector.begin(),
+ colEnd = mColVector.end();
+ col != colEnd;
+ ++col)
+ {
+ config.setValue("color" + col->text, toString(col->rgb));
+ }
+}
+
+void Color::setColor(const char c, const int rgb)
+{
+ for (ColVector::iterator col = mColVector.begin(),
+ colEnd = mColVector.end();
+ col != colEnd;
+ ++col)
+ {
+ if (col->ch == c)
+ {
+ col->rgb = rgb;
+ return;
+ }
+ }
+}
+
+int Color::getColor(const char c, bool &valid) const
+{
+ for (ColVector::const_iterator col = mColVector.begin(),
+ colEnd = mColVector.end();
+ col != colEnd;
+ ++col)
+ {
+ if (col->ch == c)
+ {
+ valid = true;
+ return col->rgb;
+ }
+ }
+ valid = false;
+ return 0x000000;
+}
+
+std::string Color::getElementAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return "";
+ }
+ return mColVector[i].text;
+}
+
+char Color::getColorCharAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return 'C';
+ }
+ return mColVector[i].ch;
+}
+
+void Color::addColor(const char c, const int rgb, const std::string &text)
+{
+ int trueRgb = config.getValue("color" + text, rgb);
+ mColVector.push_back(colorElem(c, trueRgb, text));
+}
+
+int Color::getColorAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return 0;
+ }
+ return mColVector[i].rgb;
+}
+
+void Color::setColorAt(int i, int rgb)
+{
+ if (i >= 0 && i < getNumberOfElements())
+ {
+ mColVector[i].rgb = rgb;
+ }
+}
+
+void Color::commit()
+{
+ for (ColVector::iterator i = mColVector.begin(), iEnd = mColVector.end();
+ i != iEnd;
+ ++i)
+ {
+ i->committedRgb = i->rgb;
+ }
+}
+
+void Color::rollback()
+{
+ for (ColVector::iterator i = mColVector.begin(), iEnd = mColVector.end();
+ i != iEnd;
+ ++i)
+ {
+ i->rgb = i->committedRgb;
+ }
+}
diff --git a/src/gui/color.h b/src/gui/color.h
new file mode 100644
index 00000000..509448e7
--- /dev/null
+++ b/src/gui/color.h
@@ -0,0 +1,136 @@
+/*
+ * Configurable text colors
+ * Copyright (C) 2008 Douglas Boffey <dougaboffey@netscape.net>
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef COLOUR_H
+#define COLOUR_H
+
+#include <string>
+#include <vector>
+
+#include <guichan/listmodel.hpp>
+
+class Color : public gcn::ListModel
+{
+ public:
+ /**
+ * Constructor
+ */
+ Color();
+
+ /**
+ * Destructor
+ */
+ ~Color();
+
+ /**
+ * Define the color replacement for a character
+ *
+ * @param c charater to be replaced
+ * @param rgb color to replace character
+ */
+ void setColor(const char c, const int rgb);
+
+ /**
+ * Define the color replacement for a character
+ *
+ * @param c character to be replaced
+ * @param r red component
+ * @param g green component
+ * @param b blue component
+ */
+ void setColor(const char c, const int r, const int g, const int b)
+ {
+ setColor(c, (r << 16) | (g << 8) | b);
+ }
+
+ /**
+ * Return the color associated with a character, if exists
+ *
+ * @param c character requested
+ * @param valid indicate whether character is known
+ */
+ int getColor(const char c, bool &valid) const;
+
+ /**
+ * Return the number of colors known
+ */
+ int getNumberOfElements() {return mColVector.size(); }
+
+ /**
+ * Return the name of the ith color
+ *
+ * @param i index of color interested in
+ */
+ std::string getElementAt(int i);
+
+ /**
+ * Get the color for the element at index i in the current color
+ * model
+ */
+ int getColorAt(int i);
+
+ /**
+ * Get the character used by the color for the element at index i in
+ * the current color model
+ */
+ char getColorCharAt(int i);
+
+ /**
+ * Set the color for the element at index i
+ */
+ void setColorAt(int i, int rgb);
+
+ /**
+ * Commit the colors
+ */
+ void commit();
+
+ /**
+ * Rollback the colors
+ */
+ void rollback();
+
+ private:
+ struct colorElem
+ {
+ colorElem(const char c, const int rgb, const std::string &text) :
+ ch(c), rgb(rgb), text(text) {}
+ char ch;
+ int rgb;
+ int committedRgb;
+ std::string text;
+ };
+ typedef std::vector<colorElem> ColVector;
+ ColVector mColVector;
+
+ /**
+ * Initialise color
+ *
+ * @param c character that needs initialising
+ * @param rgb default color if not found in config
+ * @param text identifier of color
+ */
+ void addColor(const char c, const int rgb, const std::string &text);
+};
+
+extern Color *textColor;
+
+#endif
diff --git a/src/gui/confirm_dialog.cpp b/src/gui/confirm_dialog.cpp
index 46b7c971..38697f3a 100644
--- a/src/gui/confirm_dialog.cpp
+++ b/src/gui/confirm_dialog.cpp
@@ -19,11 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "confirm_dialog.h"
-
-#include <guichan/widgets/label.hpp>
+#include <guichan/font.hpp>
#include "button.h"
+#include "confirm_dialog.h"
+#include "scrollarea.h"
+#include "textbox.h"
#include "../utils/gettext.h"
@@ -31,32 +32,55 @@ ConfirmDialog::ConfirmDialog(const std::string &title, const std::string &msg,
Window *parent):
Window(title, true, parent)
{
- gcn::Label *textLabel = new gcn::Label(msg);
+ mTextBox = new TextBox();
+ mTextBox->setEditable(false);
+ mTextBox->setOpaque(false);
+
+ mTextArea = new ScrollArea(mTextBox);
gcn::Button *yesButton = new Button(_("Yes"), "yes", this);
gcn::Button *noButton = new Button(_("No"), "no", this);
- int w = textLabel->getWidth() + 20;
+ mTextArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mTextArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mTextArea->setOpaque(false);
+
+ mTextBox->setTextWrapped(msg, 260);
+
+ int numRows = mTextBox->getNumberOfRows();
+ int width = getFont()->getWidth(title);
int inWidth = yesButton->getWidth() + noButton->getWidth() + 5;
- int h = textLabel->getHeight() + 25 + yesButton->getHeight();
- if (w < inWidth + 10) {
- w = inWidth + 10;
+ if (numRows > 1)
+ {
+ // 15 == height of each line of text (based on font heights)
+ // 14 == row top + bottom graphic pixel heights
+ setContentSize(mTextBox->getMinWidth() + 15, 15 + (numRows * 15) + noButton->getHeight());
+ mTextArea->setDimension(gcn::Rectangle(4, 5, mTextBox->getMinWidth() + 5,
+ 3 + (numRows * 14)));
+ }
+ else
+ {
+ if (width < getFont()->getWidth(msg))
+ width = getFont()->getWidth(msg);
+ if (width < inWidth)
+ width = inWidth;
+ setContentSize(width + 15, 30 + noButton->getHeight());
+ mTextArea->setDimension(gcn::Rectangle(4, 5, width + 5, 17));
}
- setContentSize(w, h);
- textLabel->setPosition(10, 10);
yesButton->setPosition(
- (w - inWidth) / 2,
- h - 5 - noButton->getHeight());
+ (mTextBox->getMinWidth() - inWidth) / 2,
+ (numRows * 14) + noButton->getHeight() - 8);
noButton->setPosition(
yesButton->getX() + yesButton->getWidth() + 5,
- h - 5 - noButton->getHeight());
+ (numRows * 14) + noButton->getHeight() - 8);
- add(textLabel);
+ add(mTextArea);
add(yesButton);
add(noButton);
- if (getParent()) {
+ if (getParent())
+ {
setLocationRelativeTo(getParent());
getParent()->moveToTop(this);
}
@@ -64,6 +88,11 @@ ConfirmDialog::ConfirmDialog(const std::string &title, const std::string &msg,
yesButton->requestFocus();
}
+unsigned int ConfirmDialog::getNumRows()
+{
+ return mTextBox->getNumberOfRows();
+}
+
void ConfirmDialog::action(const gcn::ActionEvent &event)
{
// Proxy button events to our listeners
diff --git a/src/gui/confirm_dialog.h b/src/gui/confirm_dialog.h
index 69b3e9e4..3fa2b90d 100644
--- a/src/gui/confirm_dialog.h
+++ b/src/gui/confirm_dialog.h
@@ -26,13 +26,16 @@
#include "window.h"
+class ScrollArea;
+class TextBox;
/**
* An option dialog.
*
* \ingroup GUI
*/
-class ConfirmDialog : public Window, public gcn::ActionListener {
+class ConfirmDialog : public Window, public gcn::ActionListener
+{
public:
/**
* Constructor.
@@ -42,10 +45,17 @@ class ConfirmDialog : public Window, public gcn::ActionListener {
ConfirmDialog(const std::string &title, const std::string &msg,
Window *parent = NULL);
+ unsigned int getNumRows();
+
/**
* Called when receiving actions from the widgets.
*/
void action(const gcn::ActionEvent &event);
+
+ private:
+ TextBox *mTextBox;
+ ScrollArea *mTextArea;
+ gcn::Button *okButton;
};
#endif
diff --git a/src/gui/connection.cpp b/src/gui/connection.cpp
index f73bb74d..a69698e9 100644
--- a/src/gui/connection.cpp
+++ b/src/gui/connection.cpp
@@ -19,20 +19,20 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "connection.h"
-
#include <guichan/actionlistener.hpp>
#include <guichan/widgets/label.hpp>
#include "button.h"
+#include "connection.h"
#include "progressbar.h"
#include "../main.h"
#include "../utils/gettext.h"
-namespace {
+namespace
+{
struct ConnectionActionListener : public gcn::ActionListener
{
void action(const gcn::ActionEvent &event) { state = EXIT_STATE; }
@@ -63,10 +63,10 @@ ConnectionDialog::ConnectionDialog():
void ConnectionDialog::logic()
{
mProgress += 0.005f;
+
if (mProgress > 1.0f)
- {
mProgress = 0.0f;
- }
+
mProgressBar->setProgress(mProgress);
Window::logic();
}
diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp
index 669aabd2..5a5acfad 100644
--- a/src/gui/debugwindow.cpp
+++ b/src/gui/debugwindow.cpp
@@ -19,14 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "debugwindow.h"
-
#include <SDL_mouse.h>
#include <guichan/widgets/label.hpp>
-#include "button.h"
-#include "gui.h"
+#include "debugwindow.h"
#include "viewport.h"
#include "widgets/layout.h"
diff --git a/src/gui/debugwindow.h b/src/gui/debugwindow.h
index 00119d15..e089de27 100644
--- a/src/gui/debugwindow.h
+++ b/src/gui/debugwindow.h
@@ -22,14 +22,10 @@
#ifndef DEBUGWINDOW_H
#define DEBUGWINDOW_H
-#include <iosfwd>
-
#include <guichan/actionlistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
-
/**
* The debug window.
*
diff --git a/src/gui/emotecontainer.cpp b/src/gui/emotecontainer.cpp
new file mode 100644
index 00000000..94ce9736
--- /dev/null
+++ b/src/gui/emotecontainer.cpp
@@ -0,0 +1,172 @@
+/*
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <guichan/mouseinput.hpp>
+#include <guichan/selectionlistener.hpp>
+
+#include "emotecontainer.h"
+
+#include "../animatedsprite.h"
+#include "../configuration.h"
+#include "../emoteshortcut.h"
+#include "../graphics.h"
+#include "../localplayer.h"
+#include "../log.h"
+
+#include "../resources/emotedb.h"
+#include "../resources/image.h"
+#include "../resources/iteminfo.h"
+#include "../resources/resourcemanager.h"
+
+#include "../utils/dtor.h"
+#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+const int EmoteContainer::gridWidth = 34; // emote icon width + 4
+const int EmoteContainer::gridHeight = 36; // emote icon height + 4
+
+static const int NO_EMOTE = -1;
+
+EmoteContainer::EmoteContainer():
+ mSelectedEmoteIndex(NO_EMOTE)
+{
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ // Setup emote sprites
+ for (int i = 0; i <= EmoteDB::getLast(); i++)
+ {
+ mEmoteImg.push_back(player_node->getEmote(i));
+ }
+
+ mSelImg = resman->getImage("graphics/gui/selection.png");
+ if (!mSelImg) logger->error(_("Unable to load selection.png"));
+
+ mSelImg->setAlpha(config.getValue("guialpha", 0.8));
+
+ mMaxEmote = EmoteDB::getLast() + 1;
+
+ addMouseListener(this);
+ addWidgetListener(this);
+}
+
+EmoteContainer::~EmoteContainer()
+{
+ if (!mSelImg)
+ {
+ mSelImg->decRef();
+ mSelImg = NULL;
+ }
+}
+
+void EmoteContainer::draw(gcn::Graphics *graphics)
+{
+ int columns = getWidth() / gridWidth;
+
+ // Have at least 1 column
+ if (columns < 1)
+ {
+ columns = 1;
+ }
+
+ for (int i = 0; i < mMaxEmote ; i++)
+ {
+ int emoteX = ((i) % columns) * gridWidth;
+ int emoteY = ((i) / columns) * gridHeight;
+
+ // Draw emote icon
+ mEmoteImg[i]->draw(static_cast<Graphics*>(graphics), emoteX, emoteY);
+
+ // Draw selection image below selected item
+ if (mSelectedEmoteIndex == i)
+ {
+ static_cast<Graphics*>(graphics)->drawImage(
+ mSelImg, emoteX, emoteY);
+ }
+ }
+}
+
+void EmoteContainer::widgetResized(const gcn::Event &event)
+{
+ recalculateHeight();
+}
+
+void EmoteContainer::recalculateHeight()
+{
+ int cols = getWidth() / gridWidth;
+
+ if (cols < 1)
+ cols = 1;
+
+ const int rows = (mMaxEmote / cols) + (mMaxEmote % cols > 0 ? 1 : 0);
+ const int height = rows * gridHeight + 8;
+ if (height != getHeight())
+ setHeight(height);
+}
+
+int EmoteContainer::getSelectedEmote()
+{
+ if (mSelectedEmoteIndex == NO_EMOTE)
+ return 0;
+
+ return 1 + mSelectedEmoteIndex;
+}
+
+void EmoteContainer::selectNone()
+{
+ setSelectedEmoteIndex(NO_EMOTE);
+}
+
+void EmoteContainer::setSelectedEmoteIndex(int index)
+{
+ if (index < 0 || index >= mMaxEmote )
+ mSelectedEmoteIndex = NO_EMOTE;
+ else
+ mSelectedEmoteIndex = index;
+}
+
+void EmoteContainer::distributeValueChangedEvent()
+{
+ gcn::SelectionEvent event(this);
+ std::list<gcn::SelectionListener*>::iterator i_end = mListeners.end();
+ std::list<gcn::SelectionListener*>::iterator i;
+
+ for (i = mListeners.begin(); i != i_end; ++i)
+ {
+ (*i)->valueChanged(event);
+ }
+}
+
+void EmoteContainer::mousePressed(gcn::MouseEvent &event)
+{
+ int button = event.getButton();
+ if (button == gcn::MouseEvent::LEFT || button == gcn::MouseEvent::RIGHT)
+ {
+ int columns = getWidth() / gridWidth;
+ int mx = event.getX();
+ int my = event.getY();
+ int index = mx / gridWidth + ((my / gridHeight) * columns);
+ if (index < mMaxEmote)
+ {
+ setSelectedEmoteIndex(index);
+ emoteShortcut->setEmoteSelected(index + 1);
+ }
+ }
+}
diff --git a/src/gui/emotecontainer.h b/src/gui/emotecontainer.h
new file mode 100644
index 00000000..fefce793
--- /dev/null
+++ b/src/gui/emotecontainer.h
@@ -0,0 +1,136 @@
+/*
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EMOTECONTAINER_H
+#define EMOTECONTAINER_H
+
+#include <list>
+#include <vector>
+
+#include <guichan/mouselistener.hpp>
+#include <guichan/widget.hpp>
+#include <guichan/widgetlistener.hpp>
+
+class AnimatedSprite;
+class Image;
+
+namespace gcn {
+ class SelectionListener;
+}
+
+/**
+ * An emote container. Used to show emotes in inventory and trade dialog.
+ *
+ * \ingroup GUI
+ */
+class EmoteContainer : public gcn::Widget,
+ public gcn::MouseListener,
+ public gcn::WidgetListener
+{
+ public:
+ /**
+ * Constructor. Initializes the graphic.
+ */
+ EmoteContainer();
+
+ /**
+ * Destructor.
+ */
+ virtual ~EmoteContainer();
+
+ /**
+ * Draws the emotes.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ /**
+ * Called whenever the widget changes size.
+ */
+ void widgetResized(const gcn::Event &event);
+
+ /**
+ * Handles mouse click.
+ */
+ void mousePressed(gcn::MouseEvent &event);
+
+ /**
+ * Returns the selected emote.
+ */
+ int getSelectedEmote();
+
+ /**
+ * Sets selected emote to NULL.
+ */
+ void selectNone();
+
+ /**
+ * Adds a listener to the list that's notified each time a change to
+ * the selection occurs.
+ */
+ void addSelectionListener(gcn::SelectionListener *listener)
+ {
+ mListeners.push_back(listener);
+ }
+
+ /**
+ * Removes a listener from the list that's notified each time a change
+ * to the selection occurs.
+ */
+ void removeSelectionListener(gcn::SelectionListener *listener)
+ {
+ mListeners.remove(listener);
+ }
+
+ private:
+ /**
+ * Sets the currently selected emote. Invalid (e.g., negative) indices
+ * set `no emotr'.
+ */
+ void setSelectedEmoteIndex(int index);
+
+ /**
+ * Find the current emote index by the most recently used emote ID
+ */
+ void refindSelectedEmote(void);
+
+ /**
+ * Determine and set the height of the container.
+ */
+ void recalculateHeight(void);
+
+ /**
+ * Sends out selection events to the list of selection listeners.
+ */
+ void distributeValueChangedEvent(void);
+
+ std::vector<AnimatedSprite*> mEmoteImg;
+ Image *mSelImg;
+ int mSelectedEmoteIndex;
+
+ int mMaxEmote;
+
+ std::list<gcn::SelectionListener*> mListeners;
+
+ static const int gridWidth;
+ static const int gridHeight;
+};
+
+#endif
diff --git a/src/gui/emoteshortcutcontainer.cpp b/src/gui/emoteshortcutcontainer.cpp
new file mode 100644
index 00000000..b66592c1
--- /dev/null
+++ b/src/gui/emoteshortcutcontainer.cpp
@@ -0,0 +1,204 @@
+/*
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "emoteshortcutcontainer.h"
+
+#include "../animatedsprite.h"
+#include "../configuration.h"
+#include "../emoteshortcut.h"
+#include "../graphics.h"
+#include "../inventory.h"
+#include "../item.h"
+#include "../itemshortcut.h"
+#include "../keyboardconfig.h"
+#include "../localplayer.h"
+#include "../log.h"
+
+#include "../resources/emotedb.h"
+#include "../resources/image.h"
+#include "../resources/resourcemanager.h"
+
+#include "../utils/dtor.h"
+#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+static const int MAX_ITEMS = 12;
+
+EmoteShortcutContainer::EmoteShortcutContainer():
+ ShortcutContainer(),
+ mEmoteClicked(false),
+ mEmoteMoved(0)
+{
+ addMouseListener(this);
+ addWidgetListener(this);
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png");
+
+ mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8));
+
+ // Setup emote sprites
+ for (int i = 0; i <= EmoteDB::getLast(); i++)
+ {
+ mEmoteImg.push_back(player_node->getEmote(i));
+ }
+
+ mMaxItems = EmoteDB::getLast() < MAX_ITEMS ? EmoteDB::getLast() : MAX_ITEMS;
+
+ mBoxHeight = mBackgroundImg->getHeight();
+ mBoxWidth = mBackgroundImg->getWidth();
+}
+
+EmoteShortcutContainer::~EmoteShortcutContainer()
+{
+ mBackgroundImg->decRef();
+}
+
+void EmoteShortcutContainer::draw(gcn::Graphics *graphics)
+{
+ Graphics *g = static_cast<Graphics*>(graphics);
+
+ graphics->setFont(getFont());
+
+ for (int i = 0; i < mMaxItems; i++)
+ {
+ const int emoteX = (i % mGridWidth) * mBoxWidth;
+ const int emoteY = (i / mGridWidth) * mBoxHeight;
+
+ g->drawImage(mBackgroundImg, emoteX, emoteY);
+
+ // Draw emote keyboard shortcut.
+ const char *key = SDL_GetKeyName(
+ (SDLKey) keyboard.getKeyValue(keyboard.KEY_EMOTE_1 + i));
+ graphics->setColor(0x000000);
+ g->drawText(key, emoteX + 2, emoteY + 2, gcn::Graphics::LEFT);
+
+ if (emoteShortcut->getEmote(i))
+ {
+ mEmoteImg[emoteShortcut->getEmote(i) - 1]->draw(g, emoteX + 2, emoteY + 10);
+ }
+
+ }
+
+ if (mEmoteMoved)
+ {
+ // Draw the emote image being dragged by the cursor.
+ AnimatedSprite* sprite = mEmoteImg[mEmoteMoved - 1];
+ if (sprite)
+ {
+ const int tPosX = mCursorPosX - (sprite->getWidth() / 2);
+ const int tPosY = mCursorPosY - (sprite->getHeight() / 2);
+
+ sprite->draw(g, tPosX, tPosY);
+ }
+ }
+
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ mBackgroundImg->setAlpha(mAlpha);
+ }
+}
+
+void EmoteShortcutContainer::mouseDragged(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ if (!mEmoteMoved && mEmoteClicked)
+ {
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ const int emoteId = emoteShortcut->getEmote(index);
+
+ if (index == -1)
+ {
+ return;
+ }
+
+ if (emoteId)
+ {
+ mEmoteMoved = emoteId;
+ emoteShortcut->removeEmote(index);
+ }
+ }
+ if (mEmoteMoved)
+ {
+ mCursorPosX = event.getX();
+ mCursorPosY = event.getY();
+ }
+ }
+}
+
+void EmoteShortcutContainer::mousePressed(gcn::MouseEvent &event)
+{
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+
+ if (index == -1)
+ {
+ return;
+ }
+
+ // Stores the selected emote if there is one.
+ if (emoteShortcut->isEmoteSelected())
+ {
+ emoteShortcut->setEmote(index);
+ emoteShortcut->setEmoteSelected(0);
+ }
+ else if (emoteShortcut->getEmote(index))
+ {
+ mEmoteClicked = true;
+ }
+}
+
+void EmoteShortcutContainer::mouseReleased(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+
+ if (emoteShortcut->isEmoteSelected())
+ {
+ emoteShortcut->setEmoteSelected(0);
+ }
+
+ if (index == -1)
+ {
+ mEmoteMoved = 0;
+ return;
+ }
+
+ if (mEmoteMoved)
+ {
+ emoteShortcut->setEmotes(index, mEmoteMoved);
+ mEmoteMoved = 0;
+ }
+ else if (emoteShortcut->getEmote(index) && mEmoteClicked)
+ {
+ emoteShortcut->useEmote(index + 1);
+ }
+
+ if (mEmoteClicked)
+ {
+ mEmoteClicked = false;
+ }
+ }
+}
+
diff --git a/src/gui/emoteshortcutcontainer.h b/src/gui/emoteshortcutcontainer.h
new file mode 100644
index 00000000..d32a9f79
--- /dev/null
+++ b/src/gui/emoteshortcutcontainer.h
@@ -0,0 +1,77 @@
+/*
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EMOTESHORTCUTCONTAINER_H
+#define EMOTESHORTCUTCONTAINER_H
+
+#include <vector>
+
+#include "shortcutcontainer.h"
+
+class AnimatedSprite;
+class Image;
+
+/**
+ * An emote shortcut container. Used to quickly use emoticons.
+ *
+ * \ingroup GUI
+ */
+class EmoteShortcutContainer : public ShortcutContainer
+{
+ public:
+ /**
+ * Constructor. Initializes the graphic.
+ */
+ EmoteShortcutContainer();
+
+ /**
+ * Destructor.
+ */
+ virtual ~EmoteShortcutContainer();
+
+ /**
+ * Draws the items.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ /**
+ * Handles mouse when dragged.
+ */
+ void mouseDragged(gcn::MouseEvent &event);
+
+ /**
+ * Handles mouse when pressed.
+ */
+ void mousePressed(gcn::MouseEvent &event);
+
+ /**
+ * Handles mouse release.
+ */
+ void mouseReleased(gcn::MouseEvent &event);
+
+ private:
+ std::vector<AnimatedSprite*> mEmoteImg;
+
+ bool mEmoteClicked;
+ int mEmoteMoved;
+};
+
+#endif
diff --git a/src/gui/emotewindow.cpp b/src/gui/emotewindow.cpp
new file mode 100644
index 00000000..f4a8999a
--- /dev/null
+++ b/src/gui/emotewindow.cpp
@@ -0,0 +1,77 @@
+/*
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "button.h"
+#include "gui.h"
+#include "emotewindow.h"
+#include "emotecontainer.h"
+#include "scrollarea.h"
+
+#include "widgets/layout.h"
+
+#include "../localplayer.h"
+
+#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+EmoteWindow::EmoteWindow():
+ Window(_("Emote"))
+{
+ setWindowName(_("Emote"));
+ setResizable(true);
+ setCloseButton(true);
+ setMinWidth(80);
+ setMinHeight(130);
+ setDefaultSize(115, 25, 322, 200);
+
+ mUseButton = new Button(_("Use"), "use", this);
+
+ mEmotes = new EmoteContainer();
+ mEmotes->addSelectionListener(this);
+
+ mEmoteScroll = new ScrollArea(mEmotes);
+ mEmoteScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+
+ place(0, 0, mEmoteScroll, 5, 4);
+ place(4, 4, mUseButton);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
+
+ mUseButton->setSize(60, mUseButton->getHeight());
+
+ loadWindowState();
+}
+
+void EmoteWindow::action(const gcn::ActionEvent &event)
+{
+ int emote = mEmotes->getSelectedEmote();
+
+ if (!emote)
+ return;
+
+ player_node->emote(emote);
+}
+
+int EmoteWindow::getSelectedEmote() const
+{
+ return mEmotes->getSelectedEmote();
+}
diff --git a/src/gui/buddywindow.h b/src/gui/emotewindow.h
index 4eed3a2c..8af24a7b 100644
--- a/src/gui/buddywindow.h
+++ b/src/gui/emotewindow.h
@@ -1,6 +1,6 @@
/*
- * The Mana World
- * Copyright (C) 2004 The Mana World Development Team
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
*
* This file is part of The Mana World.
*
@@ -19,38 +19,48 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef BUDDYWINDOW_H
-#define BUDDYWINDOW_H
+#ifndef EMOTEWINDOW_H
+#define EMOTEWINDOW_H
#include <guichan/actionlistener.hpp>
+#include <guichan/selectionlistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
-
-class BuddyList;
+class EmoteContainer;
+class TextBox;
/**
- * Window showing buddy list.
+ * Emote dialog.
*
* \ingroup Interface
*/
-class BuddyWindow : public Window, public gcn::ActionListener
+class EmoteWindow : public Window, gcn::ActionListener,
+ gcn::SelectionListener
{
public:
/**
* Constructor.
*/
- BuddyWindow();
+ EmoteWindow();
/**
- * Performs action.
+ * Called when receiving actions from the widgets.
*/
void action(const gcn::ActionEvent &event);
+ /**
+ * Returns the selected item.
+ */
+ int getSelectedEmote() const;
+
private:
- BuddyList *mBuddyList;
- gcn::ListBox *mListbox;
+ EmoteContainer *mEmotes;
+
+ gcn::Button *mUseButton;
+ gcn::ScrollArea *mEmoteScroll;
};
-#endif /* BUDDYWINDOW_H */
+extern EmoteWindow *emoteWindow;
+
+#endif
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index aa6825f2..a2be6b00 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -19,14 +19,22 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define BOX_WIDTH 36
+#define BOX_HEIGHT 36
+
+#include <guichan/font.hpp>
+
+#include "button.h"
#include "equipmentwindow.h"
+#include "itempopup.h"
+#include "playerbox.h"
+#include "viewport.h"
#include "../equipment.h"
-#include "../inventory.h"
-#include "../localplayer.h"
#include "../graphics.h"
+#include "../inventory.h"
#include "../item.h"
-#include "../log.h"
+#include "../localplayer.h"
#include "../resources/iteminfo.h"
#include "../resources/resourcemanager.h"
@@ -34,19 +42,60 @@
#include "../utils/gettext.h"
#include "../utils/tostring.h"
-EquipmentWindow::EquipmentWindow(Equipment *equipment):
+// Positions of the boxes, 2nd dimension is X and Y respectively.
+static const int boxPosition[][2] = {
+ {50, 208}, // EQUIP_LEGS_SLOT
+ {8, 123}, // EQUIP_FIGHT1_SLOT
+ {8, 78}, // EQUIP_GLOVES_SLOT
+ {129, 168}, // EQUIP_RING2_SLOT
+ {8, 168}, // EQUIP_RING1_SLOT
+ {129, 123}, // EQUIP_FIGHT2_SLOT
+ {90, 208}, // EQUIP_FEET_SLOT
+ {50, 40}, // EQUIP_CAPE_SLOT
+ {70, 0}, // EQUIP_HEAD_SLOT
+ {90, 40}, // EQUIP_TORSO_SLOT
+ {129, 78} // EQUIP_AMMO_SLOT
+};
+
+EquipmentWindow::EquipmentWindow():
Window(_("Equipment")),
- mEquipment(equipment)
+ mSelected(-1)
{
+ mItemPopup = new ItemPopup();
+
+ // Control that shows the Player
+ mPlayerBox = new PlayerBox;
+ mPlayerBox->setDimension(gcn::Rectangle(50, 80, 74, 123));
+ mPlayerBox->setPlayer(player_node);
+
setWindowName("Equipment");
setCloseButton(true);
- setDefaultSize(5, 230, 200, 140);
+ setDefaultSize(5, 195, 180, 300);
loadWindowState();
+
+ mUnequip = new Button(_("Unequip"), "unequip", this);
+ gcn::Rectangle const &area = getChildrenArea();
+ mUnequip->setPosition(area.width - mUnequip->getWidth() - 5,
+ area.height - mUnequip->getHeight() - 5);
+
+ add(mPlayerBox);
+ add(mUnequip);
+
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
+ {
+ mEquipBox[i].posX = boxPosition[i][0] + getPadding();
+ mEquipBox[i].posY = boxPosition[i][1] + getTitleBarHeight();
+ }
+
+ mEquipment = player_node->mEquipment.get();
mInventory = player_node->getInventory();
}
EquipmentWindow::~EquipmentWindow()
{
+ delete mUnequip;
+ delete mItemPopup;
+ delete mPlayerBox;
}
void EquipmentWindow::draw(gcn::Graphics *graphics)
@@ -54,37 +103,148 @@ void EquipmentWindow::draw(gcn::Graphics *graphics)
// Draw window graphics
Window::draw(graphics);
- Item *item;
- Image *image;
+ Item* item;
- // Rectangles around items are black
- graphics->setColor(gcn::Color(0, 0, 0));
+ Graphics *g = static_cast<Graphics*>(graphics);
- for (int i = 0; i < EQUIPMENT_SIZE; i++) {
- graphics->drawRectangle(gcn::Rectangle(10 + 36 * (i % 4),
- 36 * (i / 4) + 25, 32, 32));
+ Window::drawChildren(graphics);
- if (!(item = mInventory->getItem(mEquipment->getEquipment(i))))
- continue;
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
+ {
+ item = (i != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(i)) :
+ mInventory->getItem(mEquipment->getArrows());
+ if (item)
+ {
+ // Draw Item.
+ Image* image = item->getImage();
+ g->drawImage(image, mEquipBox[i].posX, mEquipBox[i].posY);
+ if (i == EQUIP_AMMO_SLOT)
+ {
+ g->setColor(gcn::Color(0, 0, 0));
+ graphics->drawText(toString(item->getQuantity()),
+ mEquipBox[i].posX + (BOX_WIDTH / 2),
+ mEquipBox[i].posY - getFont()->getHeight(),
+ gcn::Graphics::CENTER);
+ }
+ }
- image = item->getImage();
- if (image)
+ if (i == mSelected)
{
- static_cast<Graphics*>(graphics)->drawImage(
- image, 36 * (i % 4) + 10, 36 * (i / 4) + 25);
+ // Set color red.
+ g->setColor(gcn::Color(255, 0, 0));
}
+ else
+ {
+ // Set color black.
+ g->setColor(gcn::Color(0, 0, 0));
+ }
+
+ // Draw box border.
+ g->drawRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT));
}
+}
- graphics->drawRectangle(gcn::Rectangle(160, 25, 32, 32));
+void EquipmentWindow::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == "unequip" && mSelected > -1)
+ {
+ Item* item = (mSelected != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(mSelected)) :
+ mInventory->getItem(mEquipment->getArrows());
+ player_node->unequipItem(item);
+ mSelected = -1;
+ }
+}
- if (!(item = mInventory->getItem(mEquipment->getArrows())))
- return;
+Item* EquipmentWindow::getItem(const int &x, const int &y)
+{
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
+ {
+ gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT);
- image = item->getImage();
- if (image)
+ if (tRect.isPointInRect(x, y))
+ {
+ return (i != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(i)) :
+ mInventory->getItem(mEquipment->getArrows());
+ }
+ }
+ return NULL;
+}
+
+void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent)
+{
+ Window::mousePressed(mouseEvent);
+
+ const int x = mouseEvent.getX();
+ const int y = mouseEvent.getY();
+
+ Item* item;
+
+ if (mouseEvent.getButton() == gcn::MouseEvent::LEFT)
+ {
+ // Checks if any of the presses were in the equip boxes.
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
+ {
+ item = (i != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(i)) :
+ mInventory->getItem(mEquipment->getArrows());
+ gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT);
+
+ if (tRect.isPointInRect(x, y))
+ {
+ if (item)
+ {
+ mSelected = i;
+ }
+ }
+ }
+ }
+ else if (mouseEvent.getButton() == gcn::MouseEvent::RIGHT)
+ {
+ item = getItem(x, y);
+
+ if (!item)
+ return;
+
+ /* Convert relative to the window coordinates to absolute screen
+ * coordinates.
+ */
+ const int mx = x + getX();
+ const int my = y + getY();
+ viewport->showPopup(mx, my, item);
+ }
+}
+
+// Show ItemTooltip
+void EquipmentWindow::mouseMoved(gcn::MouseEvent &event)
+{
+ const int x = event.getX();
+ const int y = event.getY();
+
+ Item* item = getItem(x, y);
+
+ if (item)
+ {
+ int mouseX, mouseY;
+ SDL_GetMouseState(&mouseX, &mouseY);
+
+ mItemPopup->setItem(item->getInfo());
+ mItemPopup->setOpaque(false);
+ mItemPopup->view(x + getX(), y + getY());
+ }
+ else
{
- static_cast<Graphics*>(graphics)->drawImage(image, 160, 25);
+ mItemPopup->setVisible(false);
}
- graphics->drawText(toString(item->getQuantity()), 170, 62,
- gcn::Graphics::CENTER);
+}
+
+// Hide ItemTooltip
+void EquipmentWindow::mouseExited(gcn::MouseEvent &event)
+{
+ mItemPopup->setVisible(false);
}
diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h
index e2420134..c491062a 100644
--- a/src/gui/equipmentwindow.h
+++ b/src/gui/equipmentwindow.h
@@ -22,23 +22,37 @@
#ifndef EQUIPMENTWINDOW_H
#define EQUIPMENTWINDOW_H
+#include <guichan/actionlistener.hpp>
+
#include "window.h"
-#include "../inventory.h"
class Equipment;
+class Inventory;
+class Item;
+class ItemPopup;
+class PlayerBox;
+
+/**
+ * Equipment box.
+ */
+struct EquipBox
+{
+ int posX;
+ int posY;
+};
/**
* Equipment dialog.
*
* \ingroup Interface
*/
-class EquipmentWindow : public Window
+class EquipmentWindow : public Window, public gcn::ActionListener
{
public:
/**
* Constructor.
*/
- EquipmentWindow(Equipment *equipment);
+ EquipmentWindow();
/**
* Destructor.
@@ -50,9 +64,43 @@ class EquipmentWindow : public Window
*/
void draw(gcn::Graphics *graphics);
+ void action(const gcn::ActionEvent &event);
+
+ void mousePressed(gcn::MouseEvent& mouseEvent);
+
+ enum {
+ // Equipment rules:
+ EQUIP_LEGS_SLOT = 0,
+ EQUIP_FIGHT1_SLOT,
+ EQUIP_GLOVES_SLOT,
+ EQUIP_RING2_SLOT,
+ EQUIP_RING1_SLOT,
+ EQUIP_FIGHT2_SLOT,
+ EQUIP_FEET_SLOT,
+ EQUIP_CAPE_SLOT,
+ EQUIP_HEAD_SLOT,
+ EQUIP_TORSO_SLOT,
+ EQUIP_AMMO_SLOT,
+ EQUIP_VECTOREND
+ };
+
+
private:
+ void mouseExited(gcn::MouseEvent &event);
+ void mouseMoved(gcn::MouseEvent &event);
+
+ Item* getItem(const int &x, const int &y);
+
Equipment *mEquipment;
Inventory *mInventory;
+ gcn::Button *mUnequip; /**< Button for unequipping. */
+ EquipBox mEquipBox[EQUIP_VECTOREND]; /**< Equipment Boxes. */
+
+ ItemPopup *mItemPopup;
+
+ PlayerBox *mPlayerBox;
+
+ int mSelected; /**< Index of selected item. */
};
extern EquipmentWindow *equipmentWindow;
diff --git a/src/gui/focushandler.cpp b/src/gui/focushandler.cpp
index 3ceed595..b9cfd789 100644
--- a/src/gui/focushandler.cpp
+++ b/src/gui/focushandler.cpp
@@ -21,13 +21,12 @@
#include "focushandler.h"
-
void FocusHandler::requestModalFocus(gcn::Widget *widget)
{
/* If there is another widget with modal focus, remove its modal focus
* and put it on the modal widget stack.
*/
- if (mModalFocusedWidget != NULL && mModalFocusedWidget != widget)
+ if (mModalFocusedWidget && mModalFocusedWidget != widget)
{
mModalStack.push_front(mModalFocusedWidget);
mModalFocusedWidget = NULL;
diff --git a/src/gui/focushandler.h b/src/gui/focushandler.h
index 124b5472..b0639bd8 100644
--- a/src/gui/focushandler.h
+++ b/src/gui/focushandler.h
@@ -26,8 +26,6 @@
#include <guichan/focushandler.hpp>
-#include "../guichanfwd.h"
-
/**
* The focus handler. This focus handler does exactly the same as the Guichan
* focus handler, but keeps a stack of modal widgets to be able to handle
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index 2da451a3..87304bd1 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -19,13 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "gui.h"
-
#include <guichan/exception.hpp>
#include <guichan/image.hpp>
#include <guichan/imagefont.hpp>
#include "focushandler.h"
+#include "gui.h"
#include "sdlinput.h"
#include "truetypefont.h"
#include "viewport.h"
@@ -39,12 +38,12 @@
#include "../resources/image.h"
#include "../resources/imageset.h"
-#include "../resources/resourcemanager.h"
#include "../resources/imageloader.h"
+#include "../resources/resourcemanager.h"
// Guichan stuff
Gui *gui = 0;
-Viewport *viewport = 0; /**< Viewport on the map. */
+Viewport *viewport = 0; /**< Viewport on the map. */
SDLInput *guiInput = 0;
// Fonts used in showing hits
@@ -52,6 +51,9 @@ gcn::Font *hitRedFont = 0;
gcn::Font *hitBlueFont = 0;
gcn::Font *hitYellowFont = 0;
+// Bolded font
+gcn::Font *boldFont = 0;
+
class GuiConfigListener : public ConfigListener
{
public:
@@ -61,7 +63,8 @@ class GuiConfigListener : public ConfigListener
void optionChanged(const std::string &name)
{
- if (name == "customcursor") {
+ if (name == "customcursor")
+ {
bool bCustomCursor = config.getValue("customcursor", 1) == 1;
mGui->setUseCustomCursor(bCustomCursor);
}
@@ -105,7 +108,8 @@ Gui::Gui(Graphics *graphics):
// Set global font
std::string path = resman->getPath("fonts/dejavusans.ttf");
- try {
+ try
+ {
const int fontSize = config.getValue("fontSize", 11);
mGuiFont = new TrueTypeFont(path, fontSize);
}
@@ -115,14 +119,28 @@ Gui::Gui(Graphics *graphics):
+ e.getMessage());
}
+ // Set bold font
+ path = resman->getPath("fonts/dejavusans-bold.ttf");
+ try
+ {
+ const int fontSize = config.getValue("fontSize", 11);
+ boldFont = new TrueTypeFont(path, fontSize);
+ }
+ catch (gcn::Exception e)
+ {
+ logger->error(std::string("Unable to load dejavusans-bold.ttf: ")
+ + e.getMessage());
+ }
+
gcn::Widget::setGlobalFont(mGuiFont);
- // Load hits' colourful fonts
- try {
+ // Load hits' colorful fonts
+ try
+ {
hitRedFont = new gcn::ImageFont("graphics/gui/hits_red.png",
- "0123456789");
+ "0123456789crit! ");
hitBlueFont = new gcn::ImageFont("graphics/gui/hits_blue.png",
- "0123456789");
+ "0123456789crit! ");
hitYellowFont = new gcn::ImageFont("graphics/gui/hits_yellow.png",
"0123456789misxp ");
}
@@ -158,6 +176,7 @@ Gui::~Gui()
mMouseCursors->decRef();
delete mGuiFont;
+ delete boldFont;
delete viewport;
delete getTop();
@@ -167,12 +186,13 @@ Gui::~Gui()
void Gui::logic()
{
// Fade out mouse cursor after extended inactivity
- if (mMouseInactivityTimer < 100 * 15) {
+ if (mMouseInactivityTimer < 100 * 15)
+ {
++mMouseInactivityTimer;
mMouseCursorAlpha = std::min(1.0f, mMouseCursorAlpha + 0.05f);
- } else {
- mMouseCursorAlpha = std::max(0.0f, mMouseCursorAlpha - 0.005f);
}
+ else
+ mMouseCursorAlpha = std::max(0.0f, mMouseCursorAlpha - 0.005f);
gcn::Gui::logic();
}
@@ -217,9 +237,8 @@ void Gui::setUseCustomCursor(bool customCursor)
mMouseCursors =
resman->getImageSet("graphics/gui/mouse.png", 40, 40);
- if (!mMouseCursors) {
+ if (!mMouseCursors)
logger->error("Unable to load mouse cursors.");
- }
}
else
{
@@ -227,7 +246,8 @@ void Gui::setUseCustomCursor(bool customCursor)
SDL_ShowCursor(SDL_ENABLE);
// Unload the mouse cursor
- if (mMouseCursors) {
+ if (mMouseCursors)
+ {
mMouseCursors->decRef();
mMouseCursors = NULL;
}
diff --git a/src/gui/gui.h b/src/gui/gui.h
index 95cd5815..5c0c24f7 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -26,8 +26,8 @@
#include "../guichanfwd.h"
-class GuiConfigListener;
class Graphics;
+class GuiConfigListener;
class ImageSet;
class SDLInput;
class Viewport;
@@ -115,7 +115,6 @@ class Gui : public gcn::Gui
};
extern Gui *gui; /**< The GUI system */
-extern Viewport *viewport; /**< The viewport */
extern SDLInput *guiInput; /**< GUI input */
/**
@@ -125,4 +124,9 @@ extern gcn::Font *hitRedFont;
extern gcn::Font *hitBlueFont;
extern gcn::Font *hitYellowFont;
+/**
+ * Bolded text font
+ */
+extern gcn::Font *boldFont;
+
#endif
diff --git a/src/gui/help.cpp b/src/gui/help.cpp
index 390cb44e..ece2dce4 100644
--- a/src/gui/help.cpp
+++ b/src/gui/help.cpp
@@ -19,12 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "help.h"
-
#include "button.h"
#include "browserbox.h"
+#include "help.h"
#include "scrollarea.h"
+#include "widgets/layout.h"
+
#include "../resources/resourcemanager.h"
#include "../utils/gettext.h"
@@ -32,8 +33,11 @@
HelpWindow::HelpWindow():
Window(_("Help"))
{
+ setMinWidth(300);
+ setMinHeight(250);
setContentSize(455, 350);
- setWindowName("Help");
+ setWindowName(_("Help"));
+ setResizable(true);
mBrowserBox = new BrowserBox();
mBrowserBox->setOpaque(false);
@@ -48,8 +52,11 @@ HelpWindow::HelpWindow():
mBrowserBox->setLinkHandler(this);
- add(mScrollArea);
- add(okButton);
+ place(0, 0, mScrollArea, 5, 3).setPadding(3);
+ place(4, 3, okButton);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
setLocationRelativeTo(getParent());
}
diff --git a/src/gui/help.h b/src/gui/help.h
index e3d9246d..98e3aa67 100644
--- a/src/gui/help.h
+++ b/src/gui/help.h
@@ -24,10 +24,8 @@
#include <guichan/actionlistener.hpp>
-#include "window.h"
#include "linkhandler.h"
-
-#include "../guichanfwd.h"
+#include "window.h"
class BrowserBox;
diff --git a/src/gui/inttextfield.cpp b/src/gui/inttextfield.cpp
index eb61c4d7..fcbe938d 100644
--- a/src/gui/inttextfield.cpp
+++ b/src/gui/inttextfield.cpp
@@ -20,7 +20,6 @@
*/
#include "inttextfield.h"
-
#include "sdlinput.h"
#include "../utils/tostring.h"
diff --git a/src/gui/inttextfield.h b/src/gui/inttextfield.h
index 4dfef8e1..add78084 100644
--- a/src/gui/inttextfield.h
+++ b/src/gui/inttextfield.h
@@ -58,8 +58,7 @@ class IntTextField : public TextField
/**
* Responds to key presses.
*/
- void
- keyPressed(gcn::KeyEvent &event);
+ void keyPressed(gcn::KeyEvent &event);
private:
int mMin; /**< Minimum value */
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index 31ebb86e..af3b29a2 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -19,72 +19,101 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "inventorywindow.h"
-
#include <string>
+#include <guichan/font.hpp>
#include <guichan/mouseinput.hpp>
+
#include <guichan/widgets/label.hpp>
#include "button.h"
-#include "gui.h"
+#include "inventorywindow.h"
#include "item_amount.h"
#include "itemcontainer.h"
+#include "progressbar.h"
#include "scrollarea.h"
#include "viewport.h"
+#include "widgets/layout.h"
+
#include "../inventory.h"
#include "../item.h"
-#include "../localplayer.h"
#include "../resources/iteminfo.h"
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
+#include "../utils/tostring.h"
-InventoryWindow::InventoryWindow():
- Window(_("Inventory"))
+InventoryWindow::InventoryWindow(int invSize):
+ Window(_("Inventory")),
+ mMaxSlots(invSize),
+ mItemDesc(false)
{
- setWindowName("Inventory");
+ setWindowName(_("Inventory"));
setResizable(true);
setCloseButton(true);
- setMinWidth(240);
- setMinHeight(172);
+
// If you adjust these defaults, don't forget to adjust the trade window's.
- setDefaultSize(115, 25, 322, 200);
+ setDefaultSize(115, 25, 375, 300);
- mUseButton = new Button(_("Use"), "use", this);
+ std::string longestUseString = getFont()->getWidth(_("Equip")) >
+ getFont()->getWidth(_("Use")) ?
+ _("Equip") : _("Use");
+
+ if (getFont()->getWidth(longestUseString) <
+ getFont()->getWidth(_("Unequip")))
+ {
+ longestUseString = _("Unequip");
+ }
+
+ mUseButton = new Button(longestUseString, "use", this);
mDropButton = new Button(_("Drop"), "drop", this);
- mItems = new ItemContainer(player_node->getInventory());
+ mItems = new ItemContainer(player_node->getInventory(), 2);
mItems->addSelectionListener(this);
mInvenScroll = new ScrollArea(mItems);
mInvenScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- mItemNameLabel = new gcn::Label("Name:");
- mItemDescriptionLabel = new gcn::Label("Description:");
- mItemEffectLabel = new gcn::Label("Effect:");
- mWeightLabel = new gcn::Label("Weight:");
- mWeightLabel->setPosition(8, 8);
- mInvenScroll->setPosition(8,
- mWeightLabel->getY() + mWeightLabel->getHeight() + 5);
- mInvenSlotLabel = new gcn::Label("Slots used:");
- mInvenSlotLabel->setPosition(mWeightLabel->getX()
- + mWeightLabel->getWidth() + 100, 8);
-
- add(mUseButton);
- add(mDropButton);
- add(mInvenScroll);
- add(mItemNameLabel);
- add(mItemDescriptionLabel);
- add(mItemEffectLabel);
- add(mWeightLabel);
- add(mInvenSlotLabel);
-
- mUseButton->setSize(60, mUseButton->getHeight());
+ mTotalWeight = toString(player_node->mTotalWeight);
+ mMaxWeight = toString(player_node->mMaxWeight);
+ mUsedSlots = toString(player_node->getInventory()->getNumberOfSlotsUsed());
+
+ mSlotsLabel = new gcn::Label(_("Slots: "));
+ mWeightLabel = new gcn::Label(_("Weight: "));
+
+ mSlotsBar = new ProgressBar(1.0f, 100, 20, 225, 200, 25);
+ mWeightBar = new ProgressBar(1.0f, 100, 20, 0, 0, 255);
+
+ setMinHeight(130);
+ setMinWidth(mWeightLabel->getWidth() + mSlotsLabel->getWidth() + 280);
+
+ place(0, 0, mWeightLabel).setPadding(3);
+ place(1, 0, mWeightBar, 3);
+ place(4, 0, mSlotsLabel).setPadding(3);
+ place(5, 0, mSlotsBar, 2);
+ place(0, 1, mInvenScroll, 7, 4);
+ place(5, 5, mDropButton);
+ place(6, 5, mUseButton);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, mDropButton->getHeight());
loadWindowState();
+ setLocationRelativeTo(getParent());
+}
+
+InventoryWindow::~InventoryWindow()
+{
+ delete mWeightBar;
+ delete mSlotsBar;
+ delete mUseButton;
+ delete mDropButton;
+ delete mItems;
+ delete mWeightLabel;
+ delete mSlotsLabel;
+ delete mInvenScroll;
}
void InventoryWindow::logic()
@@ -95,15 +124,39 @@ void InventoryWindow::logic()
// redesign of InventoryWindow and ItemContainer probably.
updateButtons();
- // Update weight information
- mWeightLabel->setCaption(strprintf(_("Weight: %d / %d"),
- player_node->mTotalWeight,
- player_node->mMaxWeight));
+ if ((mMaxWeight != toString(player_node->mMaxWeight)) ||
+ mTotalWeight != toString(player_node->mTotalWeight) ||
+ mUsedSlots != toString(player_node->getInventory()->getNumberOfSlotsUsed()))
+ {
+ mTotalWeight = toString(player_node->mTotalWeight);
+ mMaxWeight = toString(player_node->mMaxWeight);
+ mUsedSlots = toString(player_node->getInventory()->getNumberOfSlotsUsed());
+
+ // Weight Bar coloration
+ if (int(player_node->mTotalWeight) < int(player_node->mMaxWeight / 3))
+ {
+ mWeightBar->setColor(0, 0, 255); // Blue
+ }
+ else if (int(player_node->mTotalWeight) <
+ int((player_node->mMaxWeight / 3) * 2))
+ {
+ mWeightBar->setColor(255, 255, 0); // Yellow
+ }
+ else
+ {
+ mWeightBar->setColor(255, 0, 0); // Red
+ }
+
+ // Adjust progress bars
+ mSlotsBar->setProgress((float)
+ player_node->getInventory()->getNumberOfSlotsUsed() / mMaxSlots);
+ mWeightBar->setProgress((float) player_node->mTotalWeight /
+ player_node->mMaxWeight);
- // Update number of items in inventory
- mInvenSlotLabel->setCaption(strprintf(_("Slots used: %d / %d"),
- player_node->getInventory()->getNumberOfSlotsUsed(),
- player_node->getInventory()->getInventorySize()));
+ mSlotsBar->setText(strprintf("%s/%d", mUsedSlots.c_str(), mMaxSlots));
+ mWeightBar->setText(strprintf("%sg/%sg", mTotalWeight.c_str(),
+ mMaxWeight.c_str()));
+ }
}
void InventoryWindow::action(const gcn::ActionEvent &event)
@@ -113,55 +166,30 @@ void InventoryWindow::action(const gcn::ActionEvent &event)
if (!item)
return;
- if (event.getId() == "use") {
- if (item->isEquipment()) {
- if (item->isEquipped()) {
+ if (event.getId() == "use")
+ {
+ if (item->isEquipment())
+ {
+ if (item->isEquipped())
player_node->unequipItem(item);
- }
- else {
+ else
player_node->equipItem(item);
- }
}
- else {
+ else
player_node->useItem(item);
- }
}
else if (event.getId() == "drop")
{
- if (item->getQuantity() == 1) {
+ if (item->getQuantity() == 1)
player_node->dropItem(item, 1);
- }
- else {
+ else
+ {
// Choose amount of items to drop
new ItemAmountWindow(AMOUNT_ITEM_DROP, this, item);
}
}
}
-void InventoryWindow::valueChanged(const gcn::SelectionEvent &event)
-{
- const Item *item = mItems->getSelectedItem();
-
- // Update name, effect and description
- if (!item)
- {
- mItemNameLabel->setCaption(strprintf(_("Name: %s"), ""));
- mItemEffectLabel->setCaption(strprintf(_("Effect: %s"), ""));
- mItemDescriptionLabel->setCaption(strprintf(_("Description: %s"), ""));
- }
- else
- {
- const ItemInfo& itemInfo = item->getInfo();
- mItemNameLabel->setCaption(
- strprintf(_("Name: %s"), itemInfo.getName().c_str()));
- mItemEffectLabel->setCaption(
- strprintf(_("Effect: %s"), itemInfo.getEffect().c_str()));
- mItemDescriptionLabel->setCaption(
- strprintf(_("Description: %s"),
- itemInfo.getDescription().c_str()));
- }
-}
-
void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
{
Window::mouseClicked(event);
@@ -182,55 +210,19 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
}
}
-void InventoryWindow::widgetResized(const gcn::Event &event)
-{
- Window::widgetResized(event);
-
- const gcn::Rectangle &area = getChildrenArea();
- const int width = area.width;
- const int height = area.height;
-
- // Adjust widgets
- mUseButton->setPosition(8, height - 8 - mUseButton->getHeight());
- mDropButton->setPosition(8 + mUseButton->getWidth() + 5,
- mUseButton->getY());
-
- mItemNameLabel->setDimension(gcn::Rectangle(8,
- mUseButton->getY() - 5 - mItemNameLabel->getHeight(),
- width - 16,
- mItemNameLabel->getHeight()));
- mItemEffectLabel->setDimension(gcn::Rectangle(8,
- mItemNameLabel->getY() - 5 - mItemEffectLabel->getHeight(),
- width - 16,
- mItemEffectLabel->getHeight()));
- mItemDescriptionLabel->setDimension(gcn::Rectangle(8,
- mItemEffectLabel->getY() - 5 - mItemDescriptionLabel->getHeight(),
- width - 16,
- mItemDescriptionLabel->getHeight()));
-
- mInvenScroll->setSize(width - 16,
- mItemDescriptionLabel->getY() - mWeightLabel->getHeight() - 18);
-
- mWeightLabel->setWidth(width - 16);
- mInvenSlotLabel->setWidth(width - 16);
-}
-
void InventoryWindow::updateButtons()
{
const Item *selectedItem = mItems->getSelectedItem();
if (selectedItem && selectedItem->isEquipment())
{
- if (selectedItem->isEquipped()) {
+ if (selectedItem->isEquipped())
mUseButton->setCaption(_("Unequip"));
- }
- else {
+ else
mUseButton->setCaption(_("Equip"));
- }
}
- else {
+ else
mUseButton->setCaption(_("Use"));
- }
mUseButton->setEnabled(selectedItem != 0);
mDropButton->setEnabled(selectedItem != 0);
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index 402ab0d2..78d30461 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -27,10 +27,12 @@
#include "window.h"
-#include "../guichanfwd.h"
+#include "../localplayer.h"
class Item;
class ItemContainer;
+class ProgressBar;
+class TextBox;
/**
* Inventory dialog.
@@ -38,13 +40,18 @@ class ItemContainer;
* \ingroup Interface
*/
class InventoryWindow : public Window, gcn::ActionListener,
- gcn::SelectionListener
+ gcn::SelectionListener
{
public:
/**
* Constructor.
*/
- InventoryWindow();
+ InventoryWindow(int invSize = (INVENTORY_SIZE - 2));
+
+ /**
+ * Destructor.
+ */
+ ~InventoryWindow();
/**
* Logic (updates buttons and weight information).
@@ -61,30 +68,30 @@ class InventoryWindow : public Window, gcn::ActionListener,
*/
Item* getSelectedItem() const;
- /**
- * Updates labels to currently selected item.
- */
- void valueChanged(const gcn::SelectionEvent &event);
-
void mouseClicked(gcn::MouseEvent &event);
- /**
- * Called whenever the widget changes size.
- */
- void widgetResized(const gcn::Event &event);
-
private:
void updateButtons(); /**< Updates button states. */
ItemContainer *mItems;
+ std::string mWeight;
+ std::string mSlots;
+ std::string mUsedSlots;
+ std::string mTotalWeight;
+ std::string mMaxWeight;
gcn::Button *mUseButton, *mDropButton;
gcn::ScrollArea *mInvenScroll;
- gcn::Label *mItemNameLabel;
- gcn::Label *mItemDescriptionLabel;
- gcn::Label *mItemEffectLabel;
+
gcn::Label *mWeightLabel;
- gcn::Label *mInvenSlotLabel;
+ gcn::Label *mSlotsLabel;
+
+ ProgressBar *mWeightBar;
+ ProgressBar *mSlotsBar;
+
+ int mMaxSlots;
+
+ bool mItemDesc;
};
extern InventoryWindow *inventoryWindow;
diff --git a/src/gui/item_amount.cpp b/src/gui/item_amount.cpp
index 7ef3d71b..92be3d6e 100644
--- a/src/gui/item_amount.cpp
+++ b/src/gui/item_amount.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "item_amount.h"
-
#include "button.h"
#include "inttextfield.h"
+#include "item_amount.h"
#include "slider.h"
#include "trade.h"
@@ -71,7 +70,8 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item):
resetAmount();
- switch (usage) {
+ switch (usage)
+ {
case AMOUNT_TRADE_ADD:
setCaption(_("Select amount of items to trade."));
okButton->setActionEventId("AddTrade");
diff --git a/src/gui/item_amount.h b/src/gui/item_amount.h
index d8eedadb..618d7d51 100644
--- a/src/gui/item_amount.h
+++ b/src/gui/item_amount.h
@@ -22,14 +22,10 @@
#ifndef ITEM_AMOUNT_WINDOW_H
#define ITEM_AMOUNT_WINDOW_H
-#include <iosfwd>
-
#include <guichan/actionlistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
-
class IntTextField;
class Item;
diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp
index a0885279..0beb5cfb 100644
--- a/src/gui/itemcontainer.cpp
+++ b/src/gui/itemcontainer.cpp
@@ -21,17 +21,21 @@
#include "itemcontainer.h"
+#include "itempopup.h"
+
#include <guichan/mouseinput.hpp>
#include <guichan/selectionlistener.hpp>
+#include <SDL_mouse.h>
+
#include "../graphics.h"
#include "../inventory.h"
#include "../item.h"
#include "../itemshortcut.h"
+#include "../localplayer.h"
#include "../log.h"
#include "../resources/image.h"
-#include "../resources/iteminfo.h"
#include "../resources/resourcemanager.h"
#include "../utils/tostring.h"
@@ -41,11 +45,14 @@ const int ItemContainer::gridHeight = 42; // item icon height + 10
static const int NO_ITEM = -1;
-ItemContainer::ItemContainer(Inventory *inventory):
+ItemContainer::ItemContainer(Inventory *inventory, int offset):
mInventory(inventory),
mSelectedItemIndex(NO_ITEM),
- mLastSelectedItemId(NO_ITEM)
+ mLastSelectedItemId(NO_ITEM),
+ mOffset(offset)
{
+ mItemPopup = new ItemPopup();
+
ResourceManager *resman = ResourceManager::getInstance();
mSelImg = resman->getImage("graphics/gui/selection.png");
@@ -60,6 +67,7 @@ ItemContainer::ItemContainer(Inventory *inventory):
ItemContainer::~ItemContainer()
{
mSelImg->decRef();
+ delete mItemPopup;
}
void ItemContainer::logic()
@@ -86,10 +94,11 @@ void ItemContainer::draw(gcn::Graphics *graphics)
}
/*
- * eAthena seems to start inventory from the 3rd slot. Still a mystery to
- * us why, make sure not to copy this oddity to our own server.
+ * mOffset is used to compensate for some weirdness that eAthena inherited from
+ * Ragnarok Online. Inventory slots and cart slots are +2 from their actual index,
+ * while storage slots are +1.
*/
- for (int i = 2; i < INVENTORY_SIZE; i++)
+ for (int i = mOffset; i < mInventory->getSize(); i++)
{
Item *item = mInventory->getItem(i);
@@ -115,6 +124,7 @@ void ItemContainer::draw(gcn::Graphics *graphics)
}
// Draw item caption
+ graphics->setFont(getFont());
graphics->setColor(gcn::Color(0, 0, 0));
graphics->drawText(
(item->isEquipped() ? "Eq." : toString(item->getQuantity())),
@@ -138,6 +148,7 @@ void ItemContainer::recalculateHeight()
const int rows = (mMaxItems / cols) + (mMaxItems % cols > 0 ? 1 : 0);
const int height = rows * gridHeight + 8;
+
if (height != getHeight())
setHeight(height);
}
@@ -159,8 +170,8 @@ void ItemContainer::selectNone()
void ItemContainer::refindSelectedItem()
{
- if (mSelectedItemIndex != NO_ITEM) {
-
+ if (mSelectedItemIndex != NO_ITEM)
+ {
if (mInventory->getItem(mSelectedItemIndex) &&
mInventory->getItem(mSelectedItemIndex)->getId() == mLastSelectedItemId)
return; // we're already fine
@@ -170,7 +181,8 @@ void ItemContainer::refindSelectedItem()
for (int i = 0; i <= mMaxItems + 1; i++)
if (mInventory->getItem(i) &&
- mInventory->getItem(i)->getId() == mLastSelectedItemId) {
+ mInventory->getItem(i)->getId() == mLastSelectedItemId)
+ {
mSelectedItemIndex = i;
return;
}
@@ -179,14 +191,16 @@ void ItemContainer::refindSelectedItem()
mLastSelectedItemId = mSelectedItemIndex = NO_ITEM;
}
-
void ItemContainer::setSelectedItemIndex(int index)
{
int newSelectedItemIndex;
- // mMaxItems is broken because of eAthena's odd inventory layout and the client's refusal
- // to handle it properly, so we work around the issue right here.
- if (index < 0 || index > mMaxItems + 1 || mInventory->getItem(index) == NULL)
+ /*
+ * mOffset is used to compensate for some weirdness that eAthena inherited from
+ * Ragnarok Online. Inventory slots and cart slots are +2 from their actual index,
+ * while storage slots are +1.
+ */
+ if (index < 0 || index > mMaxItems + mOffset || mInventory->getItem(index) == NULL)
newSelectedItemIndex = NO_ITEM;
else
newSelectedItemIndex = index;
@@ -218,14 +232,14 @@ void ItemContainer::distributeValueChangedEvent()
void ItemContainer::mousePressed(gcn::MouseEvent &event)
{
- int button = event.getButton();
+ const int button = event.getButton();
if (button == gcn::MouseEvent::LEFT || button == gcn::MouseEvent::RIGHT)
{
int columns = getWidth() / gridWidth;
int mx = event.getX();
int my = event.getY();
- int index = mx / gridWidth + ((my / gridHeight) * columns) + 2;
+ int index = mx / gridWidth + ((my / gridHeight) * columns) + mOffset;
itemShortcut->setItemSelected(-1);
setSelectedItemIndex(index);
@@ -236,3 +250,38 @@ void ItemContainer::mousePressed(gcn::MouseEvent &event)
itemShortcut->setItemSelected(item->getId());
}
}
+
+// Show ItemTooltip
+void ItemContainer::mouseMoved(gcn::MouseEvent &event)
+{
+ Item *item = mInventory->getItem(getSlotIndex(event.getX(), event.getY()));
+
+ if (item)
+ {
+ int mouseX, mouseY;
+ SDL_GetMouseState(&mouseX, &mouseY);
+
+ mItemPopup->setItem(item->getInfo());
+ mItemPopup->setOpaque(false);
+ mItemPopup->view(mouseX, mouseY);
+ }
+ else
+ {
+ mItemPopup->setVisible(false);
+ }
+}
+
+// Hide ItemTooltip
+void ItemContainer::mouseExited(gcn::MouseEvent &event)
+{
+ mItemPopup->setVisible(false);
+}
+
+int ItemContainer::getSlotIndex(const int posX, const int posY) const
+{
+ int columns = getWidth() / gridWidth;
+ int index = posX / gridWidth + ((posY / gridHeight) * columns) + mOffset;
+
+ return (index);
+}
+
diff --git a/src/gui/itemcontainer.h b/src/gui/itemcontainer.h
index a40237af..71fcc5d0 100644
--- a/src/gui/itemcontainer.h
+++ b/src/gui/itemcontainer.h
@@ -22,15 +22,16 @@
#ifndef ITEMCONTAINER_H
#define ITEMCONTAINER_H
+#include <list>
+
#include <guichan/mouselistener.hpp>
#include <guichan/widget.hpp>
#include <guichan/widgetlistener.hpp>
-#include <list>
-
class Image;
class Inventory;
class Item;
+class ItemPopup;
namespace gcn {
class SelectionListener;
@@ -41,14 +42,15 @@ namespace gcn {
*
* \ingroup GUI
*/
-class ItemContainer : public gcn::Widget, public gcn::MouseListener,
- public gcn::WidgetListener
+class ItemContainer : public gcn::Widget,
+ public gcn::MouseListener,
+ public gcn::WidgetListener
{
public:
/**
* Constructor. Initializes the graphic.
*/
- ItemContainer(Inventory *inventory);
+ ItemContainer(Inventory *inventory, int offset);
/**
* Destructor.
@@ -104,7 +106,11 @@ class ItemContainer : public gcn::Widget, public gcn::MouseListener,
}
private:
+ void mouseExited(gcn::MouseEvent &event);
+ void mouseMoved(gcn::MouseEvent &event);
+
/**
+
* Sets the currently selected item. Invalid (e.g., negative) indices set `no item'.
*/
void setSelectedItemIndex(int index);
@@ -124,12 +130,24 @@ class ItemContainer : public gcn::Widget, public gcn::MouseListener,
*/
void distributeValueChangedEvent();
+ /**
+ * Gets the slot index based on the cursor position.
+ *
+ * @param posX The X Coordinate position.
+ * @param posY The Y Coordinate position.
+ * @return The slot index on success, -1 on failure.
+ */
+ int getSlotIndex(const int posX, const int posY) const;
+
Inventory *mInventory;
Image *mSelImg;
- int mSelectedItemIndex;
- int mLastSelectedItemId; // last selected item ID. If we lose the item, find again by ID.
+ int mSelectedItemIndex;
+ int mLastSelectedItemId; // last selected item ID. If we lose the item, find again by ID.
int mMaxItems;
+ int mOffset;
+
+ ItemPopup *mItemPopup;
std::list<gcn::SelectionListener*> mListeners;
diff --git a/src/gui/itemlinkhandler.cpp b/src/gui/itemlinkhandler.cpp
new file mode 100644
index 00000000..97c0b94f
--- /dev/null
+++ b/src/gui/itemlinkhandler.cpp
@@ -0,0 +1,63 @@
+/*
+ * The Mana World
+ * Copyright 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sstream>
+#include <string>
+
+#include <SDL_mouse.h>
+
+#include "itemlinkhandler.h"
+#include "itempopup.h"
+
+#include "../resources/iteminfo.h"
+#include "../resources/itemdb.h"
+
+ItemLinkHandler::ItemLinkHandler()
+{
+ mItemPopup = new ItemPopup;
+}
+
+ItemLinkHandler::~ItemLinkHandler()
+{
+ delete mItemPopup;
+}
+
+void ItemLinkHandler::handleLink(const std::string &link)
+{
+ int id = 0;
+ std::stringstream stream;
+ stream << link;
+ stream >> id;
+ if (id > 0)
+ {
+ const ItemInfo &iteminfo = ItemDB::get(id);
+ int mouseX, mouseY;
+
+ SDL_GetMouseState(&mouseX, &mouseY);
+
+ mItemPopup->setItem(iteminfo);
+
+ if (mItemPopup->isVisible())
+ mItemPopup->setVisible(false);
+ else
+ mItemPopup->view(mouseX, mouseY);
+ }
+}
diff --git a/src/gui/itemlinkhandler.h b/src/gui/itemlinkhandler.h
new file mode 100644
index 00000000..cd6fd900
--- /dev/null
+++ b/src/gui/itemlinkhandler.h
@@ -0,0 +1,40 @@
+/*
+ * The Mana World
+ * Copyright 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef ITEM_LINK_HANDLER_H_
+#define ITEM_LINK_HANDLER_H_
+
+#include "linkhandler.h"
+
+class ItemPopup;
+
+class ItemLinkHandler : public LinkHandler
+{
+ public:
+ ItemLinkHandler();
+ ~ItemLinkHandler();
+ void handleLink(const std::string &link);
+
+ private:
+ ItemPopup *mItemPopup;
+};
+
+#endif
diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp
new file mode 100644
index 00000000..4c117f0a
--- /dev/null
+++ b/src/gui/itempopup.cpp
@@ -0,0 +1,216 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Legend of Mazzeroth Development Team
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <guichan/font.hpp>
+
+#include <guichan/widgets/label.hpp>
+
+#include "gui.h"
+#include "itempopup.h"
+#include "scrollarea.h"
+#include "textbox.h"
+#include "windowcontainer.h"
+
+#include "widgets/layout.h"
+
+#include "../resources/iteminfo.h"
+
+#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+ItemPopup::ItemPopup():
+ Window()
+{
+ setResizable(false);
+ setShowTitle(false);
+ setTitleBarHeight(0);
+
+ // Item Name
+ mItemName = new gcn::Label("Label");
+ mItemName->setFont(boldFont);
+ mItemName->setPosition(2, 2);
+
+ // Item Description
+ mItemDesc = new TextBox();
+ mItemDesc->setEditable(false);
+ mItemDescScroll = new ScrollArea(mItemDesc);
+
+ mItemDescScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemDescScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemDescScroll->setDimension(gcn::Rectangle(0, 0, 196, getFont()->getHeight()));
+ mItemDescScroll->setOpaque(false);
+ mItemDescScroll->setPosition(2, getFont()->getHeight());
+
+ // Item Effect
+ mItemEffect = new TextBox();
+ mItemEffect->setEditable(false);
+ mItemEffectScroll = new ScrollArea(mItemEffect);
+
+ mItemEffectScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemEffectScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemEffectScroll->setDimension(gcn::Rectangle(0, 0, 196, getFont()->getHeight()));
+ mItemEffectScroll->setOpaque(false);
+ mItemEffectScroll->setPosition(2, (2 * getFont()->getHeight()) + 5);
+
+ // Item Weight
+ mItemWeight = new TextBox();
+ mItemWeight->setEditable(false);
+ mItemWeightScroll = new ScrollArea(mItemWeight);
+
+ mItemWeightScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemWeightScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemWeightScroll->setDimension(gcn::Rectangle(0, 0, 196, getFont()->getHeight()));
+ mItemWeightScroll->setOpaque(false);
+ mItemWeightScroll->setPosition(2, (3 * getFont()->getHeight()) + 10);
+
+ add(mItemName);
+ add(mItemDescScroll);
+ add(mItemEffectScroll);
+ add(mItemWeightScroll);
+
+ setLocationRelativeTo(getParent());
+}
+
+ItemPopup::~ItemPopup()
+{
+ delete mItemName;
+ delete mItemDesc;
+ delete mItemDescScroll;
+ delete mItemEffect;
+ delete mItemEffectScroll;
+ delete mItemWeight;
+ delete mItemWeightScroll;
+}
+
+void ItemPopup::setItem(const ItemInfo &item)
+{
+ mItemName->setCaption(item.getName());
+ mItemName->setForegroundColor(getColor(item.getType()));
+ mItemName->setWidth(boldFont->getWidth(item.getName()));
+ mItemDesc->setTextWrapped(item.getDescription(), 196);
+ mItemEffect->setTextWrapped(item.getEffect(), 196);
+ mItemWeight->setTextWrapped(_("Weight: ") + toString(item.getWeight()) +
+ _(" grams"), 196);
+
+ int minWidth = mItemName->getWidth();
+
+ if (mItemDesc->getMinWidth() > minWidth)
+ minWidth = mItemDesc->getMinWidth();
+ if (mItemEffect->getMinWidth() > minWidth)
+ minWidth = mItemEffect->getMinWidth();
+ if (mItemWeight->getMinWidth() > minWidth)
+ minWidth = mItemWeight->getMinWidth();
+
+ minWidth += 8;
+ setWidth(minWidth);
+
+ int numRowsDesc = mItemDesc->getNumberOfRows();
+ int numRowsEffect = mItemEffect->getNumberOfRows();
+ int numRowsWeight = mItemWeight->getNumberOfRows();
+
+ mItemDescScroll->setDimension(gcn::Rectangle(2, 0, minWidth,
+ numRowsDesc * getFont()->getHeight()));
+
+ mItemEffectScroll->setDimension(gcn::Rectangle(2, 0, minWidth,
+ numRowsEffect * getFont()->getHeight()));
+
+ mItemWeightScroll->setDimension(gcn::Rectangle(2, 0, minWidth,
+ numRowsWeight * getFont()->getHeight()));
+
+ if (item.getEffect().empty())
+ {
+ setContentSize(minWidth, (numRowsDesc * getFont()->getHeight() +
+ (3 * getFont()->getHeight())));
+
+ mItemWeightScroll->setPosition(2,
+ (numRowsDesc * getFont()->getHeight()) +
+ (2 * getFont()->getHeight()));
+ }
+ else
+ {
+ setContentSize(minWidth, (numRowsDesc * getFont()->getHeight()) +
+ (numRowsEffect * getFont()->getHeight()) +
+ (3 * getFont()->getHeight()));
+
+ mItemWeightScroll->setPosition(2,
+ (numRowsDesc * getFont()->getHeight()) +
+ (numRowsEffect * getFont()->getHeight()) +
+ (2 * getFont()->getHeight()));
+ }
+
+ mItemDescScroll->setPosition(2, 20);
+ mItemEffectScroll->setPosition(2, (numRowsDesc * getFont()->getHeight()) +
+ (2 * getFont()->getHeight()));
+}
+
+gcn::Color ItemPopup::getColor(const std::string& type)
+{
+ gcn::Color color;
+
+ if (type.compare("generic") == 0)
+ color = 0x21a5b1;
+ else if (type.compare("equip-head") == 0)
+ color = 0x527fa4;
+ else if (type.compare("usable") == 0)
+ color = 0x268d24;
+ else if (type.compare("equip-torso") == 0)
+ color = 0xd12aa4;
+ else if (type.compare("equip-1hand") == 0)
+ color = 0xf42a2a;
+ else if (type.compare("equip-legs") == 0)
+ color = 0x699900;
+ else if (type.compare("equip-feet") == 0)
+ color = 0xaa1d48;
+ else if (type.compare("equip-2hand") == 0)
+ color = 0xf46d0e;
+ else if (type.compare("equip-shield") == 0)
+ color = 0x9c2424;
+ else if (type.compare("equip-ring") == 0)
+ color = 0x0000ff;
+ else if (type.compare("equip-arms") == 0)
+ color = 0x9c24e8;
+ else if (type.compare("equip-ammo") == 0)
+ color = 0x8b6311;
+ else
+ color = 0x000000;
+
+ return color;
+}
+
+unsigned int ItemPopup::getNumRows()
+{
+ return mItemDesc->getNumberOfRows() + mItemEffect->getNumberOfRows() +
+ mItemWeight->getNumberOfRows();
+}
+
+void ItemPopup::view(int x, int y)
+{
+ if (windowContainer->getWidth() < (x + getWidth() + 5))
+ x = windowContainer->getWidth() - getWidth();
+ if ((y - getHeight() - 10) < 0)
+ y = 0;
+ else
+ y = y - getHeight() - 10;
+ setPosition(x, y);
+ setVisible(true);
+ requestMoveToTop();
+}
diff --git a/src/gui/itempopup.h b/src/gui/itempopup.h
new file mode 100644
index 00000000..c820e3a0
--- /dev/null
+++ b/src/gui/itempopup.h
@@ -0,0 +1,54 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Legend of Mazzeroth Development Team
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef ITEMPOPUP_H
+#define ITEMPOPUP_H
+
+#include "window.h"
+
+class ItemInfo;
+class ScrollArea;
+class TextBox;
+
+class ItemPopup : public Window
+{
+ public:
+ ItemPopup();
+ ~ItemPopup();
+
+ void setItem(const ItemInfo &item);
+ unsigned int getNumRows();
+ void view(int x, int y);
+
+ private:
+ gcn::Label *mItemName;
+ TextBox *mItemDesc;
+ TextBox *mItemEffect;
+ TextBox *mItemWeight;
+ ScrollArea *mItemDescScroll;
+ ScrollArea *mItemEffectScroll;
+ ScrollArea *mItemWeightScroll;
+
+ gcn::Color getColor(const std::string& type);
+};
+
+#endif // ITEMPOPUP_H
diff --git a/src/gui/itemshortcutcontainer.cpp b/src/gui/itemshortcutcontainer.cpp
index b2f70348..42e3b853 100644
--- a/src/gui/itemshortcutcontainer.cpp
+++ b/src/gui/itemshortcutcontainer.cpp
@@ -18,15 +18,19 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <SDL_mouse.h>
#include "itemshortcutcontainer.h"
+#include "itempopup.h"
+#include "viewport.h"
-#include "../localplayer.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../inventory.h"
#include "../item.h"
#include "../itemshortcut.h"
#include "../keyboardconfig.h"
+#include "../localplayer.h"
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
@@ -34,30 +38,33 @@
#include "../utils/tostring.h"
ItemShortcutContainer::ItemShortcutContainer():
- mGridWidth(1),
- mGridHeight(1),
+ ShortcutContainer(),
mItemClicked(false),
mItemMoved(NULL)
{
addMouseListener(this);
addWidgetListener(this);
+ mItemPopup = new ItemPopup();
+
ResourceManager *resman = ResourceManager::getInstance();
mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png");
mMaxItems = itemShortcut->getItemCount();
- mBoxHeight = 42;
- mBoxWidth = 36;
+ mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8));
+
+ mBoxHeight = mBackgroundImg->getHeight();
+ mBoxWidth = mBackgroundImg->getWidth();
}
ItemShortcutContainer::~ItemShortcutContainer()
{
mBackgroundImg->decRef();
+ delete mItemPopup;
}
-void
-ItemShortcutContainer::logic()
+void ItemShortcutContainer::logic()
{
gcn::Widget::logic();
@@ -70,8 +77,7 @@ ItemShortcutContainer::logic()
}
}
-void
-ItemShortcutContainer::draw(gcn::Graphics *graphics)
+void ItemShortcutContainer::draw(gcn::Graphics *graphics)
{
Graphics *g = static_cast<Graphics*>(graphics);
@@ -87,7 +93,8 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics)
// Draw item keyboard shortcut.
const char *key = SDL_GetKeyName(
- (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_0 + i));
+ (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_1 + i));
+ graphics->setColor(0x000000);
g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT);
if (itemShortcut->getItem(i) < 0)
@@ -97,6 +104,8 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics)
player_node->getInventory()->findItem(itemShortcut->getItem(i));
if (item) {
// Draw item icon.
+ const std::string label =
+ item->isEquipped() ? "Eq." : toString(item->getQuantity());
Image* image = item->getImage();
if (image) {
const std::string label =
@@ -127,37 +136,30 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics)
gcn::Graphics::CENTER);
}
}
-}
-void ItemShortcutContainer::widgetResized(const gcn::Event &event)
-{
- mGridWidth = getWidth() / mBoxWidth;
- if (mGridWidth < 1) {
- mGridWidth = 1;
- }
-
- setHeight((mMaxItems / mGridWidth +
- (mMaxItems % mGridWidth > 0 ? 1 : 0)) * mBoxHeight);
-
- mGridHeight = getHeight() / mBoxHeight;
- if (mGridHeight < 1) {
- mGridHeight = 1;
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8));
}
}
-void
-ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event)
+void ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event)
{
- if (event.getButton() == gcn::MouseEvent::LEFT) {
- if (!mItemMoved && mItemClicked) {
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ if (!mItemMoved && mItemClicked)
+ {
const int index = getIndexFromGrid(event.getX(), event.getY());
- if (index == -1) {
- return;
- }
const int itemId = itemShortcut->getItem(index);
+
+ if (index == -1)
+ return;
+
if (itemId < 0)
return;
+
Item *item = player_node->getInventory()->findItem(itemId);
+
if (item)
{
mItemMoved = item;
@@ -171,39 +173,56 @@ ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event)
}
}
-void
-ItemShortcutContainer::mousePressed(gcn::MouseEvent &event)
+void ItemShortcutContainer::mousePressed(gcn::MouseEvent &event)
{
const int index = getIndexFromGrid(event.getX(), event.getY());
- if (index == -1) {
+ if (index == -1)
return;
- }
- // Stores the selected item if theirs one.
- if (itemShortcut->isItemSelected()) {
- itemShortcut->setItem(index);
- itemShortcut->setItemSelected(-1);
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+
+ // Stores the selected item if theirs one.
+ if (itemShortcut->isItemSelected())
+ {
+ itemShortcut->setItem(index);
+ itemShortcut->setItemSelected(-1);
+ }
+ else if (itemShortcut->getItem(index))
+ mItemClicked = true;
}
- else if (itemShortcut->getItem(index)) {
- mItemClicked = true;
+ else if (event.getButton() == gcn::MouseEvent::RIGHT)
+ {
+ Item *item = player_node->getInventory()->
+ findItem(itemShortcut->getItem(index));
+
+ if (!item)
+ return;
+
+ /* Convert relative to the window coordinates to absolute screen
+ * coordinates.
+ */
+ int mx, my;
+ SDL_GetMouseState(&mx, &my);
+ viewport->showPopup(mx, my, item);
}
}
-void
-ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event)
+void ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event)
{
if (event.getButton() == gcn::MouseEvent::LEFT)
{
if (itemShortcut->isItemSelected())
- {
itemShortcut->setItemSelected(-1);
- }
+
const int index = getIndexFromGrid(event.getX(), event.getY());
- if (index == -1) {
+ if (index == -1)
+ {
mItemMoved = NULL;
return;
}
- if (mItemMoved) {
+ if (mItemMoved)
+ {
itemShortcut->setItems(index, mItemMoved->getId());
mItemMoved = NULL;
}
@@ -211,25 +230,43 @@ ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event)
{
itemShortcut->useItem(index);
}
- if (mItemClicked) {
+ if (mItemClicked)
mItemClicked = false;
- }
}
}
-int
-ItemShortcutContainer::getIndexFromGrid(int pointX, int pointY) const
+// Show ItemTooltip
+void ItemShortcutContainer::mouseMoved(gcn::MouseEvent &event)
{
- const gcn::Rectangle tRect = gcn::Rectangle(
- 0, 0, mGridWidth * mBoxWidth, mGridHeight * mBoxHeight);
- if (!tRect.isPointInRect(pointX, pointY)) {
- return -1;
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ const int itemId = itemShortcut->getItem(index);
+
+ if (index == -1)
+ return;
+
+ if (itemId < 0)
+ return;
+
+ Item *item = player_node->getInventory()->findItem(itemId);
+
+ if (item)
+ {
+ int mouseX, mouseY;
+ SDL_GetMouseState(&mouseX, &mouseY);
+
+ mItemPopup->setItem(item->getInfo());
+ mItemPopup->setOpaque(false);
+ mItemPopup->view(mouseX, mouseY);
}
- const int index = ((pointY / mBoxHeight) * mGridWidth) +
- pointX / mBoxWidth;
- if (index >= mMaxItems)
+ else
{
- return -1;
+ mItemPopup->setVisible(false);
}
- return index;
}
+
+// Hide ItemTooltip
+void ItemShortcutContainer::mouseExited(gcn::MouseEvent &event)
+{
+ mItemPopup->setVisible(false);
+}
+
diff --git a/src/gui/itemshortcutcontainer.h b/src/gui/itemshortcutcontainer.h
index cdaf6713..22d94ec2 100644
--- a/src/gui/itemshortcutcontainer.h
+++ b/src/gui/itemshortcutcontainer.h
@@ -23,20 +23,19 @@
#define ITEMSHORTCUTCONTAINER_H
#include <guichan/mouselistener.hpp>
-#include <guichan/widget.hpp>
-#include <guichan/widgetlistener.hpp>
+
+#include "shortcutcontainer.h"
class Image;
class Item;
+class ItemPopup;
/**
* An item shortcut container. Used to quickly use items.
*
* \ingroup GUI
*/
-class ItemShortcutContainer : public gcn::Widget,
- public gcn::WidgetListener,
- public gcn::MouseListener
+class ItemShortcutContainer : public ShortcutContainer
{
public:
/**
@@ -60,12 +59,6 @@ class ItemShortcutContainer : public gcn::Widget,
void draw(gcn::Graphics *graphics);
/**
- * Invoked when a widget changes its size. This is used to determine
- * the new height of the container.
- */
- void widgetResized(const gcn::Event &event);
-
- /**
* Handles mouse when dragged.
*/
void mouseDragged(gcn::MouseEvent &event);
@@ -80,34 +73,14 @@ class ItemShortcutContainer : public gcn::Widget,
*/
void mouseReleased(gcn::MouseEvent &event);
- int getMaxItems()
- { return mMaxItems; }
-
- int getBoxWidth()
- { return mBoxWidth; }
-
- int getBoxHeight()
- { return mBoxHeight; }
-
private:
- /**
- * Gets the index from the grid provided the point is in an item box.
- *
- * @param pointX X coordinate of the point.
- * @param pointY Y coordinate of the point.
- * @return index on success, -1 on failure.
- */
- int getIndexFromGrid(int pointX, int pointY) const;
+ void mouseExited(gcn::MouseEvent &event);
+ void mouseMoved(gcn::MouseEvent &event);
- Image *mBackgroundImg;
-
- int mMaxItems;
- int mBoxWidth;
- int mBoxHeight;
- int mCursorPosX, mCursorPosY;
- int mGridWidth, mGridHeight;
bool mItemClicked;
Item *mItemMoved;
+
+ ItemPopup *mItemPopup;
};
#endif
diff --git a/src/gui/listbox.cpp b/src/gui/listbox.cpp
index b72c64cf..63e55e24 100644
--- a/src/gui/listbox.cpp
+++ b/src/gui/listbox.cpp
@@ -19,12 +19,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "listbox.h"
-
#include <guichan/font.hpp>
#include <guichan/graphics.hpp>
#include <guichan/listmodel.hpp>
-#include <guichan/mouseinput.hpp>
+
+#include "color.h"
+#include "listbox.h"
+
+#include "../configuration.h"
+
+float ListBox::mAlpha = config.getValue("guialpha", 0.8);
ListBox::ListBox(gcn::ListModel *listModel):
gcn::ListBox(listModel)
@@ -36,29 +40,35 @@ void ListBox::draw(gcn::Graphics *graphics)
if (!mListModel)
return;
- graphics->setColor(gcn::Color(110, 160, 255));
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ mAlpha = config.getValue("guialpha", 0.8);
+
+ bool valid;
+ const int red = (textColor->getColor('H', valid) >> 16) & 0xFF;
+ const int green = (textColor->getColor('H', valid) >> 8) & 0xFF;
+ const int blue = textColor->getColor('H', valid) & 0xFF;
+ const int alpha = mAlpha * 255;
+
+ graphics->setColor(gcn::Color(red, green, blue, alpha));
graphics->setFont(getFont());
- int fontHeight = getFont()->getHeight();
+ const int fontHeight = getFont()->getHeight();
// Draw rectangle below the selected list element
- if (mSelected >= 0) {
+ if (mSelected >= 0)
graphics->fillRectangle(gcn::Rectangle(0, fontHeight * mSelected,
getWidth(), fontHeight));
- }
// Draw the list elements
- graphics->setColor(gcn::Color(0, 0, 0));
- for (int i = 0, y = 0;
- i < mListModel->getNumberOfElements();
+ graphics->setColor(gcn::Color(0, 0, 0, 255));
+ for (int i = 0, y = 0; i < mListModel->getNumberOfElements();
++i, y += fontHeight)
{
graphics->drawText(mListModel->getElementAt(i), 1, y);
}
}
-void
-ListBox::mouseDragged(gcn::MouseEvent &event)
+void ListBox::mouseDragged(gcn::MouseEvent &event)
{
// Pretend mouse is pressed continuously while dragged. Causes list
// selection to be updated as is default in many GUIs.
diff --git a/src/gui/listbox.h b/src/gui/listbox.h
index 934ea82e..12fcb955 100644
--- a/src/gui/listbox.h
+++ b/src/gui/listbox.h
@@ -47,6 +47,9 @@ class ListBox : public gcn::ListBox
void draw(gcn::Graphics *graphics);
void mouseDragged(gcn::MouseEvent &event);
+
+ private:
+ static float mAlpha;
};
#endif
diff --git a/src/gui/login.cpp b/src/gui/login.cpp
index 2b87f6df..90ceab1a 100644
--- a/src/gui/login.cpp
+++ b/src/gui/login.cpp
@@ -19,24 +19,31 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "login.h"
-
-#include <string>
-
#include <guichan/widgets/label.hpp>
-#include "../main.h"
-#include "../logindata.h"
-
#include "button.h"
#include "checkbox.h"
+#include "listbox.h"
+#include "login.h"
#include "ok_dialog.h"
#include "passwordfield.h"
+#include "scrollarea.h"
#include "textfield.h"
+#include "widgets/dropdown.h"
#include "widgets/layout.h"
+#include "../main.h"
+#include "../logindata.h"
+#include "../configuration.h"
+
#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+static const int MAX_SERVER_LIST_SIZE = 5;
+static const int LOGIN_DIALOG_WIDTH = 220;
+static const int LOGIN_DIALOG_HEIGHT = 140;
+static const int FIELD_WIDTH = LOGIN_DIALOG_WIDTH - 70;
LoginDialog::LoginDialog(LoginData *loginData):
Window(_("Login")), mLoginData(loginData)
@@ -44,36 +51,62 @@ LoginDialog::LoginDialog(LoginData *loginData):
gcn::Label *userLabel = new gcn::Label(_("Name:"));
gcn::Label *passLabel = new gcn::Label(_("Password:"));
gcn::Label *serverLabel = new gcn::Label(_("Server:"));
+ gcn::Label *portLabel = new gcn::Label(_("Port:"));
+ gcn::Label *dropdownLabel = new gcn::Label(_("Recent:"));
+ std::vector<std::string> dfltServer;
+ dfltServer.push_back("server.themanaworld.org");
+ std::vector<std::string> dfltPort;
+ dfltPort.push_back("6901");
+ mServerList = new DropDownList("MostRecent00", dfltServer, dfltPort,
+ MAX_SERVER_LIST_SIZE);
+ mServerListBox = new ListBox(mServerList);
+ mServerScrollArea = new ScrollArea();
+
mUserField = new TextField(mLoginData->username);
mPassField = new PasswordField(mLoginData->password);
- mServerField = new TextField(mLoginData->hostname);
+ mServerField = new TextField(mServerList->getServerAt(0));
+ mPortField = new TextField(mServerList->getPortAt(0));
+ mServerDropDown = new DropDown(mServerList,
+ mServerScrollArea,
+ mServerListBox);
+ mServerDropDown->setOpaque(false);
+
mKeepCheck = new CheckBox(_("Remember Username"), mLoginData->remember);
- mOkButton = new Button(_("Ok"), "ok", this);
+ mOkButton = new Button(_("OK"), "ok", this);
mCancelButton = new Button(_("Cancel"), "cancel", this);
mRegisterButton = new Button(_("Register"), "register", this);
mUserField->setActionEventId("ok");
mPassField->setActionEventId("ok");
mServerField->setActionEventId("ok");
+ mServerDropDown->setActionEventId("changeSelection");
mUserField->addKeyListener(this);
mPassField->addKeyListener(this);
mServerField->addKeyListener(this);
+ mPortField->addKeyListener(this);
+ mServerDropDown->addKeyListener(this);
mUserField->addActionListener(this);
mPassField->addActionListener(this);
mServerField->addActionListener(this);
+ mPortField->addActionListener(this);
+ mServerDropDown->addActionListener(this);
mKeepCheck->addActionListener(this);
place(0, 0, userLabel);
place(0, 1, passLabel);
place(0, 2, serverLabel);
- place(1, 0, mUserField, 3).setPadding(2);
- place(1, 1, mPassField, 3).setPadding(2);
- place(1, 2, mServerField, 3).setPadding(2);
- place(0, 3, mKeepCheck, 4);
- place(0, 4, mRegisterButton).setHAlign(LayoutCell::LEFT);
- place(2, 4, mOkButton);
- place(3, 4, mCancelButton);
+ place(0, 3, portLabel);
+ place(0, 4, dropdownLabel);
+ place(1, 0, mUserField, 3).setPadding(1);
+ place(1, 1, mPassField, 3).setPadding(1);
+ place(1, 2, mServerField, 3).setPadding(1);
+ place(1, 3, mPortField, 3).setPadding(1);
+ place(1, 4, mServerDropDown, 3).setPadding(1);
+ place(0, 5, mKeepCheck, 4);
+ place(0, 6, mRegisterButton).setHAlign(LayoutCell::LEFT);
+ place(2, 6, mCancelButton);
+ place(3, 6, mOkButton);
reflowLayout(250, 0);
setLocationRelativeTo(getParent());
@@ -90,6 +123,9 @@ LoginDialog::LoginDialog(LoginData *loginData):
LoginDialog::~LoginDialog()
{
+ delete mServerList;
+ delete mServerListBox;
+ delete mServerScrollArea;
}
void LoginDialog::action(const gcn::ActionEvent &event)
@@ -97,6 +133,7 @@ void LoginDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "ok" && canSubmit())
{
mLoginData->hostname = mServerField->getText();
+ mLoginData->port = getUShort(mPortField->getText());
mLoginData->username = mUserField->getText();
mLoginData->password = mPassField->getText();
mLoginData->remember = mKeepCheck->isSelected();
@@ -104,9 +141,15 @@ void LoginDialog::action(const gcn::ActionEvent &event)
mOkButton->setEnabled(false);
mRegisterButton->setEnabled(false);
-
+ mServerList->save(mServerField->getText(), mPortField->getText());
state = ACCOUNT_STATE;
}
+ else if (event.getId() == "changeSelection")
+ {
+ int selected = mServerListBox->getSelected();
+ mServerField->setText(mServerList->getServerAt(selected));
+ mPortField->setText(mServerList->getPortAt(selected));
+ }
else if (event.getId() == "cancel")
{
state = EXIT_STATE;
@@ -115,6 +158,14 @@ void LoginDialog::action(const gcn::ActionEvent &event)
{
// Transfer these fields on to the register dialog
mLoginData->hostname = mServerField->getText();
+ if (isUShort(mPortField->getText()))
+ {
+ mLoginData->port = getUShort(mPortField->getText());
+ }
+ else
+ {
+ mLoginData->port = 6901;
+ }
mLoginData->username = mUserField->getText();
mLoginData->password = mPassField->getText();
@@ -132,5 +183,138 @@ bool LoginDialog::canSubmit()
return !mUserField->getText().empty() &&
!mPassField->getText().empty() &&
!mServerField->getText().empty() &&
+ isUShort(mPortField->getText()) &&
state == LOGIN_STATE;
}
+
+bool LoginDialog::isUShort(const std::string &str)
+{
+ if (str.empty())
+ {
+ return false;
+ }
+ unsigned long l = 0;
+ for (std::string::const_iterator strPtr = str.begin(), strEnd = str.end();
+ strPtr != strEnd; ++strPtr)
+ {
+ if (*strPtr < '0' || *strPtr > '9')
+ {
+ return false;
+ }
+ l = l * 10 + (*strPtr - '0'); // *strPtr - '0' will never be negative
+ if (l > 65535)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+unsigned short LoginDialog::getUShort(const std::string &str)
+{
+ unsigned long l = 0;
+ for (std::string::const_iterator strPtr = str.begin(), strEnd = str.end();
+ strPtr != strEnd; ++strPtr)
+ {
+ l = l * 10 + (*strPtr - '0');
+ }
+ return static_cast<unsigned short>(l);
+}
+
+/**
+ * LoginDialog::DropDownList
+ */
+
+void LoginDialog::DropDownList::saveEntry(const std::string &server,
+ const std::string &port, int &saved)
+{
+ if (saved < MAX_SERVER_LIST_SIZE && !server.empty())
+ {
+ config.setValue(mConfigPrefix + "Server" + toString(saved), server);
+ config.setValue(mConfigPrefix + "Port" + toString(saved), port);
+ ++saved;
+ }
+}
+
+LoginDialog::DropDownList::DropDownList(std::string prefix,
+ std::vector<std::string> dflt,
+ std::vector<std::string> dfltPort,
+ int maxEntries) :
+ mConfigPrefix(prefix),
+ mMaxEntries(maxEntries)
+{
+ for (int i = 0; i < maxEntries; ++i)
+ {
+ std::string server = config.getValue(mConfigPrefix + "Server" +
+ toString(i), "");
+ if (server.empty()) // Just in case had original config entries
+ {
+ server = config.getValue(mConfigPrefix + "ServerList" +
+ toString(i), "");
+ }
+ std::string port = config.getValue(mConfigPrefix + "Port" +
+ toString(i), dfltPort.front());
+
+ if (!server.empty())
+ {
+ mServers.push_back(server);
+ mPorts.push_back(port);
+ }
+ }
+ if (mServers.empty())
+ {
+ mServers.assign(dflt.begin(), dflt.end());
+ mPorts.assign(dfltPort.begin(), dfltPort.end());
+ }
+}
+
+void LoginDialog::DropDownList::save(const std::string &server,
+ const std::string &port)
+{
+ int position = 0;
+ saveEntry(server, port, position);
+ for (std::vector<std::string>::const_iterator sPtr = mServers.begin(),
+ sEnd = mServers.end(),
+ pPtr = mPorts.begin(),
+ pEnd = mPorts.end();
+ sPtr != sEnd && pPtr != pEnd;
+ ++sPtr, ++pPtr)
+ {
+ if (*sPtr != server || *pPtr != port)
+ {
+ saveEntry(*sPtr, *pPtr, position);
+ }
+ }
+}
+
+int LoginDialog::DropDownList::getNumberOfElements()
+{
+ return mServers.size();
+}
+
+std::string LoginDialog::DropDownList::getElementAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return "";
+ }
+ return getServerAt(i) + ":" + getPortAt(i);
+}
+
+std::string LoginDialog::DropDownList::getServerAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return "";
+ }
+ return mServers.at(i);
+}
+
+std::string LoginDialog::DropDownList::getPortAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return "";
+ }
+ return mPorts.at(i);
+}
diff --git a/src/gui/login.h b/src/gui/login.h
index 7dd59a96..c0d6e755 100644
--- a/src/gui/login.h
+++ b/src/gui/login.h
@@ -22,14 +22,18 @@
#ifndef LOGIN_H
#define LOGIN_H
-#include <iosfwd>
+#include <string>
+#include <vector>
+
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
+#include <guichan/listmodel.hpp>
#include "window.h"
-#include "../guichanfwd.h"
+class DropDown;
class LoginData;
+class ScrollArea;
/**
* The login dialog.
@@ -67,18 +71,65 @@ class LoginDialog : public Window, public gcn::ActionListener,
* Returns whether submit can be enabled. This is true in the login
* state, when all necessary fields have some text.
*/
- bool
- canSubmit();
+ bool canSubmit();
+
+ /**
+ * Function to decide whether string is an unsigned short or not
+ *
+ * @param str the string to parse
+ *
+ * @return true is str is an unsigned short, false otherwise
+ */
+ static bool isUShort(const std::string &str);
+
+ /**
+ * Converts string to an unsigned short (undefined if invalid)
+ *
+ * @param str the string to parse
+ *
+ * @return the value str represents
+ */
+ static unsigned short getUShort(const std::string &str);
+ DropDown *mServerDropDown;
gcn::TextField *mUserField;
gcn::TextField *mPassField;
gcn::TextField *mServerField;
+ gcn::TextField *mPortField;
gcn::CheckBox *mKeepCheck;
gcn::Button *mOkButton;
gcn::Button *mCancelButton;
gcn::Button *mRegisterButton;
LoginData *mLoginData;
+
+ /**
+ * Helper class to keep a list of all the recent entries for the
+ * dropdown
+ */
+ class DropDownList : public gcn::ListModel
+ {
+ private:
+ std::vector<std::string> mServers;
+ std::vector<std::string> mPorts;
+ std::string mConfigPrefix;
+ int mMaxEntries;
+ void saveEntry(const std::string &server,
+ const std::string &port, int &saved);
+ public:
+ DropDownList(std::string prefix,
+ std::vector<std::string> dfltServer,
+ std::vector<std::string> dfltPort,
+ int maxEntries);
+ void save(const std::string &server, const std::string &port);
+ int getNumberOfElements();
+ std::string getElementAt(int i);
+ std::string getServerAt(int i);
+ std::string getPortAt(int i);
+ };
+ DropDownList *mServerList;
+ gcn::ListBox *mServerListBox;
+ gcn::ScrollArea *mServerScrollArea;
};
#endif
diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp
index e19cc3e8..0dcc999f 100644
--- a/src/gui/menuwindow.cpp
+++ b/src/gui/menuwindow.cpp
@@ -19,23 +19,24 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "menuwindow.h"
-
#include <string>
#include <guichan/actionlistener.hpp>
#include "button.h"
+#include "menuwindow.h"
#include "windowcontainer.h"
#include "../utils/gettext.h"
-extern Window *setupWindow;
-extern Window *inventoryWindow;
+extern Window *chatWindow;
extern Window *equipmentWindow;
+extern Window *inventoryWindow;
+extern Window *itemShortcutWindow;
+extern Window *emoteWindow;
+extern Window *setupWindow;
extern Window *skillDialog;
extern Window *statusWindow;
-extern Window *itemShortcutWindow;
namespace {
struct MenuWindowListener : public gcn::ActionListener
@@ -58,12 +59,14 @@ MenuWindow::MenuWindow():
// Buttons
static const char *buttonNames[] =
{
- N_("Status"),
- N_("Equipment"),
- N_("Inventory"),
- N_("Skills"),
- N_("Shortcut"),
- N_("Setup"),
+ _("Chat"),
+ _("Status"),
+ _("Equipment"),
+ _("Inventory"),
+ _("Skills"),
+ _("Shortcut"),
+ _("Emote"),
+ _("Setup"),
0
};
int x = 0, h = 0;
@@ -91,27 +94,35 @@ void MenuWindowListener::action(const gcn::ActionEvent &event)
{
Window *window = NULL;
- if (event.getId() == "Status")
+ if (event.getId() == _("Chat"))
+ {
+ window = chatWindow;
+ }
+ else if (event.getId() == _("Status"))
{
window = statusWindow;
}
- else if (event.getId() == "Equipment")
+ else if (event.getId() == _("Equipment"))
{
window = equipmentWindow;
}
- else if (event.getId() == "Inventory")
+ else if (event.getId() == _("Inventory"))
{
window = inventoryWindow;
}
- else if (event.getId() == "Skills")
+ else if (event.getId() == _("Skills"))
{
window = skillDialog;
}
- else if (event.getId() == "Shortcut")
+ else if (event.getId() == _("Shortcut"))
{
window = itemShortcutWindow;
}
- else if (event.getId() == "Setup")
+ else if (event.getId() == _("Emote"))
+ {
+ window = emoteWindow;
+ }
+ else if (event.getId() == _("Setup"))
{
window = setupWindow;
}
diff --git a/src/gui/menuwindow.h b/src/gui/menuwindow.h
index 9b784c35..9bb54e29 100644
--- a/src/gui/menuwindow.h
+++ b/src/gui/menuwindow.h
@@ -24,8 +24,6 @@
#include "window.h"
-#include "../guichanfwd.h"
-
/**
* The Button Menu.
*
diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp
index f5c0c1e6..ccadf3e1 100644
--- a/src/gui/minimap.cpp
+++ b/src/gui/minimap.cpp
@@ -19,10 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <guichan/font.hpp>
+
#include "minimap.h"
#include "../being.h"
#include "../beingmanager.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../localplayer.h"
@@ -30,12 +33,18 @@
#include "../utils/gettext.h"
+bool Minimap::mShow = true;
+
Minimap::Minimap():
Window(_("MiniMap")),
- mMapImage(NULL)
+ mMapImage(NULL),
+ mProportion(0.5)
{
- setWindowName("MiniMap");
+ setWindowName(_("MiniMap"));
+ mShow = config.getValue(getWindowName() + "Show", true);
setDefaultSize(5, 25, 100, 100);
+ setResizable(true);
+
loadWindowState();
}
@@ -43,6 +52,8 @@ Minimap::~Minimap()
{
if (mMapImage)
mMapImage->decRef();
+
+ config.setValue(getWindowName() + "Show", mShow);
}
void Minimap::setMapImage(Image *img)
@@ -53,13 +64,59 @@ void Minimap::setMapImage(Image *img)
mMapImage = img;
if (mMapImage)
- mMapImage->setAlpha(0.7);
+ {
+ const int offsetX = 2 * getPadding();
+ const int offsetY = getTitleBarHeight() + getPadding();
+ const int titleWidth = getFont()->getWidth(getCaption()) + 15;
+ const int mapWidth = mMapImage->getWidth() < 100 ?
+ mMapImage->getWidth() + offsetX : 100;
+ const int mapHeight = mMapImage->getHeight() < 100 ?
+ mMapImage->getHeight() + offsetY : 100;
+
+ setMinWidth(mapWidth > titleWidth ? mapWidth : titleWidth);
+ setMinHeight(mapHeight);
+ setMaxWidth(mMapImage->getWidth() > titleWidth ?
+ mMapImage->getWidth() + offsetX : titleWidth);
+ setMaxHeight(mMapImage->getHeight() + offsetY);
+
+ // Make sure the window is within the minimum and maximum boundaries
+ // TODO: Shouldn't this be happening automatically within the Window
+ // class?
+ if (getMinWidth() > getWidth())
+ setWidth(getMinWidth());
+ else if (getMaxWidth() < getWidth())
+ setWidth(getMaxWidth());
+ if (getMinHeight() > getHeight())
+ setHeight(getMinHeight());
+ else if (getMaxHeight() < getHeight())
+ setHeight(getMaxHeight());
+
+ setContentSize(getWidth() - offsetX, getHeight() - offsetY);
+ setDefaultSize(getX(), getY(), getWidth(), getHeight());
+ resetToDefaultSize();
+
+ setVisible(mShow);
+ }
+ else
+ {
+ setVisible(false);
+ }
+}
+
+void Minimap::toggle()
+{
+ mShow = !mShow;
}
void Minimap::draw(gcn::Graphics *graphics)
{
+ setVisible(mShow);
+
Window::draw(graphics);
+ if (!mShow)
+ return;
+
const gcn::Rectangle a = getChildrenArea();
graphics->pushClipArea(a);
@@ -72,8 +129,8 @@ void Minimap::draw(gcn::Graphics *graphics)
if (mMapImage->getWidth() > a.width ||
mMapImage->getHeight() > a.height)
{
- mapOriginX = (a.width - player_node->mX) / 2;
- mapOriginY = (a.height - player_node->mY) / 2;
+ mapOriginX = (int) (((a.width) / 2) - (player_node->mX * mProportion));
+ mapOriginY = (int) (((a.height) / 2) - (player_node->mY * mProportion));
const int minOriginX = a.width - mMapImage->getWidth();
const int minOriginY = a.height - mMapImage->getHeight();
@@ -87,6 +144,7 @@ void Minimap::draw(gcn::Graphics *graphics)
if (mapOriginY > 0)
mapOriginY = 0;
}
+
static_cast<Graphics*>(graphics)->
drawImage(mMapImage, mapOriginX, mapOriginY);
}
@@ -122,10 +180,11 @@ void Minimap::draw(gcn::Graphics *graphics)
continue;
}
- const int offset = (dotSize - 1) / 2;
+ const int offset = (int) ((dotSize - 1) * mProportion);
+
graphics->fillRectangle(gcn::Rectangle(
- being->mX / 2 + mapOriginX - offset,
- being->mY / 2 + mapOriginY - offset,
+ (int) (being->mX * mProportion) + mapOriginX - offset,
+ (int) (being->mY * mProportion) + mapOriginY - offset,
dotSize, dotSize));
}
diff --git a/src/gui/minimap.h b/src/gui/minimap.h
index 67f5eb18..3ce0aacd 100644
--- a/src/gui/minimap.h
+++ b/src/gui/minimap.h
@@ -50,12 +50,24 @@ class Minimap : public Window
void setMapImage(Image *img);
/**
+ * Sets the map proportion (1 means 1 tile to one pixel, .5 means 2 tiles to 1 pixel, etc.)
+ */
+ void setProportion(float proportion) { mProportion = proportion; }
+
+ /**
+ * Toggles the displaying of the minimap.
+ */
+ void toggle();
+
+ /**
* Draws the minimap.
*/
void draw(gcn::Graphics *graphics);
private:
Image *mMapImage;
+ float mProportion;
+ static bool mShow;
};
extern Minimap *minimap;
diff --git a/src/gui/ministatus.cpp b/src/gui/ministatus.cpp
index e613a745..7058d572 100644
--- a/src/gui/ministatus.cpp
+++ b/src/gui/ministatus.cpp
@@ -19,14 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "ministatus.h"
-
#include "gui.h"
+#include "ministatus.h"
#include "progressbar.h"
-#include "../localplayer.h"
+#include "../animatedsprite.h"
#include "../configuration.h"
#include "../graphics.h"
+#include "../localplayer.h"
#include "../utils/tostring.h"
@@ -90,29 +90,27 @@ void MiniStatusWindow::update()
mHpBar->setColor(0, 171, 34); // Green
}
+ float xp = (float) player_node->getXp() / player_node->mXpForNextLevel;
+
+ if (xp != xp) xp = 0.0f; // check for NaN
+ if (xp < 0.0f) xp = 0.0f; // make sure the experience isn't negative (uninitialized pointer most likely)
+ if (xp > 1.0f) xp = 1.0f;
+
mHpBar->setProgress((float) player_node->mHp / player_node->mMaxHp);
mMpBar->setProgress((float) player_node->mMp / player_node->mMaxMp);
- if (player_node->MATK <= 0)
- mMpBar->setColor(100, 100, 100); // grey, to indicate that we lack magic
- else
- mMpBar->setColor(26, 102, 230); // blue, to indicate that we have magic
-
- mXpBar->setProgress(
- (float) player_node->getXp() / player_node->mXpForNextLevel);
+ mXpBar->setProgress(xp);
// Update labels
mHpBar->setText(toString(player_node->mHp));
mMpBar->setText(toString(player_node->mMp));
std::stringstream updatedText;
- updatedText << (int) (
- (float) player_node->getXp() /
- player_node->mXpForNextLevel * 100) << "%";
+ updatedText << (float) ((int) (xp * 10000.0f)) / 100.0f << "%";
// Displays the number of monsters to next lvl
// (disabled for now but interesting idea)
/*
- if(config.getValue("xpBarMonsterCounterExp", 0)!=0)
+ if (config.getValue("xpBarMonsterCounterExp", 0)!=0)
{
updatedText << " | "
<< (int)(((float)player_node->mXpForNextLevel - (float)player_node->mXp)
diff --git a/src/gui/ministatus.h b/src/gui/ministatus.h
index c6a36a98..f262a2a0 100644
--- a/src/gui/ministatus.h
+++ b/src/gui/ministatus.h
@@ -22,14 +22,11 @@
#ifndef MINISTATUS_H
#define MINISTATUS_H
-#include <iosfwd>
-#include <vector>
-
#include "window.h"
-#include "../guichanfwd.h"
-#include "../animatedsprite.h"
+#include <vector>
+class AnimatedSprite;
class ProgressBar;
/**
diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp
index 6ad698bc..b4313b70 100644
--- a/src/gui/npc_text.cpp
+++ b/src/gui/npc_text.cpp
@@ -19,13 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "npc_text.h"
-
-#include <string>
-
-#include "browserbox.h"
#include "button.h"
+#include "npc_text.h"
#include "scrollarea.h"
+#include "textbox.h"
+
+#include "widgets/layout.h"
#include "../npc.h"
@@ -39,66 +38,55 @@ NpcTextDialog::NpcTextDialog():
setMinWidth(200);
setMinHeight(150);
- mBrowserBox = new BrowserBox(BrowserBox::AUTO_WRAP);
- mBrowserBox->setOpaque(true);
+ setDefaultSize(0, 0, 260, 200);
+
+ mTextBox = new TextBox;
+ mTextBox->setEditable(false);
+ mTextBox->setOpaque(false);
- scrollArea = new ScrollArea(mBrowserBox);
+ scrollArea = new ScrollArea(mTextBox);
okButton = new Button(_("OK"), "ok", this);
- setContentSize(260, 175);
scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
scrollArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS);
- scrollArea->setDimension(gcn::Rectangle(
- 5, 5, 250, 160 - okButton->getHeight()));
- okButton->setPosition(
- 260 - 5 - okButton->getWidth(),
- 175 - 5 - okButton->getHeight());
- add(scrollArea);
- add(okButton);
+ place(0, 0, scrollArea, 5).setPadding(3);
+ place(4, 1, okButton);
- setLocationRelativeTo(getParent());
-}
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
-void NpcTextDialog::clearText()
-{
- mBrowserBox->clearRows();
+ loadWindowState();
+ setLocationRelativeTo(getParent());
}
void NpcTextDialog::setText(const std::string &text)
{
- mBrowserBox->clearRows();
- mBrowserBox->addRow(text);
+ mText = text;
+ mTextBox->setTextWrapped(mText, scrollArea->getWidth() - 15);
}
void NpcTextDialog::addText(const std::string &text)
{
- mBrowserBox->addRow(text);
-}
-
-void NpcTextDialog::widgetResized(const gcn::Event &event)
-{
- Window::widgetResized(event);
-
- const gcn::Rectangle &area = getChildrenArea();
- const int width = area.width;
- const int height = area.height;
-
- scrollArea->setDimension(gcn::Rectangle(
- 5, 5, width - 10, height - 15 - okButton->getHeight()));
- okButton->setPosition(
- width - 5 - okButton->getWidth(),
- height - 5 - okButton->getHeight());
+ setText(mText + text + "\n");
}
void NpcTextDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "ok")
{
- clearText();
+ setText("");
setVisible(false);
if (current_npc)
current_npc->nextDialog();
current_npc = 0;
}
}
+
+void NpcTextDialog::widgetResized(const gcn::Event &event)
+{
+ Window::widgetResized(event);
+
+ setText(mText);
+}
+
diff --git a/src/gui/npc_text.h b/src/gui/npc_text.h
index c881467a..a07aa04f 100644
--- a/src/gui/npc_text.h
+++ b/src/gui/npc_text.h
@@ -22,12 +22,13 @@
#ifndef NPC_TEXT_H
#define NPC_TEXT_H
-#include <iosfwd>
+#include <string>
+
#include <guichan/actionlistener.hpp>
#include "window.h"
-class BrowserBox;
+class TextBox;
/**
* The npc text dialog.
@@ -45,13 +46,6 @@ class NpcTextDialog : public Window, public gcn::ActionListener
NpcTextDialog();
/**
- * Called when resizing the window.
- *
- * @param event The calling event
- */
- void widgetResized(const gcn::Event &event);
-
- /**
* Called when receiving actions from the widgets.
*/
void action(const gcn::ActionEvent &event);
@@ -76,10 +70,19 @@ class NpcTextDialog : public Window, public gcn::ActionListener
*/
void addText(const std::string &string);
+ /**
+ * Called when resizing the window.
+ *
+ * @param event The calling event
+ */
+ void widgetResized(const gcn::Event &event);
+
private:
gcn::Button *okButton;
gcn::ScrollArea *scrollArea;
- BrowserBox *mBrowserBox;
+ TextBox *mTextBox;
+
+ std::string mText;
};
#endif // NPC_TEXT_H
diff --git a/src/gui/npcintegerdialog.cpp b/src/gui/npcintegerdialog.cpp
index ec91d736..c58fc460 100644
--- a/src/gui/npcintegerdialog.cpp
+++ b/src/gui/npcintegerdialog.cpp
@@ -19,27 +19,23 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "npcintegerdialog.h"
-
-#include <limits>
-#include <sstream>
-
#include "button.h"
#include "inttextfield.h"
+#include "npcintegerdialog.h"
+
+#include "widgets/layout.h"
#include "../npc.h"
#include "../utils/gettext.h"
-#include "../utils/tostring.h"
-
-#include "widgets/layout.h"
NpcIntegerDialog::NpcIntegerDialog():
Window(_("NPC Number Request"))
{
+ mValueField = new IntTextField();
+
mDecButton = new Button("-", "decvalue", this);
mIncButton = new Button("+", "incvalue", this);
- mValueField = new IntTextField();
okButton = new Button(_("OK"), "ok", this);
cancelButton = new Button(_("Cancel"), "cancel", this);
resetButton = new Button(_("Reset"), "reset", this);
@@ -61,9 +57,6 @@ NpcIntegerDialog::NpcIntegerDialog():
reflowLayout(175, 0);
setLocationRelativeTo(getParent());
-
- mValueField->setActionEventId("valuefield");
- mValueField->addKeyListener(this);
}
void NpcIntegerDialog::setRange(const int min, const int max)
@@ -107,5 +100,16 @@ void NpcIntegerDialog::action(const gcn::ActionEvent &event)
setVisible(false);
current_npc->integerInput(mValueField->getValue());
current_npc = 0;
+ mValueField->reset();
}
}
+
+bool NpcIntegerDialog::isInputFocused()
+{
+ return mValueField->isFocused();
+}
+
+void NpcIntegerDialog::requestFocus()
+{
+ mValueField->requestFocus();
+}
diff --git a/src/gui/npcintegerdialog.h b/src/gui/npcintegerdialog.h
index 983c46fe..10ec60b9 100644
--- a/src/gui/npcintegerdialog.h
+++ b/src/gui/npcintegerdialog.h
@@ -22,16 +22,10 @@
#ifndef GUI_NPCINTEGERDIALOG_H
#define GUI_NPCINTEGERDIALOG_H
-#include <iosfwd>
-#include <vector>
-
#include <guichan/actionlistener.hpp>
-#include <guichan/keylistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
-
class IntTextField;
/**
@@ -39,8 +33,7 @@ class IntTextField;
*
* \ingroup Interface
*/
-class NpcIntegerDialog : public Window, public gcn::ActionListener,
- public gcn::KeyListener
+class NpcIntegerDialog : public Window, public gcn::ActionListener
{
public:
/**
@@ -68,6 +61,16 @@ class NpcIntegerDialog : public Window, public gcn::ActionListener,
*/
void setRange(const int min, const int max);
+ /**
+ * Checks whether NpcStringDialog is Focused or not.
+ */
+ bool isInputFocused();
+
+ /**
+ * Requests the textfield to take focus for input.
+ */
+ void requestFocus();
+
private:
gcn::Button *mDecButton;
gcn::Button *mIncButton;
diff --git a/src/gui/npclistdialog.cpp b/src/gui/npclistdialog.cpp
index 4b05df5a..7d8a362a 100644
--- a/src/gui/npclistdialog.cpp
+++ b/src/gui/npclistdialog.cpp
@@ -19,13 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "npclistdialog.h"
-
#include <sstream>
#include "button.h"
-#include "scrollarea.h"
#include "listbox.h"
+#include "npclistdialog.h"
+#include "scrollarea.h"
+
+#include "widgets/layout.h"
#include "../npc.h"
@@ -39,30 +40,25 @@ NpcListDialog::NpcListDialog():
setMinWidth(200);
setMinHeight(150);
+ setDefaultSize(0, 0, 260, 200);
+
mItemList = new ListBox(this);
+ mItemList->setWrappingEnabled(true);
scrollArea = new ScrollArea(mItemList);
okButton = new Button(_("OK"), "ok", this);
cancelButton = new Button(_("Cancel"), "cancel", this);
setContentSize(260, 175);
scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- scrollArea->setDimension(gcn::Rectangle(
- 5, 5, 250, 160 - okButton->getHeight()));
- cancelButton->setPosition(
- 260 - 5 - cancelButton->getWidth(),
- 175 - 5 - cancelButton->getHeight());
- okButton->setPosition(
- cancelButton->getX() - 5 - okButton->getWidth(),
- cancelButton->getY());
-
- mItemList->setActionEventId("item");
- mItemList->addActionListener(this);
+ place(0, 0, scrollArea, 5).setPadding(3);
+ place(3, 1, okButton);
+ place(4, 1, cancelButton);
- add(scrollArea);
- add(okButton);
- add(cancelButton);
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
+ loadWindowState();
setLocationRelativeTo(getParent());
}
@@ -90,24 +86,6 @@ void NpcListDialog::reset()
mItems.clear();
}
-void NpcListDialog::widgetResized(const gcn::Event &event)
-{
- Window::widgetResized(event);
-
- const gcn::Rectangle &area = getChildrenArea();
- const int width = area.width;
- const int height = area.height;
-
- scrollArea->setDimension(gcn::Rectangle(
- 5, 5, width - 10, height - 15 - okButton->getHeight()));
- cancelButton->setPosition(
- width - 5 - cancelButton->getWidth(),
- height - 5 - cancelButton->getHeight());
- okButton->setPosition(
- cancelButton->getX() - 5 - okButton->getWidth(),
- cancelButton->getY());
-}
-
void NpcListDialog::action(const gcn::ActionEvent &event)
{
int choice = 0;
diff --git a/src/gui/npclistdialog.h b/src/gui/npclistdialog.h
index 2ae4aae3..30167a5e 100644
--- a/src/gui/npclistdialog.h
+++ b/src/gui/npclistdialog.h
@@ -22,7 +22,6 @@
#ifndef GUI_NPCLISTDIALOG_H
#define GUI_NPCLISTDIALOG_H
-#include <iosfwd>
#include <vector>
#include <guichan/actionlistener.hpp>
@@ -30,8 +29,6 @@
#include "window.h"
-#include "../guichanfwd.h"
-
/**
* The npc list dialog.
*
@@ -49,13 +46,6 @@ class NpcListDialog : public Window, public gcn::ActionListener,
NpcListDialog();
/**
- * Called when resizing the window
- *
- * @param event The calling event
- */
- void widgetResized(const gcn::Event &event);
-
- /**
* Called when receiving actions from the widgets.
*/
void action(const gcn::ActionEvent &event);
diff --git a/src/gui/npcstringdialog.cpp b/src/gui/npcstringdialog.cpp
index 1c92d620..718c416f 100644
--- a/src/gui/npcstringdialog.cpp
+++ b/src/gui/npcstringdialog.cpp
@@ -19,18 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "npcstringdialog.h"
-
-#include <limits>
-#include <sstream>
-
#include "button.h"
+#include "npcstringdialog.h"
#include "textfield.h"
#include "../npc.h"
#include "../utils/gettext.h"
-#include "../utils/tostring.h"
#include "widgets/layout.h"
@@ -38,12 +33,13 @@ NpcStringDialog::NpcStringDialog():
Window(_("NPC Text Request"))
{
mValueField = new TextField("");
+
okButton = new Button(_("OK"), "ok", this);
cancelButton = new Button(_("Cancel"), "cancel", this);
place(0, 0, mValueField, 3);
- place(1, 1, okButton);
- place(2, 1, cancelButton);
+ place(1, 1, cancelButton);
+ place(2, 1, okButton);
reflowLayout(175, 0);
setLocationRelativeTo(getParent());
@@ -69,9 +65,15 @@ void NpcStringDialog::action(const gcn::ActionEvent &event)
setVisible(false);
current_npc->stringInput(mValueField->getText());
current_npc = 0;
+ mValueField->setText("");
}
bool NpcStringDialog::isInputFocused()
{
return mValueField->isFocused();
}
+
+void NpcStringDialog::requestFocus()
+{
+ mValueField->requestFocus();
+}
diff --git a/src/gui/npcstringdialog.h b/src/gui/npcstringdialog.h
index 5aea2de0..1933e0f1 100644
--- a/src/gui/npcstringdialog.h
+++ b/src/gui/npcstringdialog.h
@@ -22,16 +22,10 @@
#ifndef GUI_NPCSTRINGDIALOG_H
#define GUI_NPCSTRINGDIALOG_H
-#include <iosfwd>
-#include <vector>
-
#include <guichan/actionlistener.hpp>
-#include <guichan/keylistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
-
/**
* The npc integer input dialog.
*
@@ -69,6 +63,11 @@ class NpcStringDialog : public Window, public gcn::ActionListener
*/
bool isInputFocused();
+ /**
+ * Requests the textfield to take focus for input.
+ */
+ void requestFocus();
+
private:
gcn::TextField *mValueField;
gcn::Button *okButton;
diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp
index a2134d5d..2c67e71f 100644
--- a/src/gui/ok_dialog.cpp
+++ b/src/gui/ok_dialog.cpp
@@ -19,10 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "ok_dialog.h"
-#include "textbox.h"
+#include <guichan/font.hpp>
+
#include "button.h"
+#include "ok_dialog.h"
#include "scrollarea.h"
+#include "textbox.h"
#include "../utils/gettext.h"
@@ -30,25 +32,44 @@ OkDialog::OkDialog(const std::string &title, const std::string &msg,
Window *parent):
Window(title, true, parent)
{
- TextBox *textBox = new TextBox();
- textBox->setEditable(false);
+ mTextBox = new TextBox();
+ mTextBox->setEditable(false);
+ mTextBox->setOpaque(false);
+
+ mTextArea = new ScrollArea(mTextBox);
+ okButton = new Button(_("Ok"), "ok", this);
+
+ mTextArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mTextArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mTextArea->setOpaque(false);
- gcn::ScrollArea *scrollArea = new ScrollArea(textBox);
- gcn::Button *okButton = new Button(_("Ok"), "ok", this);
+ mTextBox->setTextWrapped(msg, 260);
- setContentSize(260, 175);
- scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- scrollArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS);
- scrollArea->setDimension(gcn::Rectangle(
- 5, 5, 250, 160 - okButton->getHeight()));
+ int numRows = mTextBox->getNumberOfRows();
- textBox->setTextWrapped(msg);
+ if (numRows > 1)
+ {
+ // 15 == height of each line of text (based on font heights)
+ // 14 == row top + bottom graphic pixel heights
+ setContentSize(mTextBox->getMinWidth() + 15, 15 + (numRows * 15) + okButton->getHeight());
+ mTextArea->setDimension(gcn::Rectangle(4, 5, mTextBox->getMinWidth() + 5,
+ 3 + (numRows * 14)));
+ }
+ else
+ {
+ int width = getFont()->getWidth(title);
+ if (width < getFont()->getWidth(msg))
+ width = getFont()->getWidth(msg);
+ if (width < okButton->getWidth())
+ width = okButton->getWidth();
+ setContentSize(width + 15, 30 + okButton->getHeight());
+ mTextArea->setDimension(gcn::Rectangle(4, 5, width + 5, 17));
+ }
- okButton->setPosition(
- 260 - 5 - okButton->getWidth(),
- 175 - 5 - okButton->getHeight());
+ okButton->setPosition((mTextBox->getMinWidth() - okButton->getWidth()) / 2,
+ (numRows * 14) + okButton->getHeight() - 8);
- add(scrollArea);
+ add(mTextArea);
add(okButton);
setLocationRelativeTo(getParent());
@@ -56,6 +77,11 @@ OkDialog::OkDialog(const std::string &title, const std::string &msg,
okButton->requestFocus();
}
+unsigned int OkDialog::getNumRows()
+{
+ return mTextBox->getNumberOfRows();
+}
+
void OkDialog::action(const gcn::ActionEvent &event)
{
// Proxy button events to our listeners
diff --git a/src/gui/ok_dialog.h b/src/gui/ok_dialog.h
index 44dc6bb9..3a438513 100644
--- a/src/gui/ok_dialog.h
+++ b/src/gui/ok_dialog.h
@@ -26,6 +26,9 @@
#include "window.h"
+class ScrollArea;
+class TextBox;
+
/**
* An 'Ok' button dialog.
*
@@ -41,10 +44,17 @@ class OkDialog : public Window, public gcn::ActionListener {
OkDialog(const std::string &title, const std::string &msg,
Window *parent = NULL);
+ unsigned int getNumRows();
+
/**
* Called when receiving actions from the widgets.
*/
void action(const gcn::ActionEvent &event);
+
+ private:
+ TextBox *mTextBox;
+ ScrollArea *mTextArea;
+ gcn::Button *okButton;
};
#endif
diff --git a/src/gui/passwordfield.cpp b/src/gui/passwordfield.cpp
index 09b6abda..345ee1c3 100644
--- a/src/gui/passwordfield.cpp
+++ b/src/gui/passwordfield.cpp
@@ -21,8 +21,6 @@
#include "passwordfield.h"
-#include <string>
-
PasswordField::PasswordField(const std::string& text):
TextField(text)
{
diff --git a/src/gui/passwordfield.h b/src/gui/passwordfield.h
index d6082e3f..42f8d187 100644
--- a/src/gui/passwordfield.h
+++ b/src/gui/passwordfield.h
@@ -22,6 +22,8 @@
#ifndef PASSWORDFIELD_H
#define PASSWORDFIELD_H
+#include <string>
+
#include "textfield.h"
/**
@@ -29,7 +31,8 @@
*
* \ingroup GUI
*/
-class PasswordField : public TextField {
+class PasswordField : public TextField
+{
public:
/**
* Constructor, initializes the password field with the given string.
diff --git a/src/gui/playerbox.cpp b/src/gui/playerbox.cpp
index 8f698df5..f99ce6ef 100644
--- a/src/gui/playerbox.cpp
+++ b/src/gui/playerbox.cpp
@@ -19,12 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <algorithm>
-
#include "playerbox.h"
-#include "../player.h"
+#include "../animatedsprite.h"
+#include "../configuration.h"
#include "../graphics.h"
+#include "../player.h"
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
@@ -32,6 +32,7 @@
#include "../utils/dtor.h"
int PlayerBox::instances = 0;
+float PlayerBox::mAlpha = config.getValue("guialpha", 0.8);
ImageRect PlayerBox::background;
PlayerBox::PlayerBox(const Player *player):
@@ -54,6 +55,7 @@ PlayerBox::PlayerBox(const Player *player):
bggridx[x], bggridy[y],
bggridx[x + 1] - bggridx[x] + 1,
bggridy[y + 1] - bggridy[y] + 1);
+ background.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
a++;
}
}
@@ -83,7 +85,21 @@ void PlayerBox::draw(gcn::Graphics *graphics)
bs = getFrameSize();
x = getWidth() / 2 - 16 + bs;
y = getHeight() / 2 + bs;
- mPlayer->draw(static_cast<Graphics*>(graphics), x, y);
+ for (int i = 0; i < Being::VECTOREND_SPRITE; i++)
+ {
+ if (mPlayer->getSprite(i))
+ {
+ mPlayer->getSprite(i)->draw(static_cast<Graphics*>(graphics), x, y);
+ }
+ }
+ }
+
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ for (int a = 0; a < 9; a++)
+ {
+ background.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
+ }
}
}
diff --git a/src/gui/playerbox.h b/src/gui/playerbox.h
index d66db4d4..7c08defd 100644
--- a/src/gui/playerbox.h
+++ b/src/gui/playerbox.h
@@ -51,8 +51,7 @@ class PlayerBox : public gcn::ScrollArea
* player to <code>NULL</code> causes the box not to draw any
* character.
*/
- void
- setPlayer(const Player *player) { mPlayer = player; }
+ void setPlayer(const Player *player) { mPlayer = player; }
/**
* Draws the scroll area.
@@ -67,6 +66,7 @@ class PlayerBox : public gcn::ScrollArea
private:
const Player *mPlayer; /**< The character used for display */
+ static float mAlpha;
static int instances;
static ImageRect background;
};
diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp
index 06a2ad87..3503d0ea 100644
--- a/src/gui/popupmenu.cpp
+++ b/src/gui/popupmenu.cpp
@@ -19,16 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "popupmenu.h"
-
#include <cassert>
-#include <iostream>
-
-#include <guichan/focushandler.hpp>
#include "browserbox.h"
+#include "chat.h"
#include "inventorywindow.h"
#include "item_amount.h"
+#include "popupmenu.h"
#include "windowcontainer.h"
#include "../being.h"
@@ -39,7 +36,9 @@
#include "../npc.h"
#include "../player_relations.h"
-#include "../resources/iteminfo.h"
+#include "../net/messageout.h"
+#include "../net/protocol.h"
+
#include "../resources/itemdb.h"
#include "../utils/gettext.h"
@@ -77,34 +76,35 @@ void PopupMenu::showPopup(int x, int y, Being *being)
// Players can be traded with. Later also attack, follow and
// add as buddy will be options in this menu.
const std::string &name = being->getName();
- mBrowserBox->addRow(
- strprintf(_("@@trade|Trade With %s@@"), name.c_str()));
- mBrowserBox->addRow(
- strprintf(_("@@attack|Attack %s@@"), name.c_str()));
+ mBrowserBox->addRow(strprintf(_("@@trade|Trade With %s@@"), name.c_str()));
+ mBrowserBox->addRow(strprintf(_("@@attack|Attack %s@@"), name.c_str()));
mBrowserBox->addRow("##3---");
switch (player_relations.getRelation(name)) {
- case PlayerRelation::NEUTRAL:
- mBrowserBox->addRow("@@friend|Befriend " + name + "@@");
-
- case PlayerRelation::FRIEND:
- mBrowserBox->addRow("@@disregard|Disregard " + name + "@@");
- mBrowserBox->addRow("@@ignore|Ignore " + name + "@@");
- break;
-
- case PlayerRelation::DISREGARDED:
- mBrowserBox->addRow("@@unignore|Un-Ignore " + name + "@@");
- mBrowserBox->addRow("@@ignore|Completely ignore " + name + "@@");
- break;
-
- case PlayerRelation::IGNORED:
- mBrowserBox->addRow("@@unignore|Un-Ignore " + name + "@@");
- break;
+ case PlayerRelation::NEUTRAL:
+ mBrowserBox->addRow(strprintf(_("@@friend|Befriend %s@@"), name.c_str()));
+
+ case PlayerRelation::FRIEND:
+ mBrowserBox->addRow(strprintf(_("@@disregard|Disregard %s@@"), name.c_str()));
+ mBrowserBox->addRow(strprintf(_("@@ignore|Ignore %s@@"), name.c_str()));
+ break;
+
+ case PlayerRelation::DISREGARDED:
+ mBrowserBox->addRow(strprintf(_("@@unignore|Un-Ignore %s@@"), name.c_str()));
+ mBrowserBox->addRow(strprintf(_("@@ignore|Completely ignore %s@@"), name.c_str()));
+ break;
+
+ case PlayerRelation::IGNORED:
+ mBrowserBox->addRow(strprintf(_("@@unignore|Un-Ignore %s@@"), name.c_str()));
+ break;
}
- //mBrowserBox->addRow("@@follow|Follow " + name + "@@");
- //mBrowserBox->addRow("@@buddy|Add " + name + " to Buddy List@@");
+ //mBrowserBox->addRow(_("@@follow|Follow ") + name + "@@");
+ //mBrowserBox->addRow(_("@@buddy|Add ") + name + " to Buddy List@@");
+
+ mBrowserBox->addRow("##3---");
+ mBrowserBox->addRow(strprintf(_("@@party-invite|Invite %s to party@@"), name.c_str()));
}
break;
@@ -148,7 +148,7 @@ void PopupMenu::handleLink(const std::string& link)
// Talk To action
if (link == "talk" &&
- being != NULL &&
+ being &&
being->getType() == Being::NPC &&
current_npc == 0)
{
@@ -157,7 +157,7 @@ void PopupMenu::handleLink(const std::string& link)
// Trade action
else if (link == "trade" &&
- being != NULL &&
+ being &&
being->getType() == Being::PLAYER)
{
player_node->trade(being);
@@ -166,35 +166,35 @@ void PopupMenu::handleLink(const std::string& link)
// Attack action
else if (link == "attack" &&
- being != NULL &&
+ being &&
being->getType() == Being::PLAYER)
{
player_node->attack(being, true);
}
else if (link == "unignore" &&
- being != NULL &&
+ being &&
being->getType() == Being::PLAYER)
{
player_relations.setRelation(being->getName(), PlayerRelation::NEUTRAL);
}
else if (link == "ignore" &&
- being != NULL &&
+ being &&
being->getType() == Being::PLAYER)
{
player_relations.setRelation(being->getName(), PlayerRelation::IGNORED);
}
else if (link == "disregard" &&
- being != NULL &&
+ being &&
being->getType() == Being::PLAYER)
{
player_relations.setRelation(being->getName(), PlayerRelation::DISREGARDED);
}
else if (link == "friend" &&
- being != NULL &&
+ being &&
being->getType() == Being::PLAYER)
{
player_relations.setRelation(being->getName(), PlayerRelation::FRIEND);
@@ -208,7 +208,7 @@ void PopupMenu::handleLink(const std::string& link)
/*
// Add Buddy action
- else if ((link == "buddy") && being != NULL && being->isPlayer())
+ else if ((link == "buddy") && being && being->isPlayer())
{
if (!buddyWindow->isVisible())
buddyWindow->setVisible(true);
@@ -217,7 +217,7 @@ void PopupMenu::handleLink(const std::string& link)
}*/
// Pick Up Floor Item action
- else if ((link == "pickup") && mFloorItem != NULL)
+ else if ((link == "pickup") && mFloorItem)
{
player_node->pickUp(mFloorItem);
}
@@ -247,15 +247,22 @@ void PopupMenu::handleLink(const std::string& link)
}
}
+ else if (link == "chat")
+ {
+ chatWindow->addItemText(mItem->getInfo().getName());
+ }
+
else if (link == "drop")
{
new ItemAmountWindow(AMOUNT_ITEM_DROP, inventoryWindow, mItem);
}
-
- else if (link == "description")
+ else if (link == "party-invite" &&
+ being &&
+ being->getType() == Being::PLAYER)
{
- // do nothing for now, I need to write
- // a window for the description first
+ MessageOut outMsg(player_node->getNetwork());
+ outMsg.writeInt16(CMSG_PARTY_INVITE);
+ outMsg.writeInt32(being->getId());
}
// Unknown actions
@@ -288,7 +295,7 @@ void PopupMenu::showPopup(int x, int y, Item *item)
mBrowserBox->addRow(_("@@use|Use@@"));
mBrowserBox->addRow(_("@@drop|Drop@@"));
- mBrowserBox->addRow(_("@@description|Description@@"));
+ mBrowserBox->addRow(_("@@chat|Add to Chat@@"));
mBrowserBox->addRow("##3---");
mBrowserBox->addRow(_("@@cancel|Cancel@@"));
diff --git a/src/gui/popupmenu.h b/src/gui/popupmenu.h
index 1165bcb2..2694abd8 100644
--- a/src/gui/popupmenu.h
+++ b/src/gui/popupmenu.h
@@ -24,15 +24,14 @@
#include <SDL.h> // for Uint32
-#include "window.h"
#include "linkhandler.h"
+#include "window.h"
class Being;
class BrowserBox;
class FloorItem;
class Item;
-
/**
* Window showing popup menu.
*/
diff --git a/src/gui/progressbar.cpp b/src/gui/progressbar.cpp
index d877bfbc..867477e0 100644
--- a/src/gui/progressbar.cpp
+++ b/src/gui/progressbar.cpp
@@ -19,17 +19,20 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <guichan/font.hpp>
+
+#include "gui.h"
#include "progressbar.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
-#include <guichan/font.hpp>
-
ImageRect ProgressBar::mBorder;
int ProgressBar::mInstances = 0;
+float ProgressBar::mAlpha = config.getValue("guialpha", 0.8);
ProgressBar::ProgressBar(float progress,
unsigned int width, unsigned int height,
@@ -55,6 +58,12 @@ ProgressBar::ProgressBar(float progress,
mBorder.grid[6] = dBorders->getSubImage(0, 15, 4, 4);
mBorder.grid[7] = dBorders->getSubImage(4, 15, 3, 4);
mBorder.grid[8] = dBorders->getSubImage(7, 15, 4, 4);
+
+ for (int i = 0; i < 9; i++)
+ {
+ mBorder.grid[i]->setAlpha(mAlpha);
+ }
+
dBorders->decRef();
}
@@ -92,12 +101,27 @@ void ProgressBar::logic()
void ProgressBar::draw(gcn::Graphics *graphics)
{
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ if (config.getValue("opengl", 0))
+ mAlpha = config.getValue("guialpha", 0.8);
+ else
+ mAlpha = 1.0f;
+ for (int i = 0; i < 9; i++)
+ {
+ mBorder.grid[i]->setAlpha(mAlpha);
+ }
+ }
+
static_cast<Graphics*>(graphics)->
drawImageRect(0, 0, getWidth(), getHeight(), mBorder);
+ const int alpha = mAlpha * 255;
+
// The bar
if (mProgress > 0) {
- graphics->setColor(gcn::Color(mRed, mGreen, mBlue, 200));
+
+ graphics->setColor(gcn::Color(mRed, mGreen, mBlue, alpha));
graphics->fillRectangle(gcn::Rectangle(4, 4,
(int) (mProgress * (getWidth() - 8)),
getHeight() - 8));
@@ -105,20 +129,22 @@ void ProgressBar::draw(gcn::Graphics *graphics)
// The label
if (!mText.empty()) {
- gcn::Font *f = getFont();
+ gcn::Font *f = boldFont;
const int textX = getWidth() / 2;
const int textY = (getHeight() - f->getHeight()) / 2;
graphics->setFont(f);
- graphics->setColor(gcn::Color(0, 0, 0));
+ graphics->setColor(gcn::Color(0, 0, 0, alpha));
graphics->drawText(mText, textX + 1, textY, gcn::Graphics::CENTER);
graphics->drawText(mText, textX, textY - 1, gcn::Graphics::CENTER);
graphics->drawText(mText, textX, textY + 1, gcn::Graphics::CENTER);
graphics->drawText(mText, textX - 1, textY, gcn::Graphics::CENTER);
- graphics->setColor(gcn::Color(255, 255, 255));
+ graphics->setColor(gcn::Color(255, 255, 255, alpha));
graphics->drawText(mText, textX, textY, gcn::Graphics::CENTER);
+
+ graphics->setColor(gcn::Color(0, 0, 0));
}
}
diff --git a/src/gui/progressbar.h b/src/gui/progressbar.h
index a4b30b04..2c1b22da 100644
--- a/src/gui/progressbar.h
+++ b/src/gui/progressbar.h
@@ -22,12 +22,12 @@
#ifndef PROGRESSBAR_H
#define PROGRESSBAR_H
+#include <string>
+
#include <guichan/widget.hpp>
#include <SDL_types.h>
-#include <string>
-
class ImageRect;
/**
@@ -81,12 +81,12 @@ class ProgressBar : public gcn::Widget
Uint8 getRed() const { return mRed; }
/**
- * Returns the red value of color.
+ * Returns the green value of color.
*/
Uint8 getGreen() const { return mGreen; }
/**
- * Returns the red value of color.
+ * Returns the blue value of color.
*/
Uint8 getBlue() const { return mBlue; }
@@ -110,6 +110,7 @@ class ProgressBar : public gcn::Widget
static ImageRect mBorder;
static int mInstances;
+ static float mAlpha;
};
#endif
diff --git a/src/gui/radiobutton.cpp b/src/gui/radiobutton.cpp
index 245112a7..c8ae2fad 100644
--- a/src/gui/radiobutton.cpp
+++ b/src/gui/radiobutton.cpp
@@ -21,12 +21,14 @@
#include "radiobutton.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
int RadioButton::instances = 0;
+float RadioButton::mAlpha = config.getValue("guialpha", 0.8);
Image *RadioButton::radioNormal;
Image *RadioButton::radioChecked;
Image *RadioButton::radioDisabled;
@@ -43,6 +45,10 @@ RadioButton::RadioButton(const std::string& caption, const std::string& group,
radioChecked = resman->getImage("graphics/gui/radioin.png");
radioDisabled = resman->getImage("graphics/gui/radioout.png");
radioDisabledChecked = resman->getImage("graphics/gui/radioin.png");
+ radioNormal->setAlpha(mAlpha);
+ radioChecked->setAlpha(mAlpha);
+ radioDisabled->setAlpha(mAlpha);
+ radioDisabledChecked->setAlpha(mAlpha);
}
instances++;
@@ -63,32 +69,37 @@ RadioButton::~RadioButton()
void RadioButton::drawBox(gcn::Graphics* graphics)
{
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ radioNormal->setAlpha(mAlpha);
+ radioChecked->setAlpha(mAlpha);
+ radioDisabled->setAlpha(mAlpha);
+ radioDisabledChecked->setAlpha(mAlpha);
+ }
+
Image *box = NULL;
- if (isSelected()) {
- if (isEnabled()) {
+ if (isSelected())
+ {
+ if (isEnabled())
box = radioChecked;
- } else {
+ else
box = radioDisabledChecked;
- }
- } else if (isEnabled()) {
+ }
+ else if (isEnabled())
box = radioNormal;
- } else {
+ else
box = radioDisabled;
- }
- if (box != NULL) {
+ if (box)
static_cast<Graphics*>(graphics)->drawImage(box, 2, 2);
- }
}
void RadioButton::draw(gcn::Graphics* graphics)
{
-
- graphics->pushClipArea(gcn::Rectangle(1,
- 1,
- getWidth() - 1,
- getHeight() - 1));
+ graphics->pushClipArea(gcn::Rectangle(1, 1, getWidth() - 1,
+ getHeight() - 1));
drawBox(graphics);
diff --git a/src/gui/radiobutton.h b/src/gui/radiobutton.h
index 2d2bdbb7..3d952b3f 100644
--- a/src/gui/radiobutton.h
+++ b/src/gui/radiobutton.h
@@ -26,11 +26,11 @@
class Image;
-
/*
* Guichan based RadioButton with custom look
*/
-class RadioButton : public gcn::RadioButton {
+class RadioButton : public gcn::RadioButton
+{
public:
/*
* Constructor.
@@ -56,6 +56,7 @@ class RadioButton : public gcn::RadioButton {
private:
static int instances;
+ static float mAlpha;
static Image *radioNormal;
static Image *radioChecked;
static Image *radioDisabled;
diff --git a/src/gui/recorder.cpp b/src/gui/recorder.cpp
new file mode 100644
index 00000000..40ef974b
--- /dev/null
+++ b/src/gui/recorder.cpp
@@ -0,0 +1,116 @@
+/*
+ * A chat recorder
+ * Copyright (C) 2008 Lloyd Bryant <lloyd_bryant@netzero.net>
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <physfs.h>
+
+#include "button.h"
+#include "chat.h"
+#include "recorder.h"
+#include "windowcontainer.h"
+
+#include "widgets/layout.h"
+
+#include "../utils/trim.h"
+
+Recorder::Recorder(ChatWindow *chat, const std::string &title,
+ const std::string &buttonTxt) :
+ Window(title)
+{
+ setWindowName(_("Recorder"));
+ const int offsetX = 2 * getPadding() + 10;
+ const int offsetY = getTitleBarHeight() + getPadding() + 10;
+
+ mChat = chat;
+ Button *button = new Button(buttonTxt, "activate", this);
+ setDefaultSize(0, windowContainer->getHeight() - 123 - button->getHeight() -
+ offsetY, button->getWidth() + offsetX, button->getHeight() +
+ offsetY);
+
+ place(0, 0, button);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
+
+ loadWindowState();
+}
+
+Recorder::~Recorder()
+{
+}
+
+void Recorder::record(const std::string &msg)
+{
+ if (mStream.is_open())
+ {
+ mStream << msg << std::endl;
+ }
+}
+
+void Recorder::changeRecordingStatus(const std::string &msg)
+{
+ std::string msgCopy = msg;
+ trim(msgCopy);
+
+ if (msgCopy.empty())
+ {
+ if (mStream.is_open())
+ {
+ mStream.close();
+ setVisible(false);
+
+ /*
+ * Message should go after mStream is closed so that it isn't
+ * recorded.
+ */
+ mChat->chatLog(_("Finishing recording."), BY_SERVER);
+ }
+ else
+ {
+ mChat->chatLog(_("Not currently recording."), BY_SERVER);
+ }
+ }
+ else if (mStream.is_open())
+ {
+ mChat->chatLog(_("Already recording."), BY_SERVER);
+ }
+ else
+ {
+ /*
+ * Message should go before mStream is opened so that it isn't
+ * recorded.
+ */
+ mChat->chatLog(_("Starting to record..."), BY_SERVER);
+ const std::string file =
+ std::string(PHYSFS_getUserDir()) + "/.tmw/" + msgCopy;
+
+ mStream.open(file.c_str(), std::ios_base::trunc);
+
+ if (mStream.is_open())
+ setVisible(true);
+ else
+ mChat->chatLog(_("Failed to start recording."), BY_SERVER);
+ }
+}
+
+void Recorder::action(const gcn::ActionEvent &event)
+{
+ changeRecordingStatus("");
+}
diff --git a/src/gui/recorder.h b/src/gui/recorder.h
new file mode 100644
index 00000000..0bbab012
--- /dev/null
+++ b/src/gui/recorder.h
@@ -0,0 +1,76 @@
+/*
+ * A chat recorder
+ * Copyright (C) 2008 Lloyd Bryant <lloyd_bryant@netzero.net>
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef RECORD_H
+#define RECORD_H
+
+#include <fstream>
+#include <string>
+
+#include <guichan/actionlistener.hpp>
+
+#include "window.h"
+
+#include "../utils/gettext.h"
+
+class ChatWindow;
+
+class Recorder : public Window, public gcn::ActionListener
+{
+ public:
+ Recorder(ChatWindow *chat, const std::string &title = _("Recording..."),
+ const std::string &buttonTxt = _("Stop recording"));
+
+ virtual ~Recorder();
+
+ /*
+ * Outputs the message to the recorder file
+ *
+ * @param msg the line to write to the recorded file.
+ */
+ void record(const std::string &msg);
+
+ /*
+ * Outputs the message to the recorder file
+ *
+ * @param msg The file to write out to. If null, then stop recording.
+ */
+ void changeRecordingStatus(const std::string &msg);
+
+ /*
+ * Whether or not the recorder is in use.
+ */
+ bool isRecording() {return (bool) mStream.is_open();}
+
+ /*
+ * called when the button is pressed
+ *
+ * @param event is the event that is generated
+ */
+ void action(const gcn::ActionEvent &event);
+
+ private:
+ ChatWindow *mChat;
+
+ std::ofstream mStream;
+};
+
+#endif
diff --git a/src/gui/register.cpp b/src/gui/register.cpp
index 5605ef96..e17f5902 100644
--- a/src/gui/register.cpp
+++ b/src/gui/register.cpp
@@ -19,30 +19,27 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "register.h"
-
-#include <string>
-#include <sstream>
-
#include <guichan/widgets/label.hpp>
-#include "../main.h"
#include "../configuration.h"
#include "../log.h"
#include "../logindata.h"
+#include "../main.h"
#include "button.h"
#include "checkbox.h"
#include "login.h"
+#include "ok_dialog.h"
#include "passwordfield.h"
#include "radiobutton.h"
+#include "register.h"
#include "textfield.h"
-#include "ok_dialog.h"
#include "widgets/layout.h"
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
+#include "../utils/tostring.h"
/**
* Listener used while dealing with wrong data. It is used to direct the focus
@@ -80,10 +77,12 @@ RegisterDialog::RegisterDialog(LoginData *loginData):
gcn::Label *passwordLabel = new gcn::Label(_("Password:"));
gcn::Label *confirmLabel = new gcn::Label(_("Confirm:"));
gcn::Label *serverLabel = new gcn::Label(_("Server:"));
+ gcn::Label *portLabel = new gcn::Label(_("Port:"));
mUserField = new TextField(loginData->username);
mPasswordField = new PasswordField(loginData->password);
mConfirmField = new PasswordField;
mServerField = new TextField(loginData->hostname);
+ mPortField = new TextField(toString(loginData->port));
mMaleButton = new RadioButton(_("Male"), "sex", true);
mFemaleButton = new RadioButton(_("Female"), "sex", false);
mRegisterButton = new Button(_("Register"), "register", this);
@@ -97,10 +96,12 @@ RegisterDialog::RegisterDialog(LoginData *loginData):
place(1, 3, mMaleButton);
place(2, 3, mFemaleButton);
place(0, 4, serverLabel);
+ place(0, 5, portLabel);
place(1, 0, mUserField, 3).setPadding(2);
place(1, 1, mPasswordField, 3).setPadding(2);
place(1, 2, mConfirmField, 3).setPadding(2);
place(1, 4, mServerField, 3).setPadding(2);
+ place(1, 5, mPortField, 3).setPadding(2);
place = getPlacer(0, 2);
place(1, 0, mRegisterButton);
place(2, 0, mCancelButton);
@@ -110,6 +111,7 @@ RegisterDialog::RegisterDialog(LoginData *loginData):
mPasswordField->addKeyListener(this);
mConfirmField->addKeyListener(this);
mServerField->addKeyListener(this);
+ mPortField->addKeyListener(this);
/* TODO:
* This is a quick and dirty way to respond to the ENTER key, regardless of
@@ -120,10 +122,13 @@ RegisterDialog::RegisterDialog(LoginData *loginData):
mPasswordField->setActionEventId("register");
mConfirmField->setActionEventId("register");
mServerField->setActionEventId("register");
+ mPortField->setActionEventId("register");
+
mUserField->addActionListener(this);
mPasswordField->addActionListener(this);
mConfirmField->addActionListener(this);
mServerField->addActionListener(this);
+ mPortField->addActionListener(this);
setLocationRelativeTo(getParent());
setVisible(true);
@@ -216,7 +221,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event)
mRegisterButton->setEnabled(false);
mLoginData->hostname = mServerField->getText();
- mLoginData->port = (short) config.getValue("port", 0);
+ mLoginData->port = getUShort(mPortField->getText());
mLoginData->username = mUserField->getText();
mLoginData->password = mPasswordField->getText();
mLoginData->username += mFemaleButton->isSelected() ? "_F" : "_M";
@@ -238,5 +243,40 @@ bool RegisterDialog::canSubmit() const
!mPasswordField->getText().empty() &&
!mConfirmField->getText().empty() &&
!mServerField->getText().empty() &&
+ isUShort(mPortField->getText()) &&
state == REGISTER_STATE;
}
+
+bool RegisterDialog::isUShort(const std::string &str)
+{
+ if (str.empty())
+ {
+ return false;
+ }
+ unsigned long l = 0;
+ for (std::string::const_iterator strPtr = str.begin(), strEnd = str.end();
+ strPtr != strEnd; ++strPtr)
+ {
+ if (*strPtr < '0' || *strPtr > '9')
+ {
+ return false;
+ }
+ l = l * 10 + (*strPtr - '0'); // *strPtr - '0' will never be negative
+ if (l > 65535)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+unsigned short RegisterDialog::getUShort(const std::string &str)
+{
+ unsigned long l = 0;
+ for (std::string::const_iterator strPtr = str.begin(), strEnd = str.end();
+ strPtr != strEnd; ++strPtr)
+ {
+ l = l * 10 + (*strPtr - '0');
+ }
+ return static_cast<unsigned short>(l);
+}
diff --git a/src/gui/register.h b/src/gui/register.h
index 3dddae0f..9588e07e 100644
--- a/src/gui/register.h
+++ b/src/gui/register.h
@@ -22,12 +22,12 @@
#ifndef REGISTER_H
#define REGISTER_H
-#include <iosfwd>
+#include <string>
+
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
class LoginData;
class OkDialog;
@@ -72,10 +72,29 @@ class RegisterDialog : public Window, public gcn::ActionListener,
*/
bool canSubmit() const;
+ /**
+ * Function to decide whether string is an unsigned short or not
+ *
+ * @param str the string to parse
+ *
+ * @return true if str is an unsigned short, false otherwise
+ */
+ static bool isUShort(const std::string &str);
+
+ /**
+ * Converts string to an unsigned short (undefined if invalid)
+ *
+ * @param str the string to parse
+ *
+ * @return the value str represents
+ */
+ static unsigned short getUShort(const std::string &str);
+
gcn::TextField *mUserField;
gcn::TextField *mPasswordField;
gcn::TextField *mConfirmField;
gcn::TextField *mServerField;
+ gcn::TextField *mPortField;
gcn::Button *mRegisterButton;
gcn::Button *mCancelButton;
diff --git a/src/gui/scrollarea.cpp b/src/gui/scrollarea.cpp
index 8a74cd72..bc3a62dc 100644
--- a/src/gui/scrollarea.cpp
+++ b/src/gui/scrollarea.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <algorithm>
-
#include "scrollarea.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
@@ -31,19 +30,22 @@
#include "../utils/dtor.h"
int ScrollArea::instances = 0;
+float ScrollArea::mAlpha = config.getValue("guialpha", 0.8);
ImageRect ScrollArea::background;
ImageRect ScrollArea::vMarker;
Image *ScrollArea::buttons[4][2];
-ScrollArea::ScrollArea(bool gc):
+ScrollArea::ScrollArea(bool gc, bool opaque):
gcn::ScrollArea(),
+ mOpaque(opaque),
mGC(gc)
{
init();
}
-ScrollArea::ScrollArea(gcn::Widget *widget, bool gc):
+ScrollArea::ScrollArea(gcn::Widget *widget, bool gc, bool opaque):
gcn::ScrollArea(widget),
+ mOpaque(opaque),
mGC(gc)
{
init();
@@ -52,9 +54,8 @@ ScrollArea::ScrollArea(gcn::Widget *widget, bool gc):
ScrollArea::~ScrollArea()
{
// Garbage collection
- if (mGC) {
+ if (mGC)
delete getContent();
- }
instances--;
@@ -88,12 +89,15 @@ void ScrollArea::init()
const int bggridy[4] = {0, 3, 28, 31};
int a = 0, x, y;
- for (y = 0; y < 3; y++) {
- for (x = 0; x < 3; x++) {
+ for (y = 0; y < 3; y++)
+ {
+ for (x = 0; x < 3; x++)
+ {
background.grid[a] = textbox->getSubImage(
bggridx[x], bggridy[y],
bggridx[x + 1] - bggridx[x] + 1,
bggridy[y + 1] - bggridy[y] + 1);
+ background.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
a++;
}
}
@@ -106,12 +110,15 @@ void ScrollArea::init()
int vsgridy[4] = {0, 4, 15, 19};
a = 0;
- for (y = 0; y < 3; y++) {
- for (x = 0; x < 3; x++) {
+ for (y = 0; y < 3; y++)
+ {
+ for (x = 0; x < 3; x++)
+ {
vMarker.grid[a] = vscroll->getSubImage(
vsgridx[x], vsgridy[y],
vsgridx[x + 1] - vsgridx[x],
vsgridy[y + 1] - vsgridy[y]);
+ vMarker.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
a++;
}
}
@@ -146,7 +153,7 @@ void ScrollArea::logic()
// When no scrollbar in a certain direction, adapt content size to match
// the content dimension exactly.
- if (content != NULL)
+ if (content)
{
if (getHorizontalScrollPolicy() == gcn::ScrollArea::SHOW_NEVER)
{
@@ -188,6 +195,16 @@ void ScrollArea::draw(gcn::Graphics *graphics)
mScrollbarWidth));
}
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ for (int a = 0; a < 9; a++)
+ {
+ background.grid[a]->setAlpha(mAlpha);
+ vMarker.grid[a]->setAlpha(mAlpha);
+ }
+ }
+
drawChildren(graphics);
}
@@ -197,7 +214,8 @@ void ScrollArea::drawFrame(gcn::Graphics *graphics)
int w = getWidth() + bs * 2;
int h = getHeight() + bs * 2;
- if (mOpaque) {
+ if (mOpaque)
+ {
static_cast<Graphics*>(graphics)->
drawImageRect(0, 0, w, h, background);
}
@@ -207,10 +225,12 @@ void ScrollArea::setOpaque(bool opaque)
{
mOpaque = opaque;
- if (mOpaque) {
+ if (mOpaque)
+ {
setFrameSize(2);
}
- else {
+ else
+ {
setFrameSize(0);
}
}
@@ -220,7 +240,8 @@ void ScrollArea::drawButton(gcn::Graphics *graphics, BUTTON_DIR dir)
int state = 0;
gcn::Rectangle dim;
- switch(dir) {
+ switch (dir)
+ {
case UP:
state = mUpButtonPressed ? 1 : 0;
dim = getUpButtonDimension();
diff --git a/src/gui/scrollarea.h b/src/gui/scrollarea.h
index 1641f318..33ebc692 100644
--- a/src/gui/scrollarea.h
+++ b/src/gui/scrollarea.h
@@ -38,12 +38,12 @@ class ScrollArea : public gcn::ScrollArea
/**
* Constructor.
*/
- ScrollArea(bool gc = true);
+ ScrollArea(bool gc = true, bool opaque = true);
/**
* Constructor.
*/
- ScrollArea(gcn::Widget *content, bool gc = true);
+ ScrollArea(gcn::Widget *content, bool gc = true, bool opaque = true);
/**
* Destructor.
@@ -100,6 +100,7 @@ class ScrollArea : public gcn::ScrollArea
void drawHMarker(gcn::Graphics *graphics);
static int instances;
+ static float mAlpha;
static ImageRect background;
static ImageRect vMarker;
static Image *buttons[4][2];
diff --git a/src/gui/sdlinput.cpp b/src/gui/sdlinput.cpp
index f68dc9c8..51442798 100644
--- a/src/gui/sdlinput.cpp
+++ b/src/gui/sdlinput.cpp
@@ -228,7 +228,7 @@ int SDLInput::convertMouseButton(int button)
int SDLInput::convertKeyCharacter(SDL_Event event)
{
SDL_keysym keysym = event.key.keysym;
-
+
int value = keysym.unicode;
switch (keysym.sym)
diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp
index cc6f02d5..e4be7921 100644
--- a/src/gui/sell.cpp
+++ b/src/gui/sell.cpp
@@ -19,25 +19,19 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "sell.h"
-
-#include <cassert>
-
#include <guichan/widgets/label.hpp>
#include "button.h"
-#include "shoplistbox.h"
#include "scrollarea.h"
+#include "sell.h"
#include "shop.h"
+#include "shoplistbox.h"
#include "slider.h"
#include "widgets/layout.h"
-#include "../item.h"
#include "../npc.h"
-#include "../resources/iteminfo.h"
-
#include "../net/messageout.h"
#include "../net/protocol.h"
diff --git a/src/gui/sell.h b/src/gui/sell.h
index 8e639a3d..c11a7b7c 100644
--- a/src/gui/sell.h
+++ b/src/gui/sell.h
@@ -25,9 +25,9 @@
#include <guichan/actionlistener.hpp>
#include <guichan/selectionlistener.hpp>
-#include "window.h"
+#include <SDL_types.h>
-#include "../guichanfwd.h"
+#include "window.h"
class Item;
class Network;
diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp
index d38fb2e3..09eaeff0 100644
--- a/src/gui/setup.cpp
+++ b/src/gui/setup.cpp
@@ -19,31 +19,30 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup.h"
-
#include "button.h"
+#include "setup.h"
#include "setup_audio.h"
+#include "setup_colors.h"
#include "setup_joystick.h"
-#include "setup_video.h"
#include "setup_keyboard.h"
#include "setup_players.h"
+#include "setup_video.h"
#include "widgets/tabbedarea.h"
#include "../utils/dtor.h"
#include "../utils/gettext.h"
-#include <algorithm>
-#include <iostream>
-
-extern Window *statusWindow;
-extern Window *minimap;
extern Window *chatWindow;
-extern Window *inventoryWindow;
extern Window *equipmentWindow;
extern Window *helpWindow;
+extern Window *inventoryWindow;
+extern Window *minimap;
extern Window *skillDialog;
+extern Window *statusWindow;
extern Window *itemShortcutWindow;
+extern Window *emoteShortcutWindow;
+extern Window *emoteWindow;
extern Window *tradeWindow;
Setup::Setup():
@@ -58,7 +57,8 @@ Setup::Setup():
N_("Apply"), N_("Cancel"), N_("Reset Windows"), 0
};
int x = width;
- for (const char **curBtn = buttonNames; *curBtn; ++curBtn) {
+ for (const char **curBtn = buttonNames; *curBtn; ++curBtn)
+ {
Button *btn = new Button(gettext(*curBtn), *curBtn, this);
x -= btn->getWidth() + 5;
btn->setPosition(x, height - btn->getHeight() - 5);
@@ -90,6 +90,10 @@ Setup::Setup():
panel->addTab(_("Keyboard"), tab);
mTabs.push_back(tab);
+ tab = new Setup_Colors();
+ panel->addTab(_("Colors"), tab);
+ mTabs.push_back(tab);
+
tab = new Setup_Players();
panel->addTab(_("Players"), tab);
mTabs.push_back(tab);
@@ -131,6 +135,8 @@ void Setup::action(const gcn::ActionEvent &event)
helpWindow->resetToDefaultSize();
skillDialog->resetToDefaultSize();
itemShortcutWindow->resetToDefaultSize();
+ emoteShortcutWindow->resetToDefaultSize();
+ emoteWindow->resetToDefaultSize();
tradeWindow->resetToDefaultSize();
}
}
diff --git a/src/gui/setup.h b/src/gui/setup.h
index 881961f6..e4eb0902 100644
--- a/src/gui/setup.h
+++ b/src/gui/setup.h
@@ -28,6 +28,8 @@
#include "window.h"
+#include "../guichanfwd.h"
+
class SetupTab;
/**
@@ -51,8 +53,7 @@ class Setup : public Window, public gcn::ActionListener
/**
* Event handling method.
*/
- void
- action(const gcn::ActionEvent &event);
+ void action(const gcn::ActionEvent &event);
private:
std::list<SetupTab*> mTabs;
diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp
index b9fc1d2d..5c189882 100644
--- a/src/gui/setup_audio.cpp
+++ b/src/gui/setup_audio.cpp
@@ -19,12 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup_audio.h"
-
#include <guichan/widgets/label.hpp>
#include "checkbox.h"
#include "ok_dialog.h"
+#include "setup_audio.h"
#include "slider.h"
#include "widgets/layouthelper.h"
@@ -110,8 +109,8 @@ void Setup_Audio::cancel()
sound.setMusicVolume(mMusicVolume);
mMusicSlider->setValue(mMusicVolume);
- config.setValue("sound", mSoundEnabled ? 1 : 0);
- config.setValue("sfxVolume", mSfxVolume ? 1 : 0);
+ config.setValue("sound", mSoundEnabled ? true : false);
+ config.setValue("sfxVolume", mSfxVolume);
config.setValue("musicVolume", mMusicVolume);
}
diff --git a/src/gui/setup_audio.h b/src/gui/setup_audio.h
index 5345d3cf..9e951895 100644
--- a/src/gui/setup_audio.h
+++ b/src/gui/setup_audio.h
@@ -22,11 +22,9 @@
#ifndef GUI_SETUP_AUDIO_H
#define GUI_SETUP_AUDIO_H
-#include "setuptab.h"
-
#include <guichan/actionlistener.hpp>
-#include "../guichanfwd.h"
+#include "setuptab.h"
class Setup_Audio : public SetupTab, public gcn::ActionListener
{
diff --git a/src/gui/setup_colors.cpp b/src/gui/setup_colors.cpp
new file mode 100644
index 00000000..372dbd17
--- /dev/null
+++ b/src/gui/setup_colors.cpp
@@ -0,0 +1,249 @@
+/*
+ * Configurable text colors
+ * Copyright (C) 2008 Douglas Boffey <dougaboffey@netscape.net>
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string>
+#include <cmath>
+
+#include <guichan/listmodel.hpp>
+#include <guichan/widgets/label.hpp>
+#include <guichan/widgets/slider.hpp>
+
+#include "browserbox.h"
+#include "color.h"
+#include "itemlinkhandler.h"
+#include "listbox.h"
+#include "scrollarea.h"
+#include "setup_colors.h"
+#include "slider.h"
+#include "textfield.h"
+
+#include "widgets/layouthelper.h"
+
+#include "../configuration.h"
+
+#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+Setup_Colors::Setup_Colors() :
+ mSelected(-1)
+{
+ setOpaque(false);
+
+ mColorBox = new ListBox(textColor);
+ mColorBox->setActionEventId("color_box");
+ mColorBox->addActionListener(this);
+
+ mScroll = new ScrollArea(mColorBox);
+ mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+
+ mPreview = new BrowserBox(BrowserBox::AUTO_WRAP);
+ mPreview->setOpaque(false);
+
+ // Replace this later with a more appropriate link handler. For now, this'll
+ // do, as it'll do nothing when clicked on.
+ mPreview->setLinkHandler(new ItemLinkHandler());
+
+ mPreviewBox = new ScrollArea(mPreview);
+ mPreviewBox->setHeight(20);
+ mPreviewBox->setScrollPolicy(gcn::ScrollArea::SHOW_NEVER,
+ gcn::ScrollArea::SHOW_NEVER);
+
+ mRedLabel = new gcn::Label(_("Red: "));
+
+ mRedText = new TextField();
+ mRedText->setWidth(40);
+ mRedText->setRange(0, 255);
+ mRedText->setNumeric(true);
+ mRedText->addListener(this);
+
+ mRedSlider = new Slider(0, 255);
+ mRedSlider->setWidth(160);
+ mRedSlider->setValue(mRedText->getValue());
+ mRedSlider->setActionEventId("slider_red");
+ mRedSlider->addActionListener(this);
+
+ mGreenLabel = new gcn::Label(_("Green: "));
+
+ mGreenText = new TextField();
+ mGreenText->setWidth(40);
+ mGreenText->setRange(0, 255);
+ mGreenText->setNumeric(true);
+ mGreenText->addListener(this);
+
+ mGreenSlider = new Slider(0, 255);
+ mGreenSlider->setWidth(160);
+ mGreenSlider->setValue(mGreenText->getValue());
+ mGreenSlider->setActionEventId("slider_green");
+ mGreenSlider->addActionListener(this);
+
+ mBlueLabel = new gcn::Label(_("Blue: "));
+
+ mBlueText = new TextField();
+ mBlueText->setWidth(40);
+ mBlueText->setRange(0, 255);
+ mBlueText->setNumeric(true);
+ mBlueText->addListener(this);
+
+ mBlueSlider = new Slider(0, 255);
+ mBlueSlider->setWidth(160);
+ mBlueSlider->setValue(mBlueText->getValue());
+ mBlueSlider->setActionEventId("slider_blue");
+ mBlueSlider->addActionListener(this);
+
+ setOpaque(false);
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, mScroll, 4, 7).setPadding(2);
+ place(0, 7, mPreviewBox, 4).setPadding(2);
+ place(0, 8, mRedLabel, 2);
+ place(2, 8, mRedSlider);
+ place(3, 8, mRedText).setPadding(1);
+ place(0, 9, mGreenLabel, 2);
+ place(2, 9, mGreenSlider);
+ place(3, 9, mGreenText).setPadding(1);
+ place(0, 10, mBlueLabel, 2);
+ place(2, 10, mBlueSlider);
+ place(3, 10, mBlueText).setPadding(1);
+
+ setDimension(gcn::Rectangle(0, 0, 290, 250));
+}
+
+Setup_Colors::~Setup_Colors()
+{
+ delete mRedLabel;
+ delete mRedSlider;
+ delete mRedText;
+
+ delete mGreenLabel;
+ delete mGreenSlider;
+ delete mGreenText;
+
+ delete mBlueLabel;
+ delete mBlueSlider;
+ delete mBlueText;
+
+ delete mScroll;
+}
+
+void Setup_Colors::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == "color_box")
+ {
+ mSelected = mColorBox->getSelected();
+ int col = textColor->getColorAt(mSelected);
+ char ch = textColor->getColorCharAt(mSelected);
+ std::string msg;
+
+ if (ch == '<')
+ msg = toString("@@|") +
+ _("This is what the color looks like") + "@@";
+ else
+ msg = "##" + toString(ch) +
+ _("This is what the color looks like");
+
+ mPreview->clearRows();
+ mPreview->addRow(msg);
+ setEntry(mRedSlider, mRedText, col >> 16);
+ setEntry(mGreenSlider, mGreenText, (col >> 8) & 0xff);
+ setEntry(mBlueSlider, mBlueText, col & 0xff);
+ return;
+ }
+
+ if (event.getId() == "slider_red")
+ {
+ mRedText->setText(toString(std::floor(mRedSlider->getValue())));
+ updateColor();
+ return;
+ }
+
+ if (event.getId() == "slider_green")
+ {
+ mGreenText->setText(toString(std::floor(mGreenSlider->getValue())));
+ updateColor();
+ return;
+ }
+
+ if (event.getId() == "slider_blue")
+ {
+ mBlueText->setText(toString(std::floor(mBlueSlider->getValue())));
+ updateColor();
+ return;
+ }
+}
+
+void Setup_Colors::setEntry(gcn::Slider *s, TextField *t, int value)
+{
+ s->setValue(value);
+ char buffer[100];
+ sprintf(buffer, "%d", value);
+ t->setText(buffer);
+}
+
+void Setup_Colors::apply()
+{
+ textColor->commit();
+}
+
+void Setup_Colors::cancel()
+{
+ textColor->rollback();
+ int col = textColor->getColorAt(mSelected);
+ setEntry(mRedSlider, mRedText, col >> 16);
+ setEntry(mGreenSlider, mGreenText, (col >> 8) & 0xff);
+ setEntry(mBlueSlider, mBlueText, col & 0xff);
+}
+
+void Setup_Colors::listen(const TextField *tf)
+{
+ if (tf == mRedText)
+ {
+ mRedSlider->setValue(tf->getValue());
+ updateColor();
+ return;
+ }
+ if (tf == mGreenText)
+ {
+ mGreenSlider->setValue(tf->getValue());
+ updateColor();
+ return;
+ }
+ if (tf == mBlueText)
+ {
+ mBlueSlider->setValue(tf->getValue());
+ updateColor();
+ return;
+ }
+}
+
+void Setup_Colors::updateColor()
+{
+ if (mSelected == -1)
+ {
+ return;
+ }
+ int rgb = static_cast<int>(mRedSlider->getValue()) << 16 |
+ static_cast<int>(mGreenSlider->getValue()) << 8 |
+ static_cast<int>(mBlueSlider->getValue());
+ textColor->setColorAt(mSelected, rgb);
+}
diff --git a/src/gui/setup_colors.h b/src/gui/setup_colors.h
new file mode 100644
index 00000000..8fd1ba59
--- /dev/null
+++ b/src/gui/setup_colors.h
@@ -0,0 +1,75 @@
+/*
+ * Configurable text colors
+ * Copyright (C) 2008 Douglas Boffey <dougaboffey@netscape.net>
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SETUP_COLOURS_H
+#define SETUP_COLOURS_H
+
+#include <string>
+
+#include <guichan/actionlistener.hpp>
+
+#include <guichan/widgets/label.hpp>
+#include <guichan/widgets/listbox.hpp>
+
+#include "setuptab.h"
+#include "textfield.h"
+
+#include "../guichanfwd.h"
+
+class BrowserBox;
+
+class Setup_Colors : public SetupTab, public gcn::ActionListener,
+ public TextFieldListener
+{
+ public:
+ Setup_Colors();
+ ~Setup_Colors();
+ void apply();
+ void cancel();
+ void action(const gcn::ActionEvent &event);
+
+ void listen(const TextField *tf);
+ private:
+ gcn::ListBox *mColorBox;
+ gcn::ScrollArea *mScroll;
+ BrowserBox *mPreview;
+ gcn::ScrollArea *mPreviewBox;
+ int mSelected;
+
+ gcn::Label *mRedLabel;
+ gcn::Slider *mRedSlider;
+ TextField *mRedText;
+ int mRedValue;
+
+ gcn::Label *mGreenLabel;
+ gcn::Slider *mGreenSlider;
+ TextField *mGreenText;
+ int mGreenValue;
+
+ gcn::Label *mBlueLabel;
+ gcn::Slider *mBlueSlider;
+ TextField *mBlueText;
+ int mBlueValue;
+
+ void setEntry(gcn::Slider *s, TextField *t, int value);
+ void updateColor();
+};
+#endif
diff --git a/src/gui/setup_joystick.cpp b/src/gui/setup_joystick.cpp
index f8fc194f..2ebcdbde 100644
--- a/src/gui/setup_joystick.cpp
+++ b/src/gui/setup_joystick.cpp
@@ -19,12 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup_joystick.h"
-
#include <guichan/widgets/label.hpp>
#include "button.h"
#include "checkbox.h"
+#include "setup_joystick.h"
#include "widgets/layouthelper.h"
@@ -42,7 +41,7 @@ Setup_Joystick::Setup_Joystick():
{
setOpaque(false);
- mOriginalJoystickEnabled = (int)config.getValue("joystickEnabled", 0) != 0;
+ mOriginalJoystickEnabled = !config.getValue("joystickEnabled", false);
mJoystickEnabled->setSelected(mOriginalJoystickEnabled);
mJoystickEnabled->addActionListener(this);
@@ -62,7 +61,8 @@ Setup_Joystick::Setup_Joystick():
void Setup_Joystick::action(const gcn::ActionEvent &event)
{
- if (!joystick) {
+ if (!joystick)
+ {
return;
}
@@ -72,12 +72,15 @@ void Setup_Joystick::action(const gcn::ActionEvent &event)
}
else
{
- if (joystick->isCalibrating()) {
+ if (joystick->isCalibrating())
+ {
mCalibrateButton->setCaption(_("Calibrate"));
mCalibrateLabel->setCaption
(_("Press the button to start calibration"));
joystick->finishCalibration();
- } else {
+ }
+ else
+ {
mCalibrateButton->setCaption(_("Stop"));
mCalibrateLabel->setCaption(_("Rotate the stick"));
joystick->startCalibration();
diff --git a/src/gui/setup_joystick.h b/src/gui/setup_joystick.h
index dd8c331f..eba8a2cc 100644
--- a/src/gui/setup_joystick.h
+++ b/src/gui/setup_joystick.h
@@ -22,11 +22,9 @@
#ifndef GUI_SETUP_JOYSTICK_H
#define GUI_SETUP_JOYSTICK_H
-#include "setuptab.h"
-
#include <guichan/actionlistener.hpp>
-#include "../guichanfwd.h"
+#include "setuptab.h"
class Setup_Joystick : public SetupTab, public gcn::ActionListener
{
diff --git a/src/gui/setup_keyboard.cpp b/src/gui/setup_keyboard.cpp
index cf44731c..5d7519ef 100644
--- a/src/gui/setup_keyboard.cpp
+++ b/src/gui/setup_keyboard.cpp
@@ -1,6 +1,7 @@
/*
- * The Mana World
- * Copyright (C) 2007 The Mana World Development Team
+ * Custom keyboard shortcuts configuration
+ * Copyright (C) 2007 Joshua Langley <joshlangley@optusnet.com.au>
+ * Copyright (C) 2009 The Mana World Development Team
*
* This file is part of The Mana World.
*
@@ -19,7 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup_keyboard.h"
+#include <SDL_keyboard.h>
#include <guichan/widgets/label.hpp>
#include <guichan/listmodel.hpp>
@@ -28,17 +29,15 @@
#include "listbox.h"
#include "ok_dialog.h"
#include "scrollarea.h"
+#include "setup_keyboard.h"
#include "widgets/layouthelper.h"
-#include "../configuration.h"
#include "../keyboardconfig.h"
#include "../utils/gettext.h"
#include "../utils/tostring.h"
-#include <SDL_keyboard.h>
-
/**
* The list model for key function list.
*
@@ -79,11 +78,10 @@ Setup_Keyboard::Setup_Keyboard():
refreshKeys();
- mKeyList->setDimension(gcn::Rectangle(0, 0, 185, 140));
mKeyList->addActionListener(this);
- mKeyList->setSelected(-1);
ScrollArea *scrollArea = new ScrollArea(mKeyList);
+ scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
mAssignKeyButton = new Button(_("Assign"), "assign", this);
mAssignKeyButton->addActionListener(this);
@@ -140,9 +138,8 @@ void Setup_Keyboard::action(const gcn::ActionEvent &event)
{
if (event.getSource() == mKeyList)
{
- if (!mKeySetting) {
+ if (!mKeySetting)
mAssignKeyButton->setEnabled(true);
- }
}
else if (event.getId() == "assign")
{
@@ -186,7 +183,8 @@ void Setup_Keyboard::refreshKeys()
void Setup_Keyboard::keyUnresolved()
{
- if (mKeySetting) {
+ if (mKeySetting)
+ {
newKeyCallback(keyboard.getNewKeyIndex());
keyboard.setNewKeyIndex(keyboard.KEY_NO_VALUE);
}
diff --git a/src/gui/setup_keyboard.h b/src/gui/setup_keyboard.h
index f04be792..dee12135 100644
--- a/src/gui/setup_keyboard.h
+++ b/src/gui/setup_keyboard.h
@@ -1,6 +1,6 @@
/*
- * The Mana World
- * Copyright (C) 2007 The Mana World Development Team
+ * Custom keyboard shortcuts configuration
+ * Copyright (C) 2007 Joshua Langley <joshlangley@optusnet.com.au>
*
* This file is part of The Mana World.
*
@@ -22,14 +22,13 @@
#ifndef GUI_SETUP_KEYBOARD_H
#define GUI_SETUP_KEYBOARD_H
-#include "setuptab.h"
-#include "button.h"
-#include "../guichanfwd.h"
+#include <string>
#include <guichan/actionlistener.hpp>
+#include "setuptab.h"
-#include <string>
+#include "../guichanfwd.h"
class Setup_Keyboard : public SetupTab, public gcn::ActionListener
{
diff --git a/src/gui/setup_players.cpp b/src/gui/setup_players.cpp
index 1d8649eb..d25117de 100644
--- a/src/gui/setup_players.cpp
+++ b/src/gui/setup_players.cpp
@@ -19,26 +19,27 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup_players.h"
+#include <string>
+#include <vector>
+
+#include <guichan/widgets/label.hpp>
#include "button.h"
#include "checkbox.h"
+#include "listbox.h"
#include "ok_dialog.h"
+#include "scrollarea.h"
+#include "setup_players.h"
+#include "table.h"
+#include "widgets/dropdown.h"
#include "widgets/layouthelper.h"
#include "../configuration.h"
#include "../log.h"
-#include "../player_relations.h"
-#include "../sound.h"
#include "../utils/gettext.h"
-#include <guichan/widgets/dropdown.hpp>
-#include <guichan/widgets/label.hpp>
-
-#include <vector>
-
#define COLUMNS_NR 2 // name plus listbox
#define NAME_COLUMN 0
#define RELATION_CHOICE_COLUMN 1
@@ -136,8 +137,12 @@ public:
std::string name = (*player_names)[r];
gcn::Widget *widget = new gcn::Label(name);
mWidgets.push_back(widget);
+ gcn::ListModel *playerRelation = new PlayerRelationListModel();
- gcn::DropDown *choicebox = new gcn::DropDown(new PlayerRelationListModel());
+ gcn::DropDown *choicebox = new DropDown(playerRelation,
+ new ScrollArea(),
+ new ListBox(playerRelation),
+ false);
choicebox->setSelected(player_relations.getRelation(name));
mWidgets.push_back(choicebox);
}
@@ -198,7 +203,7 @@ public:
virtual std::string getElementAt(int i)
{
if (i >= getNumberOfElements()) {
- return "???";
+ return _("???");
}
return (*player_relations.getPlayerIgnoreStrategies())[i]->mDescription;
}
@@ -220,18 +225,22 @@ Setup_Players::Setup_Players():
player_relations.getDefault() & PlayerRelation::TRADE)),
mDefaultWhisper(new CheckBox(_("Allow whispers"),
player_relations.getDefault() & PlayerRelation::WHISPER)),
- mDeleteButton(new Button(_("Delete"), ACTION_DELETE, this)),
- mIgnoreActionChoicesBox(new gcn::DropDown(new IgnoreChoicesListModel()))
+ mDeleteButton(new Button(_("Delete"), ACTION_DELETE, this))
{
setOpaque(false);
+ mPlayerTable->setOpaque(false);
int table_width = NAME_COLUMN_WIDTH + RELATION_CHOICE_COLUMN_WIDTH;
mPlayerTableTitleModel->fixColumnWidth(NAME_COLUMN, NAME_COLUMN_WIDTH);
mPlayerTableTitleModel->fixColumnWidth(RELATION_CHOICE_COLUMN,
RELATION_CHOICE_COLUMN_WIDTH);
- mPlayerTitleTable->setDimension(gcn::Rectangle(10, 10, table_width, 10));
+ mPlayerTitleTable->setDimension(gcn::Rectangle(10, 10, table_width - 1, 10));
mPlayerTitleTable->setBackgroundColor(gcn::Color(0xbf, 0xbf, 0xbf));
+ gcn::ListModel *ignoreChoices = new IgnoreChoicesListModel();
+ mIgnoreActionChoicesBox = new DropDown(ignoreChoices, new ScrollArea(),
+ new ListBox(ignoreChoices), false);
+
for (int i = 0; i < COLUMNS_NR; i++)
{
mPlayerTableTitleModel->set(0, i,
diff --git a/src/gui/setup_players.h b/src/gui/setup_players.h
index d380d9f6..74247b77 100644
--- a/src/gui/setup_players.h
+++ b/src/gui/setup_players.h
@@ -22,20 +22,19 @@
#ifndef GUI_SETUP_PLAYERS_H
#define GUI_SETUP_PLAYERS_H
-#include "setuptab.h"
-
-#include "scrollarea.h"
-#include "button.h"
-#include "table.h"
#include <guichan/actionlistener.hpp>
-#include "../guichanfwd.h"
+#include "setuptab.h"
#include "../player_relations.h"
+class GuiTable;
class PlayerTableModel;
+class StaticTableModel;
-class Setup_Players : public SetupTab, public gcn::ActionListener, public PlayerRelationsListener
+class Setup_Players : public SetupTab,
+ public gcn::ActionListener,
+ public PlayerRelationsListener
{
public:
Setup_Players();
@@ -55,13 +54,13 @@ private:
PlayerTableModel *mPlayerTableModel;
GuiTable *mPlayerTable;
GuiTable *mPlayerTitleTable;
- ScrollArea *mPlayerScrollArea;
+ gcn::ScrollArea *mPlayerScrollArea;
gcn::CheckBox *mPersistIgnores;
gcn::CheckBox *mDefaultTrading;
gcn::CheckBox *mDefaultWhisper;
- Button *mDeleteButton;
+ gcn::Button *mDeleteButton;
gcn::DropDown *mIgnoreActionChoicesBox;
};
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index 53041a9c..c02025c8 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -19,11 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup_video.h"
-
+#include <SDL.h>
#include <string>
#include <vector>
-#include <SDL.h>
#include <guichan/key.hpp>
#include <guichan/listmodel.hpp>
@@ -34,6 +32,7 @@
#include "listbox.h"
#include "ok_dialog.h"
#include "scrollarea.h"
+#include "setup_video.h"
#include "slider.h"
#include "textfield.h"
@@ -41,6 +40,7 @@
#include "../configuration.h"
#include "../graphics.h"
+#include "../localplayer.h"
#include "../log.h"
#include "../main.h"
#include "../particle.h"
@@ -104,9 +104,12 @@ ModeListModel::ModeListModel()
}
Setup_Video::Setup_Video():
- mFullScreenEnabled(config.getValue("screen", 0)),
- mOpenGLEnabled(config.getValue("opengl", 0)),
- mCustomCursorEnabled(config.getValue("customcursor", 1)),
+ mFullScreenEnabled(config.getValue("screen", false)),
+ mOpenGLEnabled(config.getValue("opengl", false)),
+ mCustomCursorEnabled(config.getValue("customcursor", true)),
+ mParticleEffectsEnabled(config.getValue("particleeffects", true)),
+ mSpeechBubbleEnabled(config.getValue("speechbubble", true)),
+ mNameEnabled(config.getValue("showownname", false)),
mOpacity(config.getValue("guialpha", 0.8)),
mFps((int) config.getValue("fpslimit", 0)),
mModeListModel(new ModeListModel),
@@ -114,6 +117,9 @@ Setup_Video::Setup_Video():
mFsCheckBox(new CheckBox(_("Full screen"), mFullScreenEnabled)),
mOpenGLCheckBox(new CheckBox(_("OpenGL"), mOpenGLEnabled)),
mCustomCursorCheckBox(new CheckBox(_("Custom cursor"), mCustomCursorEnabled)),
+ mParticleEffectsCheckBox(new CheckBox(_("Particle effects"), mParticleEffectsEnabled)),
+ mSpeechBubbleCheckBox(new CheckBox(_("Speech bubbles"), mSpeechBubbleEnabled)),
+ mNameCheckBox(new CheckBox(_("Show name"), mNameEnabled)),
mAlphaSlider(new Slider(0.2, 1.0)),
mFpsCheckBox(new CheckBox(_("FPS Limit:"))),
mFpsSlider(new Slider(10, 200)),
@@ -137,13 +143,12 @@ Setup_Video::Setup_Video():
scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
gcn::Label *alphaLabel = new gcn::Label(_("Gui opacity"));
-
gcn::Label *scrollRadiusLabel = new gcn::Label(_("Scroll radius"));
gcn::Label *scrollLazinessLabel = new gcn::Label(_("Scroll laziness"));
gcn::Label *overlayDetailLabel = new gcn::Label(_("Ambient FX"));
gcn::Label *particleDetailLabel = new gcn::Label(_("Particle Detail"));
- mModeList->setEnabled(false);
+ mModeList->setEnabled(true);
#ifndef USE_OPENGL
mOpenGLCheckBox->setEnabled(false);
#endif
@@ -159,7 +164,11 @@ Setup_Video::Setup_Video():
mFpsSlider->setEnabled(mFps > 0);
mFpsCheckBox->setSelected(mFps > 0);
+ mModeList->setActionEventId("videomode");
mCustomCursorCheckBox->setActionEventId("customcursor");
+ mParticleEffectsCheckBox->setActionEventId("particleeffects");
+ mSpeechBubbleCheckBox->setActionEventId("speechbubble");
+ mNameCheckBox->setActionEventId("showownname");
mAlphaSlider->setActionEventId("guialpha");
mFpsCheckBox->setActionEventId("fpslimitcheckbox");
mFpsSlider->setActionEventId("fpslimitslider");
@@ -172,7 +181,11 @@ Setup_Video::Setup_Video():
mParticleDetailSlider->setActionEventId("particledetailslider");
mParticleDetailField->setActionEventId("particledetailfield");
+ mModeList->addActionListener(this);
mCustomCursorCheckBox->addActionListener(this);
+ mParticleEffectsCheckBox->addActionListener(this);
+ mSpeechBubbleCheckBox->addActionListener(this);
+ mNameCheckBox->addActionListener(this);
mAlphaSlider->addActionListener(this);
mFpsCheckBox->addActionListener(this);
mFpsSlider->addActionListener(this);
@@ -227,30 +240,33 @@ Setup_Video::Setup_Video():
LayoutHelper h(this);
ContainerPlacer place = h.getPlacer(0, 0);
- place(0, 0, scrollArea, 1, 4).setPadding(2);
+ place(0, 0, scrollArea, 1, 6).setPadding(2);
place(1, 0, mFsCheckBox, 3);
place(1, 1, mOpenGLCheckBox, 3);
place(1, 2, mCustomCursorCheckBox, 3);
-
- place(0, 4, mAlphaSlider);
- place(0, 5, mFpsSlider);
- place(0, 6, mScrollRadiusSlider);
- place(0, 7, mScrollLazinessSlider);
- place(0, 8, mOverlayDetailSlider);
- place(0, 9, mParticleDetailSlider);
-
- place(1, 4, alphaLabel, 2);
- place(1, 5, mFpsCheckBox).setPadding(3);
- place(1, 6, scrollRadiusLabel);
- place(1, 7, scrollLazinessLabel);
- place(1, 8, overlayDetailLabel);
- place(1, 9, particleDetailLabel);
-
- place(2, 5, mFpsField).setPadding(1);
- place(2, 6, mScrollRadiusField).setPadding(1);
- place(2, 7, mScrollLazinessField).setPadding(1);
- place(2, 8, mOverlayDetailField, 2).setPadding(2);
- place(2, 9, mParticleDetailField, 2).setPadding(2);
+ place(1, 3, mSpeechBubbleCheckBox, 3);
+ place(1, 4, mNameCheckBox, 3);
+ place(1, 5, mParticleEffectsCheckBox, 3);
+
+ place(0, 7, mAlphaSlider);
+ place(0, 8, mFpsSlider);
+ place(0, 9, mScrollRadiusSlider);
+ place(0, 10, mScrollLazinessSlider);
+ place(0, 11, mOverlayDetailSlider);
+ place(0, 12, mParticleDetailSlider);
+
+ place(1, 7, alphaLabel, 2);
+ place(1, 8, mFpsCheckBox).setPadding(3);
+ place(1, 9, scrollRadiusLabel);
+ place(1, 10, scrollLazinessLabel);
+ place(1, 11, overlayDetailLabel);
+ place(1, 12, particleDetailLabel);
+
+ place(2, 8, mFpsField).setPadding(1);
+ place(2, 9, mScrollRadiusField).setPadding(1);
+ place(2, 10, mScrollLazinessField).setPadding(1);
+ place(2, 11, mOverlayDetailField, 2).setPadding(2);
+ place(2, 12, mParticleDetailField, 2).setPadding(2);
setDimension(gcn::Rectangle(0, 0, 295, 250));
}
@@ -264,7 +280,7 @@ void Setup_Video::apply()
{
// Full screen changes
bool fullscreen = mFsCheckBox->isSelected();
- if (fullscreen != (config.getValue("screen", 0) == 1))
+ if (fullscreen != (config.getValue("screen", false) == 1))
{
/* The OpenGL test is only necessary on Windows, since switching
* to/from full screen works fine on Linux. On Windows we'd have to
@@ -275,7 +291,7 @@ void Setup_Video::apply()
#if defined(WIN32) || defined(__APPLE__)
// checks for opengl usage
- if (!(config.getValue("opengl", 0) == 1))
+ if (!(config.getValue("opengl", false) == 1))
{
#endif
if (!graphics->setFullscreen(fullscreen))
@@ -284,9 +300,9 @@ void Setup_Video::apply()
if (!graphics->setFullscreen(fullscreen))
{
std::stringstream error;
- error << "Failed to switch to " <<
- (fullscreen ? "windowed" : "fullscreen") <<
- "mode and restoration of old mode also failed!" <<
+ error << _("Failed to switch to ") <<
+ (fullscreen ? _("windowed") : _("fullscreen")) <<
+ _("mode and restoration of old mode also failed!") <<
std::endl;
logger->error(error.str());
}
@@ -297,13 +313,13 @@ void Setup_Video::apply()
_("Restart needed for changes to take effect."));
}
#endif
- config.setValue("screen", fullscreen ? 1 : 0);
+ config.setValue("screen", fullscreen ? true : false);
}
// OpenGL change
if (mOpenGLCheckBox->isSelected() != mOpenGLEnabled)
{
- config.setValue("opengl", mOpenGLCheckBox->isSelected() ? 1 : 0);
+ config.setValue("opengl", mOpenGLCheckBox->isSelected() ? true : false);
// OpenGL can currently only be changed by restarting, notify user.
new OkDialog(_("Changing OpenGL"),
@@ -314,11 +330,14 @@ void Setup_Video::apply()
config.setValue("fpslimit", mFps);
// We sync old and new values at apply time
- mFullScreenEnabled = config.getValue("screen", 0);
- mCustomCursorEnabled = config.getValue("customcursor", 1);
+ mFullScreenEnabled = config.getValue("screen", false);
+ mCustomCursorEnabled = config.getValue("customcursor", true);
+ mParticleEffectsEnabled = config.getValue("particleeffects", true);
+ mSpeechBubbleEnabled = config.getValue("speechbubble", true);
+ mNameEnabled = config.getValue("showownname", false);
mOpacity = config.getValue("guialpha", 0.8);
- mOverlayDetail = (int)config.getValue("OverlayDetail", 2);
- mOpenGLEnabled = config.getValue("opengl", 0);
+ mOverlayDetail = (int) config.getValue("OverlayDetail", 2);
+ mOpenGLEnabled = config.getValue("opengl", false);
}
int Setup_Video::updateSlider(gcn::Slider *slider, gcn::TextField *field,
@@ -346,6 +365,9 @@ void Setup_Video::cancel()
mFsCheckBox->setSelected(mFullScreenEnabled);
mOpenGLCheckBox->setSelected(mOpenGLEnabled);
mCustomCursorCheckBox->setSelected(mCustomCursorEnabled);
+ mParticleEffectsCheckBox->setSelected(mParticleEffectsEnabled);
+ mSpeechBubbleCheckBox->setSelected(mSpeechBubbleEnabled);
+ mNameCheckBox->setSelected(mNameEnabled);
mAlphaSlider->setValue(mOpacity);
mOverlayDetailSlider->setValue(mOverlayDetail);
mParticleDetailSlider->setValue(mParticleDetail);
@@ -355,22 +377,59 @@ void Setup_Video::cancel()
updateSlider(mScrollRadiusSlider, mScrollRadiusField, "ScrollRadius");
updateSlider(mScrollLazinessSlider, mScrollLazinessField, "ScrollLaziness");
- config.setValue("screen", mFullScreenEnabled ? 1 : 0);
- config.setValue("customcursor", mCustomCursorEnabled ? 1 : 0);
+ config.setValue("screen", mFullScreenEnabled ? true : false);
+ config.setValue("customcursor", mCustomCursorEnabled ? true : false);
+ config.setValue("particleeffects", mParticleEffectsEnabled ? true : false);
+ config.setValue("speechbubble", mSpeechBubbleEnabled ? true : false);
+ config.setValue("showownname", mNameEnabled ? true : false);
config.setValue("guialpha", mOpacity);
- config.setValue("opengl", mOpenGLEnabled ? 1 : 0);
+ config.setValue("opengl", mOpenGLEnabled ? true : false);
}
void Setup_Video::action(const gcn::ActionEvent &event)
{
- if (event.getId() == "guialpha")
+ if (event.getId() == "videomode")
+ {
+ const std::string mode = mModeListModel->getElementAt(mModeList->getSelected());
+ const int width = atoi(mode.substr(0, mode.find("x")).c_str());
+ const int height = atoi(mode.substr(mode.find("x") + 1).c_str());
+
+ // TODO: Find out why the drawing area doesn't resize without a restart.
+ new OkDialog(_("Screen resolution changed"),
+ _("Restart your client for the change to take effect."));
+
+ config.setValue("screenwidth", width);
+ config.setValue("screenheight", height);
+ }
+ else if (event.getId() == "guialpha")
{
config.setValue("guialpha", mAlphaSlider->getValue());
}
else if (event.getId() == "customcursor")
{
config.setValue("customcursor",
- mCustomCursorCheckBox->isSelected() ? 1 : 0);
+ mCustomCursorCheckBox->isSelected() ? true : false);
+ }
+ else if (event.getId() == "particleeffects")
+ {
+ config.setValue("particleeffects",
+ mParticleEffectsCheckBox->isSelected() ? true : false);
+ new OkDialog(_("Particle effect settings changed"),
+ _("Restart your client or change maps for the change to take effect."));
+ }
+ else if (event.getId() == "speechbubble")
+ {
+ config.setValue("speechbubble",
+ mSpeechBubbleCheckBox->isSelected() ? true : false);
+ }
+ else if (event.getId() == "showownname")
+ {
+ // Notify the local player that settings have changed for the name
+ // and requires an update
+ if (player_node)
+ player_node->mUpdateName = true;
+ config.setValue("showownname",
+ mNameCheckBox->isSelected() ? true : false);
}
else if (event.getId() == "fpslimitslider")
{
diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h
index b7011186..303b5bfc 100644
--- a/src/gui/setup_video.h
+++ b/src/gui/setup_video.h
@@ -22,12 +22,10 @@
#ifndef GUI_SETUP_VIDEO_H
#define GUI_SETUP_VIDEO_H
-#include "setuptab.h"
-
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
-#include "../guichanfwd.h"
+#include "setuptab.h"
class Setup_Video : public SetupTab, public gcn::ActionListener,
public gcn::KeyListener
@@ -53,6 +51,9 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
bool mFullScreenEnabled;
bool mOpenGLEnabled;
bool mCustomCursorEnabled;
+ bool mParticleEffectsEnabled;
+ bool mSpeechBubbleEnabled;
+ bool mNameEnabled;
double mOpacity;
int mFps;
@@ -62,6 +63,9 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
gcn::CheckBox *mFsCheckBox;
gcn::CheckBox *mOpenGLCheckBox;
gcn::CheckBox *mCustomCursorCheckBox;
+ gcn::CheckBox *mParticleEffectsCheckBox;
+ gcn::CheckBox *mSpeechBubbleCheckBox;
+ gcn::CheckBox *mNameCheckBox;
gcn::Slider *mAlphaSlider;
gcn::CheckBox *mFpsCheckBox;
diff --git a/src/gui/shop.h b/src/gui/shop.h
index 4a03b2bc..e0db4c59 100644
--- a/src/gui/shop.h
+++ b/src/gui/shop.h
@@ -27,10 +27,10 @@
#include <guichan/listmodel.hpp>
-#include "../resources/image.h"
-
#include "../shopitem.h"
+class ShopItem;
+
class ShopItems : public gcn::ListModel
{
public:
diff --git a/src/gui/shoplistbox.cpp b/src/gui/shoplistbox.cpp
index 2517d749..94187818 100644
--- a/src/gui/shoplistbox.cpp
+++ b/src/gui/shoplistbox.cpp
@@ -19,19 +19,20 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "shoplistbox.h"
-
#include <guichan/font.hpp>
-#include <guichan/graphics.hpp>
#include <guichan/listmodel.hpp>
-#include <guichan/mouseinput.hpp>
-#include <guichan/imagefont.hpp>
-#include <guichan/basiccontainer.hpp>
+#include "color.h"
+#include "shop.h"
+#include "shoplistbox.h"
+
+#include "../configuration.h"
#include "../graphics.h"
const int ITEM_ICON_SIZE = 32;
+float ShopListBox::mAlpha = config.getValue("guialpha", 0.8);
+
ShopListBox::ShopListBox(gcn::ListModel *listModel):
ListBox(listModel),
mPlayerMoney(0)
@@ -59,6 +60,15 @@ void ShopListBox::draw(gcn::Graphics *gcnGraphics)
if (!mListModel)
return;
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ mAlpha = config.getValue("guialpha", 0.8);
+
+ bool valid;
+ const int red = (textColor->getColor('H', valid) >> 16) & 0xFF;
+ const int green = (textColor->getColor('H', valid) >> 8) & 0xFF;
+ const int blue = textColor->getColor('H', valid) & 0xFF;
+ const int alpha = mAlpha * 255;
+
Graphics *graphics = static_cast<Graphics*>(gcnGraphics);
graphics->setFont(getFont());
@@ -68,16 +78,16 @@ void ShopListBox::draw(gcn::Graphics *gcnGraphics)
i < mListModel->getNumberOfElements();
++i, y += mRowHeight)
{
- gcn::Color backgroundColor = gcn::Color(0xffffff);
+ gcn::Color backgroundColor = gcn::Color(255, 255, 255, alpha);
if (i == mSelected)
{
- backgroundColor = gcn::Color(110, 160, 255);
+ backgroundColor = gcn::Color(red, green, blue, alpha);
}
else if (mShopItems &&
mPlayerMoney < mShopItems->at(i)->getPrice() && mPriceCheck)
{
- backgroundColor = gcn::Color(0x919191);
+ backgroundColor = gcn::Color(145, 145, 145, alpha);
}
graphics->setColor(backgroundColor);
diff --git a/src/gui/shoplistbox.h b/src/gui/shoplistbox.h
index bad848d6..cde4786e 100644
--- a/src/gui/shoplistbox.h
+++ b/src/gui/shoplistbox.h
@@ -23,7 +23,8 @@
#define SHOPLISTBOX_H
#include "listbox.h"
-#include "shop.h"
+
+class ShopItems;
/**
* A list box, meant to be used inside a scroll area. Same as the Guichan list
@@ -84,6 +85,8 @@ class ShopListBox : public ListBox
unsigned int mRowHeight; /**< Row Height */
+ static float mAlpha;
+
bool mPriceCheck;
};
diff --git a/src/gui/shortcutcontainer.cpp b/src/gui/shortcutcontainer.cpp
new file mode 100644
index 00000000..4472818e
--- /dev/null
+++ b/src/gui/shortcutcontainer.cpp
@@ -0,0 +1,71 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "shortcutcontainer.h"
+
+#include "../configuration.h"
+
+#include "../resources/image.h"
+
+#include "../utils/tostring.h"
+
+float ShortcutContainer::mAlpha = config.getValue("guialpha", 0.8);
+
+ShortcutContainer::ShortcutContainer():
+ mGridWidth(1),
+ mGridHeight(1)
+{
+}
+
+void ShortcutContainer::widgetResized(const gcn::Event &event)
+{
+ mGridWidth = getWidth() / mBoxWidth;
+ if (mGridWidth < 1)
+ {
+ mGridWidth = 1;
+ }
+
+ setHeight((mMaxItems / mGridWidth +
+ (mMaxItems % mGridWidth > 0 ? 1 : 0)) * mBoxHeight);
+
+ mGridHeight = getHeight() / mBoxHeight;
+ if (mGridHeight < 1)
+ {
+ mGridHeight = 1;
+ }
+}
+
+int ShortcutContainer::getIndexFromGrid(int pointX, int pointY) const
+{
+ const gcn::Rectangle tRect = gcn::Rectangle(
+ 0, 0, mGridWidth * mBoxWidth, mGridHeight * mBoxHeight);
+ if (!tRect.isPointInRect(pointX, pointY))
+ {
+ return -1;
+ }
+ const int index = ((pointY / mBoxHeight) * mGridWidth) +
+ pointX / mBoxWidth;
+ if (index >= mMaxItems)
+ {
+ return -1;
+ }
+ return index;
+}
diff --git a/src/gui/shortcutcontainer.h b/src/gui/shortcutcontainer.h
new file mode 100644
index 00000000..f5f06163
--- /dev/null
+++ b/src/gui/shortcutcontainer.h
@@ -0,0 +1,107 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SHORTCUTCONTAINER_H__
+#define SHORTCUTCONTAINER_H__
+
+#include <guichan/mouselistener.hpp>
+#include <guichan/widget.hpp>
+#include <guichan/widgetlistener.hpp>
+
+class Image;
+
+/**
+ * A generic shortcut container.
+ *
+ * \ingroup GUI
+ */
+class ShortcutContainer : public gcn::Widget,
+ public gcn::WidgetListener,
+ public gcn::MouseListener
+{
+ public:
+ /**
+ * Constructor. Initializes the shortcut container.
+ */
+ ShortcutContainer();
+
+ /**
+ * Destructor.
+ */
+ ~ShortcutContainer(){}
+
+ /**
+ * Draws the shortcuts
+ */
+ virtual void draw(gcn::Graphics *graphics) = 0;
+
+ /**
+ * Invoked when a widget changes its size. This is used to determine
+ * the new height of the container.
+ */
+ virtual void widgetResized(const gcn::Event &event);
+
+ /**
+ * Handles mouse when dragged.
+ */
+ virtual void mouseDragged(gcn::MouseEvent &event) = 0;
+
+ /**
+ * Handles mouse when pressed.
+ */
+ virtual void mousePressed(gcn::MouseEvent &event) = 0;
+
+ /**
+ * Handles mouse release.
+ */
+ virtual void mouseReleased(gcn::MouseEvent &event) = 0;
+
+ virtual int getMaxItems()
+ { return mMaxItems; }
+
+ virtual int getBoxWidth()
+ { return mBoxWidth; }
+
+ virtual int getBoxHeight()
+ { return mBoxHeight; }
+
+ protected:
+ /**
+ * Gets the index from the grid provided the point is in an item box.
+ *
+ * @param pointX X coordinate of the point.
+ * @param pointY Y coordinate of the point.
+ * @return index on success, -1 on failure.
+ */
+ int getIndexFromGrid(int pointX, int pointY) const;
+
+ Image *mBackgroundImg;
+
+ static float mAlpha;
+
+ int mMaxItems;
+ int mBoxWidth;
+ int mBoxHeight;
+ int mCursorPosX, mCursorPosY;
+ int mGridWidth, mGridHeight;
+};
+
+#endif
diff --git a/src/gui/itemshortcutwindow.cpp b/src/gui/shortcutwindow.cpp
index 6fe1a10b..b6987b3e 100644
--- a/src/gui/itemshortcutwindow.cpp
+++ b/src/gui/shortcutwindow.cpp
@@ -19,23 +19,27 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "itemshortcutwindow.h"
-
-#include "itemshortcutcontainer.h"
#include "scrollarea.h"
+#include "shortcutcontainer.h"
+#include "shortcutwindow.h"
+
+#include "../configuration.h"
static const int SCROLL_PADDING = 0;
-ItemShortcutWindow::ItemShortcutWindow()
+int ShortcutWindow::mInstances = 0;
+
+ShortcutWindow::ShortcutWindow(const char *title, ShortcutContainer *content)
{
- setWindowName("ItemShortcut");
+ setWindowName(title);
// no title presented, title bar is padding so window can be moved.
gcn::Window::setTitleBarHeight(gcn::Window::getPadding());
setShowTitle(false);
setResizable(true);
- setDefaultSize(758, 174, 42, 426);
- mItems = new ItemShortcutContainer;
+ mItems = content;
+
+ mInstances++;
const int border = SCROLL_PADDING * 2 + getPadding() * 2;
setMinWidth(mItems->getBoxWidth() + border);
@@ -43,6 +47,15 @@ ItemShortcutWindow::ItemShortcutWindow()
setMaxWidth(mItems->getBoxWidth() * mItems->getMaxItems() + border);
setMaxHeight(mItems->getBoxHeight() * mItems->getMaxItems() + border);
+ const int width = (int) config.getValue("screenwidth", 800);
+ const int height = (int) config.getValue("screenheight", 600);
+
+ setDefaultSize(width - (mInstances * mItems->getBoxWidth()) -
+ (mInstances * border), height - (mItems->getBoxHeight() *
+ mItems->getMaxItems()) - border, mItems->getBoxWidth() +
+ border, (mItems->getBoxHeight() * mItems->getMaxItems()) +
+ border);
+
mScrollArea = new ScrollArea(mItems);
mScrollArea->setPosition(SCROLL_PADDING, SCROLL_PADDING);
mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
@@ -53,13 +66,13 @@ ItemShortcutWindow::ItemShortcutWindow()
loadWindowState();
}
-ItemShortcutWindow::~ItemShortcutWindow()
+ShortcutWindow::~ShortcutWindow()
{
delete mItems;
delete mScrollArea;
}
-void ItemShortcutWindow::widgetResized(const gcn::Event &event)
+void ShortcutWindow::widgetResized(const gcn::Event &event)
{
Window::widgetResized(event);
diff --git a/src/gui/itemshortcutwindow.h b/src/gui/shortcutwindow.h
index baa34b13..64592328 100644
--- a/src/gui/itemshortcutwindow.h
+++ b/src/gui/shortcutwindow.h
@@ -19,31 +19,31 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef ITEMSHORTCUTWINDOW_H
-#define ITEMSHORTCUTWINDOW_H
+#ifndef SHORTCUTWINDOW_H
+#define SHORTCUTWINDOW_H
#include "window.h"
-class ItemShortcutContainer;
class ScrollArea;
+class ShortcutContainer;
/**
* A window around the ItemShortcutContainer.
*
* \ingroup Interface
*/
-class ItemShortcutWindow : public Window
+class ShortcutWindow : public Window
{
public:
/**
* Constructor.
*/
- ItemShortcutWindow();
+ ShortcutWindow(const char *title, ShortcutContainer *content);
/**
* Destructor.
*/
- ~ItemShortcutWindow();
+ ~ShortcutWindow();
/**
* Called whenever the widget changes size.
@@ -51,11 +51,15 @@ class ItemShortcutWindow : public Window
void widgetResized(const gcn::Event &event);
private:
- ItemShortcutContainer *mItems;
+ ShortcutWindow();
+ ShortcutContainer *mItems;
ScrollArea *mScrollArea;
+
+ static int mInstances;
};
-extern ItemShortcutWindow *itemShortcutWindow;
+extern ShortcutWindow *itemShortcutWindow;
+extern ShortcutWindow *emoteShortcutWindow;
#endif
diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp
index 4afd913d..03711a47 100644
--- a/src/gui/skill.cpp
+++ b/src/gui/skill.cpp
@@ -21,13 +21,15 @@
#include <guichan/widgets/label.hpp>
-#include "skill.h"
-
#include "button.h"
#include "listbox.h"
#include "scrollarea.h"
+#include "skill.h"
+#include "table.h"
#include "windowcontainer.h"
+#include "widgets/layout.h"
+
#include "../localplayer.h"
#include "../log.h"
@@ -36,13 +38,18 @@
#include "../utils/strprintf.h"
#include "../utils/xml.h"
-static const char *SKILLS_FILE = "skills.xml";
+static const char *SKILLS_FILE = _("skills.xml");
struct SkillInfo {
std::string name;
bool modifiable;
};
+static const SkillInfo fakeSkillInfo = {
+ _("Mystery Skill"),
+ false
+};
+
std::vector<SkillInfo> skill_db;
static void initSkillinfo();
@@ -58,14 +65,17 @@ public:
update();
}
- virtual int getRows() { return mEntriesNr; }
+ virtual int getRows(void)
+ {
+ return mEntriesNr;
+ }
virtual int getColumnWidth(int index)
{
- switch (index) {
- case 0: return 160;
- default: return 35;
- }
+ if (index == 0)
+ return 160;
+
+ return 35;
}
virtual int getRowHeight()
@@ -75,15 +85,11 @@ public:
virtual void update()
{
- static const SkillInfo fakeSkillInfo = {
- _("Mystery Skill"),
- false
- };
-
mEntriesNr = mDialog->getSkills().size();
resize();
- for (int i = 0; i < mEntriesNr; i++) {
+ for (int i = 0; i < mEntriesNr; i++)
+ {
SKILL *skill = mDialog->getSkills()[i];
SkillInfo const *info;
char tmp[128];
@@ -120,37 +126,35 @@ SkillDialog::SkillDialog():
{
initSkillinfo();
mTableModel = new SkillGuiTableModel(this);
- mTable.setModel(mTableModel);
- mTable.setLinewiseSelection(true);
-
- setWindowName("Skills");
+ mTable = new GuiTable(mTableModel);
+ mTable->setOpaque(false);
+ mTable->setLinewiseSelection(true);
+ mTable->setWrappingEnabled(true);
+ mTable->setActionEventId("skill");
+ mTable->addActionListener(this);
+
+ setWindowName(_("Skills"));
setCloseButton(true);
setDefaultSize(windowContainer->getWidth() - 260, 25, 255, 260);
-// mSkillListBox = new ListBox(this);
- ScrollArea *skillScrollArea = new ScrollArea(&mTable);
+ setMinHeight(50 + mTableModel->getHeight());
+ setMinWidth(200);
+
+ ScrollArea *skillScrollArea = new ScrollArea(mTable);
mPointsLabel = new gcn::Label(strprintf(_("Skill points: %d"), 0));
- mIncButton = new Button(_("Up"), "inc", this);
- mUseButton = new Button(_("Use"), "use", this);
+ mIncButton = new Button(_("Up"), _("inc"), this);
+ mUseButton = new Button(_("Use"), _("use"), this);
mUseButton->setEnabled(false);
-// mSkillListBox->setActionEventId("skill");
- mTable.setActionEventId("skill");
-
skillScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- skillScrollArea->setDimension(gcn::Rectangle(5, 5, 230, 180));
- mPointsLabel->setDimension(gcn::Rectangle(8, 190, 200, 16));
- mIncButton->setPosition(skillScrollArea->getX(), 210);
- mUseButton->setPosition(mIncButton->getX() + mIncButton->getWidth() + 5,
- 210);
- add(skillScrollArea);
- add(mPointsLabel);
- add(mIncButton);
- add(mUseButton);
+ place(0, 0, skillScrollArea, 5).setPadding(3);
+ place(0, 1, mPointsLabel, 2);
+ place(3, 2, mIncButton);
+ place(4, 2, mUseButton);
-// mSkillListBox->addActionListener(this);
- mTable.addActionListener(this);
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
setLocationRelativeTo(getParent());
loadWindowState();
@@ -158,6 +162,7 @@ SkillDialog::SkillDialog():
SkillDialog::~SkillDialog()
{
+ delete mTable;
}
void SkillDialog::action(const gcn::ActionEvent &event)
@@ -165,22 +170,25 @@ void SkillDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "inc")
{
// Increment skill
- int selectedSkill = mTable.getSelectedRow();//mSkillListBox->getSelected();
+ int selectedSkill = mTable->getSelectedRow();
if (selectedSkill >= 0)
- {
player_node->raiseSkill(mSkillList[selectedSkill]->id);
- }
}
- else if (event.getId() == "skill")
+ else if (event.getId() == "skill" && mTable->getSelectedRow() > -1)
{
- mIncButton->setEnabled(
- mTable.getSelectedRow() > -1 &&
- player_node->mSkillPoint > 0);
+ SKILL *skill = mSkillList[mTable->getSelectedRow()];
+ SkillInfo const *info;
+
+ if (skill->id >= 0 && (unsigned int) skill->id < skill_db.size())
+ info = &skill_db[skill->id];
+ else
+ info = &fakeSkillInfo;
+
+ mIncButton->setEnabled(player_node->mSkillPoint > 0 &&
+ info->modifiable);
}
else if (event.getId() == "close")
- {
setVisible(false);
- }
}
void SkillDialog::update()
@@ -188,9 +196,10 @@ void SkillDialog::update()
mPointsLabel->setCaption(strprintf(_("Skill points: %d"),
player_node->mSkillPoint));
- int selectedSkill = mTable.getSelectedRow();
+ int selectedSkill = mTable->getSelectedRow();
- if (selectedSkill >= 0) {
+ if (selectedSkill >= 0)
+ {
int skillId = mSkillList[selectedSkill]->id;
bool modifiable;
@@ -201,10 +210,12 @@ void SkillDialog::update()
mIncButton->setEnabled(modifiable
&& player_node->mSkillPoint > 0);
- } else
+ }
+ else
mIncButton->setEnabled(false);
mTableModel->update();
+ setMinHeight(50 + mTableModel->getHeight());
}
int SkillDialog::getNumberOfElements()
@@ -214,10 +225,10 @@ int SkillDialog::getNumberOfElements()
bool SkillDialog::hasSkill(int id)
{
- for (unsigned int i = 0; i < mSkillList.size(); i++) {
- if (mSkillList[i]->id == id) {
+ for (unsigned int i = 0; i < mSkillList.size(); i++)
+ {
+ if (mSkillList[i]->id == id)
return true;
- }
}
return false;
}
@@ -233,8 +244,10 @@ void SkillDialog::addSkill(int id, int lvl, int mp)
void SkillDialog::setSkill(int id, int lvl, int mp)
{
- for (unsigned int i = 0; i < mSkillList.size(); i++) {
- if (mSkillList[i]->id == id) {
+ for (unsigned int i = 0; i < mSkillList.size(); i++)
+ {
+ if (mSkillList[i]->id == id)
+ {
mSkillList[i]->lv = lvl;
mSkillList[i]->sp = mp;
}
@@ -271,7 +284,8 @@ static void initSkillinfo()
std::string name = XML::getProperty(node, "name", "");
bool modifiable = !atoi(XML::getProperty(node, "fixed", "0").c_str());
- if (index >= 0) {
+ if (index >= 0)
+ {
skill_db.resize(index + 1, emptySkillInfo);
skill_db[index].name = name;
skill_db[index].modifiable = modifiable;
diff --git a/src/gui/skill.h b/src/gui/skill.h
index 893a61e7..0600d106 100644
--- a/src/gui/skill.h
+++ b/src/gui/skill.h
@@ -24,19 +24,16 @@
#include <vector>
-#include <guichan/listmodel.hpp>
#include <guichan/actionlistener.hpp>
#include "window.h"
-#include "table.h"
-
-#include "../guichanfwd.h"
struct SKILL {
short id; /**< Index into "skill_db" array */
short lv, sp;
};
+class GuiTable;
class SkillGuiTableModel;
/**
@@ -71,7 +68,8 @@ class SkillDialog : public Window, public gcn::ActionListener
const std::vector<SKILL*>& getSkills() const { return mSkillList; }
private:
- GuiTable mTable;//gcn::ListBox *mSkillListBox;
+ GuiTable *mTable;
+ ScrollArea *skillScrollArea;
SkillGuiTableModel *mTableModel;
gcn::Label *mPointsLabel;
gcn::Button *mIncButton;
diff --git a/src/gui/slider.cpp b/src/gui/slider.cpp
index 37136012..9bfa840f 100644
--- a/src/gui/slider.cpp
+++ b/src/gui/slider.cpp
@@ -21,6 +21,7 @@
#include "slider.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
@@ -28,6 +29,7 @@
Image *Slider::hStart, *Slider::hMid, *Slider::hEnd, *Slider::hGrip;
Image *Slider::vStart, *Slider::vMid, *Slider::vEnd, *Slider::vGrip;
+float Slider::mAlpha = config.getValue("guialpha", 0.8);
int Slider::mInstances = 0;
Slider::Slider(double scaleEnd):
@@ -107,6 +109,20 @@ void Slider::draw(gcn::Graphics *graphics)
int x = 0;
int y = (h - hStart->getHeight()) / 2;
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ hStart->setAlpha(mAlpha);
+ hMid->setAlpha(mAlpha);
+ hEnd->setAlpha(mAlpha);
+ hGrip->setAlpha(mAlpha);
+
+ vStart->setAlpha(mAlpha);
+ vMid->setAlpha(mAlpha);
+ vEnd->setAlpha(mAlpha);
+ vGrip->setAlpha(mAlpha);
+ }
+
static_cast<Graphics*>(graphics)->drawImage(hStart, x, y);
w -= hStart->getWidth() + hEnd->getWidth();
diff --git a/src/gui/slider.h b/src/gui/slider.h
index 1fe668c5..56ea334a 100644
--- a/src/gui/slider.h
+++ b/src/gui/slider.h
@@ -26,7 +26,6 @@
class Image;
-
/**
* Slider widget. Same as the Guichan slider but with custom look.
*
@@ -67,6 +66,7 @@ class Slider : public gcn::Slider {
static Image *hStart, *hMid, *hEnd, *hGrip;
static Image *vStart, *vMid, *vEnd, *vGrip;
+ static float mAlpha;
static int mInstances;
};
diff --git a/src/gui/speechbubble.cpp b/src/gui/speechbubble.cpp
new file mode 100644
index 00000000..dd404a63
--- /dev/null
+++ b/src/gui/speechbubble.cpp
@@ -0,0 +1,95 @@
+/*
+ * Speech bubbles
+ * Copyright (C) 2008 The Legend of Mazzeroth Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <guichan/font.hpp>
+
+#include <guichan/widgets/label.hpp>
+
+#include "gui.h"
+#include "scrollarea.h"
+#include "speechbubble.h"
+#include "textbox.h"
+
+#include "../utils/gettext.h"
+
+SpeechBubble::SpeechBubble():
+ Window(_("Speech"), false, NULL, "graphics/gui/speechbubble.xml")
+{
+ setContentSize(140, 46);
+ setShowTitle(false);
+ setTitleBarHeight(0);
+
+ mCaption = new gcn::Label("");
+ mCaption->setFont(boldFont);
+ mCaption->setPosition(5, 3);
+
+ mSpeechBox = new TextBox();
+ mSpeechBox->setEditable(false);
+ mSpeechBox->setOpaque(false);
+
+ mSpeechArea = new ScrollArea(mSpeechBox);
+
+ mSpeechArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mSpeechArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mSpeechArea->setDimension(gcn::Rectangle(4, boldFont->getHeight() + 3,
+ 130, 28));
+ mSpeechArea->setOpaque(false);
+
+ add(mCaption);
+ add(mSpeechArea);
+
+ setLocationRelativeTo(getParent());
+}
+
+SpeechBubble::~SpeechBubble()
+{
+ delete mCaption;
+ delete mSpeechBox;
+ delete mSpeechArea;
+}
+
+void SpeechBubble::setCaption(const std::string &name, const gcn::Color &color)
+{
+ mCaption->setCaption(name);
+ mCaption->adjustSize();
+ mCaption->setForegroundColor(color);
+}
+
+void SpeechBubble::setText(std::string mText)
+{
+ int width = mCaption->getWidth() + 3;
+ mSpeechBox->setTextWrapped(mText, 130 > width ? 130 : width);
+
+ const int fontHeight = getFont()->getHeight();
+ const int numRows = mSpeechBox->getNumberOfRows() + 1;
+
+ if (width < mSpeechBox->getMinWidth())
+ width = mSpeechBox->getMinWidth();
+
+ setContentSize(width + fontHeight, (numRows * fontHeight) + 6);
+ mSpeechArea->setDimension(gcn::Rectangle(4, fontHeight + 3, width + 5,
+ (numRows * fontHeight)));
+}
+
+unsigned int SpeechBubble::getNumRows()
+{
+ return mSpeechBox->getNumberOfRows();
+}
diff --git a/src/gui/speechbubble.h b/src/gui/speechbubble.h
new file mode 100644
index 00000000..d2d81332
--- /dev/null
+++ b/src/gui/speechbubble.h
@@ -0,0 +1,48 @@
+/*
+ * Speech bubbles
+ * Copyright (C) 2008 The Legend of Mazzeroth Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SPEECHBUBBLE_H
+#define SPEECHBUBBLE_H
+
+#include "window.h"
+
+class ScrollArea;
+class TextBox;
+
+class SpeechBubble : public Window
+{
+ public:
+ SpeechBubble();
+ ~SpeechBubble();
+
+ void setCaption(const std::string &name,
+ const gcn::Color &color = 0x000000);
+ void setText(std::string mText);
+ void setLocation(int x, int y);
+ unsigned int getNumRows();
+
+ private:
+ gcn::Label *mCaption;
+ TextBox *mSpeechBox;
+ ScrollArea *mSpeechArea;
+};
+
+#endif
diff --git a/src/gui/status.cpp b/src/gui/status.cpp
index b95a1eb8..683a9a41 100644
--- a/src/gui/status.cpp
+++ b/src/gui/status.cpp
@@ -19,14 +19,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "status.h"
-
#include <guichan/widgets/label.hpp>
#include "button.h"
#include "progressbar.h"
+#include "status.h"
#include "windowcontainer.h"
+#include "widgets/layout.h"
+
#include "../localplayer.h"
#include "../utils/gettext.h"
@@ -37,87 +38,30 @@ StatusWindow::StatusWindow(LocalPlayer *player):
Window(player->getName()),
mPlayer(player)
{
- setWindowName("Status");
- setResizable(true);
+ setWindowName(_("Status"));
setCloseButton(true);
setDefaultSize((windowContainer->getWidth() - 365) / 2,
- (windowContainer->getHeight() - 255) / 2, 365, 275);
- loadWindowState();
+ (windowContainer->getHeight() - 255) / 2, 400, 345);
// ----------------------
// Status Part
// ----------------------
mLvlLabel = new gcn::Label(strprintf(_("Level: %d"), 0));
- mGpLabel = new gcn::Label(strprintf(_("Job: %d"), 0));
- mJobLvlLabel = new gcn::Label(strprintf(_("Money: %d GP"), 0));
+ mJobLvlLabel = new gcn::Label(strprintf(_("Job: %d"), 0));
+ mGpLabel = new gcn::Label(strprintf(_("Money: %d GP"), 0));
- mHpLabel = new gcn::Label("HP:");
+ mHpLabel = new gcn::Label(_("HP:"));
mHpBar = new ProgressBar(1.0f, 80, 15, 0, 171, 34);
- mHpValueLabel = new gcn::Label;
- mXpLabel = new gcn::Label("Exp:");
+ mXpLabel = new gcn::Label(_("Exp:"));
mXpBar = new ProgressBar(1.0f, 80, 15, 143, 192, 211);
- mXpValueLabel = new gcn::Label;
- mMpLabel = new gcn::Label("MP:");
+ mMpLabel = new gcn::Label(_("MP:"));
mMpBar = new ProgressBar(1.0f, 80, 15, 26, 102, 230);
- mMpValueLabel = new gcn::Label;
-
- mJobXpLabel = new gcn::Label("Job:");
- mJobXpBar = new ProgressBar(1.0f, 80, 15, 220, 135, 203);
- mJobValueLabel = new gcn::Label;
-
- int y = 3;
- int x = 5;
-
- mLvlLabel->setPosition(x, y);
- x += mLvlLabel->getWidth() + 40;
- mJobLvlLabel->setPosition(x, y);
- x += mJobLvlLabel->getWidth() + 40;
- mGpLabel->setPosition(x, y);
-
- y += mLvlLabel->getHeight() + 5; // Next Row
- x = 5;
-
- mHpLabel->setPosition(x, y);
- x += mHpLabel->getWidth() + 5;
- mHpBar->setPosition(x, y);
- x += mHpBar->getWidth() + 5;
- mHpValueLabel->setPosition(x, y);
-
- mXpLabel->setPosition(175, y);
- mXpBar->setPosition(205, y);
- mXpValueLabel->setPosition(290, y);
-
- y += mHpLabel->getHeight() + 5; // Next Row
- x = 5;
-
- mMpLabel->setPosition(x, y);
- x += mMpLabel->getWidth() + 5;
- mMpBar->setPosition(x, y);
- x += mMpBar->getWidth() + 5;
- mMpValueLabel->setPosition(x, y);
-
- mJobXpLabel->setPosition(175, y);
- mJobXpBar->setPosition(205, y);
- mJobValueLabel->setPosition(290, y);
-
- add(mLvlLabel);
- add(mJobLvlLabel);
- add(mGpLabel);
- add(mHpLabel);
- add(mHpValueLabel);
- add(mMpLabel);
- add(mMpValueLabel);
- add(mXpLabel);
- add(mXpValueLabel);
- add(mJobXpLabel);
- add(mJobValueLabel);
- add(mHpBar);
- add(mMpBar);
- add(mXpBar);
- add(mJobXpBar);
+
+ mJobLabel = new gcn::Label(_("Job:"));
+ mJobBar = new ProgressBar(1.0f, 80, 15, 220, 135, 203);
// ----------------------
// Stats Part
@@ -127,14 +71,18 @@ StatusWindow::StatusWindow(LocalPlayer *player):
gcn::Label *mStatsTitleLabel = new gcn::Label(_("Stats"));
gcn::Label *mStatsTotalLabel = new gcn::Label(_("Total"));
gcn::Label *mStatsCostLabel = new gcn::Label(_("Cost"));
+ mStatsTotalLabel->setAlignment(gcn::Graphics::CENTER);
// Derived Stats
mStatsAttackLabel = new gcn::Label(_("Attack:"));
mStatsDefenseLabel= new gcn::Label(_("Defense:"));
mStatsMagicAttackLabel = new gcn::Label(_("M.Attack:"));
mStatsMagicDefenseLabel = new gcn::Label(_("M.Defense:"));
+ // Gettext flag for next line: xgettext:no-c-format
mStatsAccuracyLabel = new gcn::Label(_("% Accuracy:"));
+ // Gettext flag for next line: xgettext:no-c-format
mStatsEvadeLabel = new gcn::Label(_("% Evade:"));
+ // Gettext flag for next line: xgettext:no-c-format
mStatsReflexLabel = new gcn::Label(_("% Reflex:"));
mStatsAttackPoints = new gcn::Label;
@@ -146,10 +94,13 @@ StatusWindow::StatusWindow(LocalPlayer *player):
mStatsReflexPoints = new gcn::Label;
// New labels
- for (int i = 0; i < 6; i++) {
- mStatsLabel[i] = new gcn::Label;
+ for (int i = 0; i < 6; i++)
+ {
+ mStatsLabel[i] = new gcn::Label("0");
+ mStatsLabel[i]->setAlignment(gcn::Graphics::CENTER);
mStatsDisplayLabel[i] = new gcn::Label;
mPointsLabel[i] = new gcn::Label("0");
+ mPointsLabel[i]->setAlignment(gcn::Graphics::CENTER);
}
mRemainingStatsPointsLabel = new gcn::Label;
@@ -161,68 +112,53 @@ StatusWindow::StatusWindow(LocalPlayer *player):
mStatsButton[4] = new Button("+", "DEX", this);
mStatsButton[5] = new Button("+", "LUK", this);
-
- // Set position
- mStatsTitleLabel->setPosition(mMpLabel->getX(), mMpLabel->getY() + 23 );
- mStatsTotalLabel->setPosition(110, mStatsTitleLabel->getY() + 15);
- int totalLabelY = mStatsTotalLabel->getY();
- mStatsCostLabel->setPosition(170, totalLabelY);
-
+ // Assemble
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
+
+ place(0, 0, mLvlLabel, 3);
+ place(5, 0, mJobLvlLabel, 3);
+ place(8, 0, mGpLabel, 3);
+ place(1, 1, mHpLabel).setPadding(3);
+ place(2, 1, mHpBar, 3);
+ place(6, 1, mXpLabel).setPadding(3);
+ place(7, 1, mXpBar, 3);
+ place(1, 2, mMpLabel).setPadding(3);
+ place(2, 2, mMpBar, 3);
+ place(6, 2, mJobLabel).setPadding(3);
+ place(7, 2, mJobBar, 3);
+ place.getCell().matchColWidth(0, 1);
+ place = getPlacer(0, 3);
+ place(0, 0, mStatsTitleLabel, 5);
+ place(5, 1, mStatsTotalLabel, 5);
+ place(12, 1, mStatsCostLabel, 5);
for (int i = 0; i < 6; i++)
{
- mStatsLabel[i]->setPosition(5, mStatsTotalLabel->getY() + (i * 23) + 15);
- mStatsDisplayLabel[i]->setPosition(115,
- totalLabelY + (i * 23) + 15);
- mStatsButton[i]->setPosition(145, totalLabelY + (i * 23) + 10);
- mPointsLabel[i]->setPosition(175, totalLabelY + (i * 23) + 15);
+ place(0, 2 + i, mStatsLabel[i], 7).setPadding(5);
+ place(7, 2 + i, mStatsDisplayLabel[i]).setPadding(5);
+ place(10, 2 + i, mStatsButton[i]);
+ place(12, 2 + i, mPointsLabel[i]).setPadding(5);
}
+ place(14, 2, mStatsAttackLabel, 7).setPadding(5);
+ place(14, 3, mStatsDefenseLabel, 7).setPadding(5);
+ place(14, 4, mStatsMagicAttackLabel, 7).setPadding(5);
+ place(14, 5, mStatsMagicDefenseLabel, 7).setPadding(5);
+ place(14, 6, mStatsAccuracyLabel, 7).setPadding(5);
+ place(14, 7, mStatsEvadeLabel, 7).setPadding(5);
+ place(14, 8, mStatsReflexLabel, 7).setPadding(5);
+ place(21, 2, mStatsAttackPoints, 3).setPadding(5);
+ place(21, 3, mStatsDefensePoints, 3).setPadding(5);
+ place(21, 4, mStatsMagicAttackPoints, 3).setPadding(5);
+ place(21, 5, mStatsMagicDefensePoints, 3).setPadding(5);
+ place(21, 6, mStatsAccuracyPoints, 3).setPadding(5);
+ place(21, 7, mStatsEvadePoints, 3).setPadding(5);
+ place(21, 8, mStatsReflexPoints, 3).setPadding(5);
+ place(0, 8, mRemainingStatsPointsLabel, 3).setPadding(5);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
- mRemainingStatsPointsLabel->setPosition(5, mPointsLabel[5]->getY() + 25);
-
- mStatsAttackLabel->setPosition(220, mStatsLabel[0]->getY());
- mStatsDefenseLabel->setPosition(220, mStatsLabel[1]->getY());
- mStatsMagicAttackLabel->setPosition(220, mStatsLabel[2]->getY());
- mStatsMagicDefenseLabel->setPosition(220, mStatsLabel[3]->getY());
- mStatsAccuracyLabel->setPosition(220, mStatsLabel[4]->getY());
- mStatsEvadeLabel->setPosition(220, mStatsLabel[5]->getY());
- mStatsReflexLabel->setPosition(220, mRemainingStatsPointsLabel->getY());
-
- mStatsAttackPoints->setPosition(310, mStatsLabel[0]->getY());
- mStatsDefensePoints->setPosition(310, mStatsLabel[1]->getY());
- mStatsMagicAttackPoints->setPosition(310, mStatsLabel[2]->getY());
- mStatsMagicDefensePoints->setPosition(310, mStatsLabel[3]->getY());
- mStatsAccuracyPoints->setPosition(310, mStatsLabel[4]->getY());
- mStatsEvadePoints->setPosition(310, mStatsLabel[5]->getY());
- mStatsReflexPoints->setPosition(310, mRemainingStatsPointsLabel->getY());
-
- // Assemble
- add(mStatsTitleLabel);
- add(mStatsTotalLabel);
- add(mStatsCostLabel);
- for(int i = 0; i < 6; i++)
- {
- add(mStatsLabel[i]);
- add(mStatsDisplayLabel[i]);
- add(mStatsButton[i]);
- add(mPointsLabel[i]);
- }
- add(mStatsAttackLabel);
- add(mStatsDefenseLabel);
- add(mStatsMagicAttackLabel);
- add(mStatsMagicDefenseLabel);
- add(mStatsAccuracyLabel);
- add(mStatsEvadeLabel);
- add(mStatsReflexLabel);
-
- add(mStatsAttackPoints);
- add(mStatsDefensePoints);
- add(mStatsMagicAttackPoints);
- add(mStatsMagicDefensePoints);
- add(mStatsAccuracyPoints);
- add(mStatsEvadePoints);
- add(mStatsReflexPoints);
-
- add(mRemainingStatsPointsLabel);
+ loadWindowState();
}
void StatusWindow::update()
@@ -238,21 +174,17 @@ void StatusWindow::update()
mGpLabel->setCaption(strprintf(_("Money: %d GP"), mPlayer->mGp));
mGpLabel->adjustSize();
- mHpValueLabel->setCaption(toString(mPlayer->mHp) +
- "/" + toString(mPlayer->mMaxHp));
- mHpValueLabel->adjustSize();
+ mHpBar->setText(toString(mPlayer->mHp) +
+ "/" + toString(mPlayer->mMaxHp));
- mMpValueLabel->setCaption(toString(mPlayer->mMp) +
- "/" + toString(mPlayer->mMaxMp));
- mMpValueLabel->adjustSize();
+ mMpBar->setText(toString(mPlayer->mMp) +
+ "/" + toString(mPlayer->mMaxMp));
- mXpValueLabel->setCaption(toString(mPlayer->getXp()) +
- "/" + toString(mPlayer->mXpForNextLevel));
- mXpValueLabel->adjustSize();
+ mXpBar->setText(toString(mPlayer->getXp()) +
+ "/" + toString(mPlayer->mXpForNextLevel));
- mJobValueLabel->setCaption(toString(mPlayer->mJobXp) +
- "/" + toString(mPlayer->mJobXpForNextLevel));
- mJobValueLabel->adjustSize();
+ mJobBar->setText(toString(mPlayer->mJobXp) +
+ "/" + toString(mPlayer->mJobXpForNextLevel));
// HP Bar coloration
if (mPlayer->mHp < int(mPlayer->mMaxHp / 3))
@@ -273,7 +205,7 @@ void StatusWindow::update()
mXpBar->setProgress(
(float) mPlayer->getXp() / (float) mPlayer->mXpForNextLevel);
- mJobXpBar->setProgress(
+ mJobBar->setProgress(
(float) mPlayer->mJobXp / (float) mPlayer->mJobXpForNextLevel);
// Stats Part
@@ -338,30 +270,6 @@ void StatusWindow::update()
// Reflex %
mStatsReflexPoints->setCaption(toString(mPlayer->DEX / 4)); // + counter
mStatsReflexPoints->adjustSize();
-
- // Update Second column widgets position
- mJobLvlLabel->setPosition(mLvlLabel->getX() + mLvlLabel->getWidth() + 20,
- mLvlLabel->getY());
- mGpLabel->setPosition(mJobLvlLabel->getX() + mJobLvlLabel->getWidth() + 20,
- mJobLvlLabel->getY());
-
- mXpLabel->setPosition(
- mHpValueLabel->getX() + mHpValueLabel->getWidth() + 10,
- mHpLabel->getY());
- mXpBar->setPosition(
- mXpLabel->getX() + mXpLabel->getWidth() + 5,
- mXpLabel->getY());
- mXpValueLabel->setPosition(
- mXpBar->getX() + mXpBar->getWidth() + 5,
- mXpLabel->getY());
-
- mJobXpLabel->setPosition(mXpBar->getX() - mJobXpLabel->getWidth() - 5,
- mMpLabel->getY());
- mJobXpBar->setPosition(
- mJobXpLabel->getX() + mJobXpLabel->getWidth() + 5,
- mJobXpLabel->getY());
- mJobValueLabel->setPosition(mJobXpBar->getX() + mJobXpBar->getWidth() + 5,
- mJobXpLabel->getY());
}
void StatusWindow::draw(gcn::Graphics *g)
@@ -402,3 +310,4 @@ void StatusWindow::action(const gcn::ActionEvent &event)
}
}
}
+
diff --git a/src/gui/status.h b/src/gui/status.h
index 6d360caf..00a48f4e 100644
--- a/src/gui/status.h
+++ b/src/gui/status.h
@@ -22,18 +22,13 @@
#ifndef STATUS_H
#define STATUS_H
-#include <iosfwd>
-
#include <guichan/actionlistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
-
class LocalPlayer;
class ProgressBar;
-
/**
* The player status dialog.
*
@@ -70,11 +65,9 @@ class StatusWindow : public Window, public gcn::ActionListener
*/
gcn::Label *mLvlLabel, *mJobLvlLabel;
gcn::Label *mGpLabel;
- gcn::Label *mHpLabel, *mHpValueLabel;
- gcn::Label *mMpLabel, *mMpValueLabel;
- gcn::Label *mXpLabel, *mXpValueLabel, *mJobXpLabel, *mJobValueLabel;
+ gcn::Label *mHpLabel, *mMpLabel, *mXpLabel, *mJobLabel;
ProgressBar *mHpBar, *mMpBar;
- ProgressBar *mXpBar, *mJobXpBar;
+ ProgressBar *mXpBar, *mJobBar;
/**
* Derived Statistics captions
diff --git a/src/gui/table.cpp b/src/gui/table.cpp
index f6678737..8dd546d9 100644
--- a/src/gui/table.cpp
+++ b/src/gui/table.cpp
@@ -19,13 +19,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <guichan/actionlistener.hpp>
+#include <guichan/graphics.hpp>
+#include <guichan/key.hpp>
+
+#include "color.h"
#include "table.h"
-#include <guichan/graphics.hpp>
-#include <guichan/actionlistener.hpp>
+#include "../configuration.h"
-#include <cassert>
+#include "../utils/dtor.h"
+float GuiTable::mAlpha = config.getValue("guialpha", 0.8);
class GuiTableActionListener : public gcn::ActionListener
{
@@ -50,7 +55,8 @@ GuiTableActionListener::GuiTableActionListener(GuiTable *table, gcn::Widget *wid
mColumn(column),
mWidget(widget)
{
- if (widget) {
+ if (widget)
+ {
widget->addActionListener(this);
widget->_setParent(table);
}
@@ -58,7 +64,8 @@ GuiTableActionListener::GuiTableActionListener(GuiTable *table, gcn::Widget *wid
GuiTableActionListener::~GuiTableActionListener()
{
- if (mWidget) {
+ if (mWidget)
+ {
mWidget->removeActionListener(this);
mWidget->_setParent(NULL);
}
@@ -71,14 +78,20 @@ void GuiTableActionListener::action(const gcn::ActionEvent& actionEvent)
}
-GuiTable::GuiTable(TableModel *initial_model) :
+GuiTable::GuiTable(TableModel *initial_model, gcn::Color background,
+ bool opacity) :
mLinewiseMode(false),
+ mWrappingEnabled(false),
+ mOpaque(opacity),
+ mBackgroundColor(background),
mModel(NULL),
mSelectedRow(0),
mSelectedColumn(0),
mTopWidget(NULL)
{
setModel(initial_model);
+ setFocusable(true);
+
addMouseListener(this);
addKeyListener(this);
}
@@ -95,7 +108,8 @@ TableModel *GuiTable::getModel() const
void GuiTable::setModel(TableModel *new_model)
{
- if (mModel) {
+ if (mModel)
+ {
uninstallActionListeners();
mModel->removeListener(this);
}
@@ -103,13 +117,13 @@ void GuiTable::setModel(TableModel *new_model)
mModel = new_model;
installActionListeners();
- if (new_model) {
+ if (new_model)
+ {
new_model->installListener(this);
recomputeDimensions();
}
}
-
void GuiTable::recomputeDimensions()
{
int rows_nr = mModel->getRows();
@@ -169,10 +183,62 @@ int GuiTable::getColumnWidth(int i)
return 0;
}
-void GuiTable::uninstallActionListeners()
+void GuiTable::setSelectedRow(int selected)
{
- for (std::vector<GuiTableActionListener *>::const_iterator it = action_listeners.begin(); it != action_listeners.end(); it++)
- delete *it;
+ if (!mModel)
+ {
+ mSelectedRow = -1;
+ }
+ else
+ {
+ if (selected < 0 && !mWrappingEnabled)
+ {
+ mSelectedRow = -1;
+ }
+ else if (selected >= mModel->getRows() && mWrappingEnabled)
+ {
+ mSelectedRow = 0;
+ }
+ else if ((selected >= mModel->getRows() && !mWrappingEnabled) ||
+ (selected < 0 && mWrappingEnabled))
+ {
+ mSelectedRow = mModel->getRows() - 1;
+ }
+ else
+ {
+ mSelectedRow = selected;
+ }
+ }
+}
+
+void GuiTable::setSelectedColumn(int selected)
+{
+ if (!mModel)
+ {
+ mSelectedColumn = -1;
+ }
+ else
+ {
+ if ((selected >= mModel->getColumns() && mWrappingEnabled) ||
+ (selected < 0 && !mWrappingEnabled))
+ {
+ mSelectedColumn = 0;
+ }
+ else if ((selected >= mModel->getColumns() && !mWrappingEnabled) ||
+ (selected < 0 && mWrappingEnabled))
+ {
+ mSelectedColumn = mModel->getColumns() - 1;
+ }
+ else
+ {
+ mSelectedColumn = selected;
+ }
+ }
+}
+
+void GuiTable::uninstallActionListeners(void)
+{
+ delete_all(action_listeners);
action_listeners.clear();
}
@@ -185,10 +251,11 @@ void GuiTable::installActionListeners()
int columns = mModel->getColumns();
for (int row = 0; row < rows; ++row)
- for (int column = 0; column < columns; ++column) {
+ for (int column = 0; column < columns; ++column)
+ {
gcn::Widget *widget = mModel->getElementAt(row, column);
action_listeners.push_back(new GuiTableActionListener(this, widget,
- row, column));
+ row, column));
}
_setFocusHandler(_getFocusHandler()); // propagate focus handler to widgets
@@ -197,12 +264,22 @@ void GuiTable::installActionListeners()
// -- widget ops
void GuiTable::draw(gcn::Graphics* graphics)
{
- graphics->setColor(getBackgroundColor());
- graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
-
if (!mModel)
return;
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ mAlpha = config.getValue("guialpha", 0.8);
+
+ if (mOpaque)
+ {
+ const int red = getBackgroundColor().r;
+ const int green = getBackgroundColor().g;
+ const int blue = getBackgroundColor().b;
+ const int alpha = mAlpha * 255;
+ graphics->setColor(gcn::Color(red, green, blue, alpha));
+ graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
+ }
+
// First, determine how many rows we need to draw, and where we should start.
int first_row = -(getY() / getRowHeight());
@@ -224,44 +301,68 @@ void GuiTable::draw(gcn::Graphics* graphics)
int height = getRowHeight();
int y_offset = first_row * height;
- for (int r = first_row; r < first_row + rows_nr; ++r) {
+ for (int r = first_row; r < first_row + rows_nr; ++r)
+ {
int x_offset = 0;
- for (int c = first_column; c <= last_column; ++c) {
+ for (int c = first_column; c <= last_column; ++c)
+ {
gcn::Widget *widget = mModel->getElementAt(r, c);
int width = getColumnWidth(c);
- if (widget) {
+ if (widget)
+ {
gcn::Rectangle bounds(x_offset, y_offset, width, height);
- if (widget == mTopWidget) {
+ if (widget == mTopWidget)
+ {
bounds.height = widget->getHeight();
bounds.width = widget->getWidth();
}
widget->setDimension(bounds);
+ if (!mLinewiseMode && c == mSelectedColumn && r == mSelectedRow)
+ {
+ bool valid;
+ const int red =
+ (textColor->getColor('H', valid) >> 16) & 0xFF;
+ const int green =
+ (textColor->getColor('H', valid) >> 8) & 0xFF;
+ const int blue = textColor->getColor('H', valid) & 0xFF;
+ const int alpha = mAlpha * 127;
+
+ graphics->setColor(gcn::Color(red, green, blue, alpha));
+ graphics->fillRectangle(bounds);
+ }
+
graphics->pushClipArea(bounds);
widget->draw(graphics);
graphics->popClipArea();
-
- if (!mLinewiseMode
- && c == mSelectedColumn
- && r == mSelectedRow)
- graphics->drawRectangle(bounds);
}
x_offset += width;
}
- if (mLinewiseMode
- && r == mSelectedRow)
- graphics->drawRectangle(gcn::Rectangle(0, y_offset,
+ if (mLinewiseMode && r == mSelectedRow)
+ {
+ bool valid;
+ const int red =
+ (textColor->getColor('H', valid) >> 16) & 0xFF;
+ const int green =
+ (textColor->getColor('H', valid) >> 8) & 0xFF;
+ const int blue = textColor->getColor('H', valid) & 0xFF;
+ const int alpha = mAlpha * 127;
+
+ graphics->setColor(gcn::Color(red, green, blue, alpha));
+ graphics->fillRectangle(gcn::Rectangle(0, y_offset,
x_offset, height));
+ }
y_offset += height;
}
- if (mTopWidget) {
+ if (mTopWidget)
+ {
gcn::Rectangle bounds = mTopWidget->getDimension();
graphics->pushClipArea(bounds);
mTopWidget->draw(graphics);
@@ -269,21 +370,17 @@ void GuiTable::draw(gcn::Graphics* graphics)
}
}
-void GuiTable::logic()
-{
-}
-
void GuiTable::moveToTop(gcn::Widget *widget)
{
gcn::Widget::moveToTop(widget);
- this->mTopWidget = widget;
+ mTopWidget = widget;
}
void GuiTable::moveToBottom(gcn::Widget *widget)
{
gcn::Widget::moveToBottom(widget);
- if (widget == this->mTopWidget)
- this->mTopWidget = NULL;
+ if (widget == mTopWidget)
+ mTopWidget = NULL;
}
gcn::Rectangle GuiTable::getChildrenArea()
@@ -294,17 +391,62 @@ gcn::Rectangle GuiTable::getChildrenArea()
// -- KeyListener notifications
void GuiTable::keyPressed(gcn::KeyEvent& keyEvent)
{
-}
+ gcn::Key key = keyEvent.getKey();
+
+ if (key.getValue() == gcn::Key::ENTER || key.getValue() == gcn::Key::SPACE)
+ {
+ distributeActionEvent();
+ keyEvent.consume();
+ }
+ else if (key.getValue() == gcn::Key::UP)
+ {
+ setSelectedRow(mSelectedRow - 1);
+ keyEvent.consume();
+ }
+ else if (key.getValue() == gcn::Key::DOWN)
+ {
+ setSelectedRow(mSelectedRow + 1);
+
+ keyEvent.consume();
+ }
+ else if (key.getValue() == gcn::Key::LEFT)
+ {
+ setSelectedColumn(mSelectedColumn - 1);
+
+ keyEvent.consume();
+ }
+ else if (key.getValue() == gcn::Key::RIGHT)
+ {
+ setSelectedColumn(mSelectedColumn + 1);
+
+ keyEvent.consume();
+ }
+ else if (key.getValue() == gcn::Key::HOME)
+ {
+ setSelectedRow(0);
+ setSelectedColumn(0);
+ keyEvent.consume();
+ }
+ else if (key.getValue() == gcn::Key::END)
+ {
+ setSelectedRow(mModel->getRows() - 1);
+ setSelectedColumn(mModel->getColumns() - 1);
+ keyEvent.consume();
+ }
+}
// -- MouseListener notifications
void GuiTable::mousePressed(gcn::MouseEvent& mouseEvent)
{
- if (mouseEvent.getButton() == gcn::MouseEvent::LEFT) {
+ if (mouseEvent.getButton() == gcn::MouseEvent::LEFT)
+ {
int row = getRowForY(mouseEvent.getY());
int column = getColumnForX(mouseEvent.getX());
- if (row > -1 && column > -1) {
+ if (row > -1 && column > -1 &&
+ row < mModel->getRows() && column < mModel->getColumns())
+ {
mSelectedColumn = column;
mSelectedRow = row;
}
@@ -315,10 +457,25 @@ void GuiTable::mousePressed(gcn::MouseEvent& mouseEvent)
void GuiTable::mouseWheelMovedUp(gcn::MouseEvent& mouseEvent)
{
+ if (isFocused())
+ {
+ if (getSelectedRow() >= 0 )
+ {
+ setSelectedRow(getSelectedRow() - 1);
+ }
+
+ mouseEvent.consume();
+ }
}
void GuiTable::mouseWheelMovedDown(gcn::MouseEvent& mouseEvent)
{
+ if (isFocused())
+ {
+ setSelectedRow(getSelectedRow() + 1);
+
+ mouseEvent.consume();
+ }
}
void GuiTable::mouseDragged(gcn::MouseEvent& mouseEvent)
@@ -328,10 +485,13 @@ void GuiTable::mouseDragged(gcn::MouseEvent& mouseEvent)
// -- TableModelListener notifications
void GuiTable::modelUpdated(bool completed)
{
- if (completed) {
+ if (completed)
+ {
recomputeDimensions();
installActionListeners();
- } else { // before the update?
+ }
+ else
+ { // before the update?
mTopWidget = NULL; // No longer valid in general
uninstallActionListeners();
}
@@ -342,18 +502,18 @@ gcn::Widget *GuiTable::getWidgetAt(int x, int y)
int row = getRowForY(y);
int column = getColumnForX(x);
- if (mTopWidget
- && mTopWidget->getDimension().isPointInRect(x, y))
+ if (mTopWidget && mTopWidget->getDimension().isPointInRect(x, y))
return mTopWidget;
- if (row > -1
- && column > -1) {
+ if (row > -1 && column > -1)
+ {
gcn::Widget *w = mModel->getElementAt(row, column);
if (w && w->isFocusable())
return w;
else
return NULL; // Grab the event locally
- } else
+ }
+ else
return NULL;
}
@@ -361,8 +521,7 @@ int GuiTable::getRowForY(int y)
{
int row = y / getRowHeight();
- if (row < 0
- || row >= mModel->getRows())
+ if (row < 0 || row >= mModel->getRows())
return -1;
else
return row;
@@ -373,20 +532,19 @@ int GuiTable::getColumnForX(int x)
int column;
int delta = 0;
- for (column = 0; column < mModel->getColumns(); column++) {
+ for (column = 0; column < mModel->getColumns(); column++)
+ {
delta += getColumnWidth(column);
if (x <= delta)
break;
}
- if (column < 0
- || column >= mModel->getColumns())
+ if (column < 0 || column >= mModel->getColumns())
return -1;
else
return column;
}
-
void GuiTable::_setFocusHandler(gcn::FocusHandler* focusHandler)
{
gcn::Widget::_setFocusHandler(focusHandler);
diff --git a/src/gui/table.h b/src/gui/table.h
index c7ede36c..841f6ef2 100644
--- a/src/gui/table.h
+++ b/src/gui/table.h
@@ -24,14 +24,11 @@
#include <vector>
-#include <guichan/gui.hpp>
#include <guichan/keylistener.hpp>
#include <guichan/mouselistener.hpp>
-#include <guichan/platform.hpp>
#include <guichan/widget.hpp>
#include "table_model.h"
-#include "../guichanfwd.h"
class GuiTableActionListener;
@@ -53,7 +50,8 @@ class GuiTable : public gcn::Widget,
friend class GuiTableActionListener;
public:
- GuiTable(TableModel * initial_model = NULL);
+ GuiTable(TableModel * initial_model = NULL, gcn::Color background = 0xffffff,
+ bool opacity = true);
virtual ~GuiTable();
@@ -67,25 +65,36 @@ public:
*
* Note that actions issued by widgets returned from the model will update
* the table selection, but only AFTER any event handlers installed within
- * the widget have been triggered. To be notified after such an update,
- * add an action listener to the table instead.
+ * the widget have been triggered. To be notified after such an update, add
+ * an action listener to the table instead.
*/
void setModel(TableModel *m);
+ const TableModel* getModel() {return mModel;}
+
void setSelected(int row, int column);
int getSelectedRow();
int getSelectedColumn();
- gcn::Rectangle getChildrenArea();
+ void setSelectedRow(int selected);
+
+ void setSelectedColumn(int selected);
+
+ bool isWrappingEnabled() const {return mWrappingEnabled;}
+
+ void setWrappingEnabled(bool wrappingEnabled)
+ {mWrappingEnabled = wrappingEnabled;}
+
+ gcn::Rectangle getChildrenArea(void);
/**
- * Toggle whether to use linewise selection mode, in which the table
- * selects an entire line at a time, rather than a single cell.
+ * Toggle whether to use linewise selection mode, in which the table selects
+ * an entire line at a time, rather than a single cell.
*
- * Note that column information is tracked even in linewise selection
- * mode; this mode therefore only affects visualisation.
+ * Note that column information is tracked even in linewise selection mode;
+ * this mode therefore only affects visualisation.
*
* Disabled by default.
*
@@ -96,8 +105,6 @@ public:
// Inherited from Widget
virtual void draw(gcn::Graphics* graphics);
- virtual void logic();
-
virtual gcn::Widget *getWidgetAt(int x, int y);
virtual void moveToTop(gcn::Widget *child);
@@ -109,6 +116,21 @@ public:
// Inherited from KeyListener
virtual void keyPressed(gcn::KeyEvent& keyEvent);
+ /**
+ * Sets the table to be opaque, that is sets the table
+ * to display its background.
+ *
+ * @param opaque True if the table should be opaque, false otherwise.
+ */
+ virtual void setOpaque(bool opaque) {mOpaque = opaque;}
+
+ /**
+ * Checks if the table is opaque, that is if the table area displays its
+ * background.
+ *
+ * @return True if the table is opaque, false otherwise.
+ */
+ virtual bool isOpaque() const {return mOpaque;}
// Inherited from MouseListener
virtual void mousePressed(gcn::MouseEvent& mouseEvent);
@@ -136,6 +158,15 @@ private:
int getColumnForX(int x); // -1 on error
void recomputeDimensions();
bool mLinewiseMode;
+ bool mWrappingEnabled;
+ bool mOpaque;
+
+ static float mAlpha;
+
+ /**
+ * Holds the background color of the table.
+ */
+ gcn::Color mBackgroundColor;
TableModel *mModel;
diff --git a/src/gui/table_model.cpp b/src/gui/table_model.cpp
index 7bc29b47..4fa13bae 100644
--- a/src/gui/table_model.cpp
+++ b/src/gui/table_model.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "table_model.h"
-
#include <guichan/widget.hpp>
-#include <cstdlib>
+
+#include "table_model.h"
#include "../utils/dtor.h"
@@ -49,7 +48,6 @@ void TableModel::signalAfterUpdate()
}
-
#define WIDGET_AT(row, column) (((row) * mColumns) + (column))
#define DYN_SIZE(h) ((h) >= 0) // determines whether this size is tagged for auto-detection
@@ -143,3 +141,21 @@ int StaticTableModel::getColumns()
{
return mColumns;
}
+
+int StaticTableModel::getWidth(void)
+{
+ int width = 0;
+
+ for (unsigned int i = 0; i < mWidths.size(); i++)
+ {
+ width += mWidths[i];
+ }
+
+ return width;
+}
+
+int StaticTableModel::getHeight(void)
+{
+ return (mColumns * mHeight);
+}
+
diff --git a/src/gui/table_model.h b/src/gui/table_model.h
index d245d7bd..9ca36120 100644
--- a/src/gui/table_model.h
+++ b/src/gui/table_model.h
@@ -22,10 +22,6 @@
#ifndef TABLE_MODEL_H
#define TABLE_MODEL_H
-#include "../guichanfwd.h"
-
-#include <guichan/gui.hpp>
-
#include <set>
#include <vector>
@@ -133,6 +129,8 @@ public:
virtual int getRows();
virtual int getColumns();
virtual int getRowHeight();
+ virtual int getWidth();
+ virtual int getHeight();
virtual int getColumnWidth(int index);
virtual gcn::Widget *getElementAt(int row, int column);
diff --git a/src/gui/textbox.cpp b/src/gui/textbox.cpp
index 75f0b5a1..2a86d549 100644
--- a/src/gui/textbox.cpp
+++ b/src/gui/textbox.cpp
@@ -19,21 +19,21 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "textbox.h"
-
#include <sstream>
-#include <guichan/basiccontainer.hpp>
#include <guichan/font.hpp>
+#include "textbox.h"
+
TextBox::TextBox():
gcn::TextBox()
{
setOpaque(false);
setFrameSize(0);
+ mMinWidth = getWidth();
}
-void TextBox::setTextWrapped(const std::string &text)
+void TextBox::setTextWrapped(const std::string &text, int minDimension)
{
// Make sure parent scroll area sets width of this widget
if (getParent())
@@ -41,8 +41,13 @@ void TextBox::setTextWrapped(const std::string &text)
getParent()->logic();
}
+ // Take the supplied minimum dimension as a starting point and try to beat it
+ mMinWidth = minDimension;
+
std::stringstream wrappedStream;
std::string::size_type newlinePos, lastNewlinePos = 0;
+ int minWidth = 0;
+ int xpos;
do
{
@@ -57,7 +62,18 @@ void TextBox::setTextWrapped(const std::string &text)
std::string line =
text.substr(lastNewlinePos, newlinePos - lastNewlinePos);
std::string::size_type spacePos, lastSpacePos = 0;
- int xpos = 0;
+ xpos = 0;
+
+ spacePos = text.rfind(" ", text.size());
+
+ if (spacePos != std::string::npos)
+ {
+ const std::string word = text.substr(spacePos + 1);
+ const int length = getFont()->getWidth(word);
+
+ if (length > mMinWidth)
+ mMinWidth = length;
+ }
do
{
@@ -73,7 +89,7 @@ void TextBox::setTextWrapped(const std::string &text)
int width = getFont()->getWidth(word);
- if (xpos != 0 && xpos + width < getWidth())
+ if (xpos != 0 && xpos + width + getFont()->getWidth(" ") <= mMinWidth)
{
xpos += width + getFont()->getWidth(" ");
wrappedStream << " " << word;
@@ -85,22 +101,46 @@ void TextBox::setTextWrapped(const std::string &text)
}
else
{
+ if (xpos > minWidth)
+ minWidth = xpos;
+
+ // The window wasn't big enough. Resize it and try again.
+ if (minWidth > mMinWidth)
+ {
+ mMinWidth = minWidth;
+ wrappedStream.clear();
+ wrappedStream.str("");
+ spacePos = 0;
+ lastNewlinePos = 0;
+ newlinePos = text.find("\n", lastNewlinePos);
+ if (newlinePos == std::string::npos)
+ newlinePos = text.size();
+ line = text.substr(lastNewlinePos, newlinePos -
+ lastNewlinePos);
+ width = 0;
+ break;
+ }
+ else
+ {
+ wrappedStream << "\n" << word;
+ }
xpos = width;
- wrappedStream << "\n" << word;
}
-
lastSpacePos = spacePos + 1;
}
while (spacePos != line.size());
if (text.find("\n", lastNewlinePos) != std::string::npos)
- {
wrappedStream << "\n";
- }
lastNewlinePos = newlinePos + 1;
}
while (newlinePos != text.size());
+ if (xpos > minWidth)
+ minWidth = xpos;
+
+ mMinWidth = minWidth;
+
gcn::TextBox::setText(wrappedStream.str());
}
diff --git a/src/gui/textbox.h b/src/gui/textbox.h
index a42562ea..10a81fc0 100644
--- a/src/gui/textbox.h
+++ b/src/gui/textbox.h
@@ -31,7 +31,8 @@
*
* \ingroup GUI
*/
-class TextBox : public gcn::TextBox {
+class TextBox : public gcn::TextBox
+{
public:
/**
* Constructor.
@@ -41,7 +42,15 @@ class TextBox : public gcn::TextBox {
/**
* Sets the text after wrapping it to the current width of the widget.
*/
- void setTextWrapped(const std::string &text);
+ void setTextWrapped(const std::string &text, int minDimension);
+
+ /**
+ * Get the minimum text width for the text box.
+ */
+ int getMinWidth() { return mMinWidth; }
+
+ private:
+ int mMinWidth;
};
#endif
diff --git a/src/gui/textfield.cpp b/src/gui/textfield.cpp
index f7b02cbf..99a95a2e 100644
--- a/src/gui/textfield.cpp
+++ b/src/gui/textfield.cpp
@@ -19,14 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "textfield.h"
-
-#include <algorithm>
-
#include <guichan/font.hpp>
#include "sdlinput.h"
+#include "textfield.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
@@ -37,10 +35,13 @@
#undef DELETE //Win32 compatibility hack
int TextField::instances = 0;
+float TextField::mAlpha = config.getValue("guialpha", 0.8);
ImageRect TextField::skin;
TextField::TextField(const std::string& text):
- gcn::TextField(text)
+ gcn::TextField(text),
+ mNumeric(false),
+ mListener(0)
{
setFrameSize(2);
@@ -51,9 +52,6 @@ TextField::TextField(const std::string& text):
Image *textbox = resman->getImage("graphics/gui/deepbox.png");
int gridx[4] = {0, 3, 28, 31};
int gridy[4] = {0, 3, 28, 31};
- //Image *textbox = resman->getImage("graphics/gui/textbox.png");
- //int gridx[4] = {0, 5, 26, 31};
- //int gridy[4] = {0, 5, 26, 31};
int a = 0, x, y;
for (y = 0; y < 3; y++) {
@@ -62,6 +60,7 @@ TextField::TextField(const std::string& text):
gridx[x], gridy[y],
gridx[x + 1] - gridx[x] + 1,
gridy[y + 1] - gridy[y] + 1);
+ skin.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
a++;
}
}
@@ -93,6 +92,15 @@ void TextField::draw(gcn::Graphics *graphics)
graphics->setColor(getForegroundColor());
graphics->setFont(getFont());
graphics->drawText(mText, 1 - mXScroll, 1);
+
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ for (int a = 0; a < 9; a++)
+ {
+ skin.grid[a]->setAlpha(mAlpha);
+ }
+ }
}
void TextField::drawFrame(gcn::Graphics *graphics)
@@ -105,6 +113,42 @@ void TextField::drawFrame(gcn::Graphics *graphics)
static_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, skin);
}
+void TextField::setNumeric(bool numeric)
+{
+ mNumeric = numeric;
+ if (!numeric)
+ {
+ return;
+ }
+ const char *text = mText.c_str();
+ for (const char *textPtr = text; *textPtr; ++textPtr)
+ {
+ if (*textPtr < '0' || *textPtr > '9')
+ {
+ setText(mText.substr(0, textPtr - text));
+ return;
+ }
+ }
+}
+
+int TextField::getValue() const
+{
+ if (!mNumeric)
+ {
+ return 0;
+ }
+ int value = atoi(mText.c_str());
+ if (value < mMinimum)
+ {
+ return mMinimum;
+ }
+ if (value > mMaximum)
+ {
+ return mMaximum;
+ }
+ return value;
+}
+
void TextField::keyPressed(gcn::KeyEvent &keyEvent)
{
int val = keyEvent.getKey().getValue();
diff --git a/src/gui/textfield.h b/src/gui/textfield.h
index 3570f89d..73824615 100644
--- a/src/gui/textfield.h
+++ b/src/gui/textfield.h
@@ -25,6 +25,13 @@
#include <guichan/widgets/textfield.hpp>
class ImageRect;
+class TextField;
+
+class TextFieldListener
+{
+ public:
+ virtual void listen(const TextField *value) = 0;
+};
/**
* A text field.
@@ -54,13 +61,48 @@ class TextField : public gcn::TextField {
void drawFrame(gcn::Graphics *graphics);
/**
+ * Determine whether the field should be numeric or not
+ */
+ void setNumeric(bool numeric);
+
+ /**
+ * Set the range on the field if it is numeric
+ */
+ void setRange(int min, int max) {mMinimum = min; mMaximum = max; }
+
+ /**
* Processes one keypress.
*/
void keyPressed(gcn::KeyEvent &keyEvent);
+ /**
+ * Set the minimum value for a range
+ */
+ void setMinimum(int min) {mMinimum = min; }
+
+ /**
+ * Set the maximum value for a range
+ */
+ void setMaximum(int max) {mMaximum = max; }
+
+ /**
+ * Return the value for a numeric field
+ */
+ int getValue() const;
+
+ /**
+ * Add a listener
+ */
+ void addListener(TextFieldListener *listener) {mListener = listener; }
+
private:
static int instances;
+ static float mAlpha;
static ImageRect skin;
+ bool mNumeric;
+ int mMinimum;
+ int mMaximum;
+ TextFieldListener *mListener;
};
#endif
diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp
index 66df55b8..af30d1fe 100644
--- a/src/gui/trade.cpp
+++ b/src/gui/trade.cpp
@@ -19,8 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "trade.h"
-
#include <sstream>
#include <guichan/widgets/label.hpp>
@@ -32,26 +30,28 @@
#include "itemcontainer.h"
#include "scrollarea.h"
#include "textfield.h"
+#include "trade.h"
+
+#include "widgets/layout.h"
#include "../inventory.h"
#include "../item.h"
+#include "../localplayer.h"
#include "../net/messageout.h"
#include "../net/protocol.h"
-#include "../resources/iteminfo.h"
-
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
#include "../utils/tostring.h"
TradeWindow::TradeWindow(Network *network):
- Window("Trade: You"),
+ Window(_("Trade: You")),
mNetwork(network),
- mMyInventory(new Inventory),
- mPartnerInventory(new Inventory)
+ mMyInventory(new Inventory(INVENTORY_SIZE)),
+ mPartnerInventory(new Inventory(INVENTORY_SIZE))
{
- setWindowName("Trade");
+ setWindowName(_("Trade"));
setDefaultSize(115, 227, 342, 209);
setResizable(true);
@@ -63,47 +63,43 @@ TradeWindow::TradeWindow(Network *network):
mCancelButton = new Button(_("Cancel"), "cancel", this);
mTradeButton = new Button(_("Trade"), "trade", this);
- mMyItemContainer = new ItemContainer(mMyInventory.get());
+ mTradeButton->setEnabled(false);
+
+ mMyItemContainer = new ItemContainer(mMyInventory.get(), 2);
+ mMyItemContainer->setWidth(160);
mMyItemContainer->addSelectionListener(this);
- mMyItemContainer->setPosition(2, 2);
mMyScroll = new ScrollArea(mMyItemContainer);
- mMyScroll->setPosition(8, 8);
- mPartnerItemContainer = new ItemContainer(mPartnerInventory.get());
+ mPartnerItemContainer = new ItemContainer(mPartnerInventory.get(), 2);
+ mPartnerItemContainer->setWidth(160);
mPartnerItemContainer->addSelectionListener(this);
- mPartnerItemContainer->setPosition(2, 58);
mPartnerScroll = new ScrollArea(mPartnerItemContainer);
- mPartnerScroll->setPosition(8, 64);
mMoneyLabel = new gcn::Label(strprintf(_("You get %d GP."), 0));
mMoneyLabel2 = new gcn::Label(_("You give:"));
mMoneyField = new TextField;
mMoneyField->setWidth(50);
- mAddButton->adjustSize();
- mOkButton->adjustSize();
- mCancelButton->adjustSize();
- mTradeButton->adjustSize();
-
- mTradeButton->setEnabled(false);
-
- mItemNameLabel = new gcn::Label(strprintf(_("Name: %s"), ""));
- mItemDescriptionLabel = new gcn::Label(
- strprintf(_("Description: %s"), ""));
-
- add(mMyScroll);
- add(mPartnerScroll);
- add(mAddButton);
- add(mOkButton);
- add(mCancelButton);
- add(mTradeButton);
- add(mItemNameLabel);
- add(mItemDescriptionLabel);
- add(mMoneyLabel2);
- add(mMoneyField);
- add(mMoneyLabel);
+ place(1, 0, mMoneyLabel);
+ place(0, 1, mMyScroll).setPadding(3);
+ place(1, 1, mPartnerScroll).setPadding(3);
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
+ place(0, 0, mMoneyLabel2);
+ place(1, 0, mMoneyField);
+ place = getPlacer(0, 2);
+ place(0, 0, mAddButton);
+ place(1, 0, mOkButton);
+ place(2, 0, mTradeButton);
+ place(3, 0, mCancelButton);
+ Layout &layout = getLayout();
+ layout.extend(0, 2, 2, 1);
+ layout.setRowHeight(1, Layout::AUTO_SET);
+ layout.setRowHeight(2, 0);
+ layout.setColWidth(0, Layout::AUTO_SET);
+ layout.setColWidth(1, Layout::AUTO_SET);
loadWindowState();
}
@@ -114,48 +110,13 @@ TradeWindow::~TradeWindow()
void TradeWindow::widgetResized(const gcn::Event &event)
{
- Window::widgetResized(event);
+ mMyItemContainer->setWidth(mMyScroll->getWidth());
+ mPartnerItemContainer->setWidth(mPartnerScroll->getWidth());
- const gcn::Rectangle &area = getChildrenArea();
- const int width = area.width;
- const int height = area.height;
-
- mMoneyLabel2->setPosition(8, height - 8 - mMoneyLabel2->getHeight());
- mMoneyField->setPosition(
- 8 + mMoneyLabel2->getWidth(),
- height - 8 - mMoneyField->getHeight());
- mMoneyLabel->setPosition(
- mMoneyField->getX() + mMoneyField->getWidth() + 6,
- mMoneyLabel2->getY());
-
- mCancelButton->setPosition(width - 8 - mCancelButton->getWidth(),
- height - 8 - mCancelButton->getHeight());
- mTradeButton->setPosition(
- mCancelButton->getX() - 4 - mTradeButton->getWidth(),
- mCancelButton->getY());
- mOkButton->setPosition(mTradeButton->getX() - 4 - mOkButton->getWidth(),
- mCancelButton->getY());
- mAddButton->setPosition(mOkButton->getX() - 4 - mAddButton->getWidth(),
- mCancelButton->getY());
-
- mItemDescriptionLabel->setPosition(8,
- mOkButton->getY() - mItemDescriptionLabel->getHeight() - 4);
- mItemNameLabel->setPosition(8,
- mItemDescriptionLabel->getY() - mItemNameLabel->getHeight() - 4);
-
- const int remaining = mItemNameLabel->getY() - 4 - 8 - 8;
- const int itemContainerHeight = remaining / 2;
-
- mMyItemContainer->setSize(width - 24 - 12 - 1,
- (INVENTORY_SIZE * 24) / (width / 24) - 1);
- mMyScroll->setSize(width - 16, itemContainerHeight);
-
- mPartnerItemContainer->setSize(width - 24 - 12 - 1,
- (INVENTORY_SIZE * 24) / (width / 24) - 1);
- mPartnerScroll->setSize(width - 16, itemContainerHeight);
- mPartnerScroll->setPosition(8, 8 + itemContainerHeight + 8);
+ Window::widgetResized(event);
}
+
void TradeWindow::addMoney(int amount)
{
mMoneyLabel->setCaption(strprintf(_("You get %d GP."), amount));
@@ -164,38 +125,40 @@ void TradeWindow::addMoney(int amount)
void TradeWindow::addItem(int id, bool own, int quantity, bool equipment)
{
- if (own) {
+ if (own)
+ {
+ mMyItemContainer->setWidth(mMyScroll->getWidth());
mMyInventory->addItem(id, quantity, equipment);
- } else {
+ }
+ else
+ {
+ mPartnerItemContainer->setWidth(mPartnerScroll->getWidth());
mPartnerInventory->addItem(id, quantity, equipment);
}
}
void TradeWindow::removeItem(int id, bool own)
{
- if (own) {
+ if (own)
mMyInventory->removeItem(id);
- } else {
+ else
mPartnerInventory->removeItem(id);
- }
}
void TradeWindow::changeQuantity(int index, bool own, int quantity)
{
- if (own) {
+ if (own)
mMyInventory->getItem(index)->setQuantity(quantity);
- } else {
+ else
mPartnerInventory->getItem(index)->setQuantity(quantity);
- }
}
void TradeWindow::increaseQuantity(int index, bool own, int quantity)
{
- if (own) {
+ if (own)
mMyInventory->getItem(index)->increaseQuantity(quantity);
- } else {
+ else
mPartnerInventory->getItem(index)->increaseQuantity(quantity);
- }
}
void TradeWindow::reset()
@@ -218,21 +181,30 @@ void TradeWindow::setTradeButton(bool enabled)
void TradeWindow::receivedOk(bool own)
{
- if (own) {
+ if (own)
+ {
mOkMe = true;
- if (mOkOther) {
+ if (mOkOther)
+ {
mTradeButton->setEnabled(true);
mOkButton->setEnabled(false);
- } else {
+ }
+ else
+ {
mTradeButton->setEnabled(false);
mOkButton->setEnabled(false);
}
- } else {
+ }
+ else
+ {
mOkOther = true;
- if (mOkMe) {
+ if (mOkMe)
+ {
mTradeButton->setEnabled(true);
mOkButton->setEnabled(false);
- } else {
+ }
+ else
+ {
mTradeButton->setEnabled(false);
mOkButton->setEnabled(true);
}
@@ -256,22 +228,9 @@ void TradeWindow::valueChanged(const gcn::SelectionEvent &event)
*/
if (event.getSource() == mMyItemContainer &&
(item = mMyItemContainer->getSelectedItem()))
- {
mPartnerItemContainer->selectNone();
- }
else if ((item = mPartnerItemContainer->getSelectedItem()))
- {
mMyItemContainer->selectNone();
- }
-
- // Update name and description
- ItemInfo const *info = item ? &item->getInfo() : NULL;
- mItemNameLabel->setCaption(strprintf(_("Name: %s"),
- info ? info->getName().c_str() : ""));
- mItemNameLabel->adjustSize();
- mItemDescriptionLabel->setCaption(strprintf(_("Description: %s"),
- info ? info->getDescription().c_str() : ""));
- mItemDescriptionLabel->adjustSize();
}
void TradeWindow::action(const gcn::ActionEvent &event)
@@ -286,16 +245,19 @@ void TradeWindow::action(const gcn::ActionEvent &event)
if (mMyInventory->getFreeSlot() < 1)
return;
- if (mMyInventory->contains(item)) {
+ if (mMyInventory->contains(item))
+ {
chatWindow->chatLog(_("Failed adding item. You can not "
"overlap one kind of item on the window."), BY_SERVER);
return;
}
- if (item->getQuantity() == 1) {
+ if (item->getQuantity() == 1)
+ {
tradeItem(item, 1);
}
- else {
+ else
+ {
// Choose amount of items to trade
new ItemAmountWindow(AMOUNT_TRADE_ADD, this, item);
}
@@ -317,7 +279,9 @@ void TradeWindow::action(const gcn::ActionEvent &event)
outMsg.writeInt16(CMSG_TRADE_ITEM_ADD_REQUEST);
outMsg.writeInt16(0);
outMsg.writeInt32(tempInt);
- } else {
+ }
+ else
+ {
mMoneyField->setText("");
}
mMoneyField->setEnabled(false);
diff --git a/src/gui/trade.h b/src/gui/trade.h
index 3129c4b9..df724038 100644
--- a/src/gui/trade.h
+++ b/src/gui/trade.h
@@ -128,8 +128,6 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener
ItemContainer *mMyItemContainer;
ItemContainer *mPartnerItemContainer;
- gcn::Label *mItemNameLabel;
- gcn::Label *mItemDescriptionLabel;
gcn::Label *mMoneyLabel;
gcn::Label *mMoneyLabel2;
gcn::Button *mAddButton, *mOkButton, *mCancelButton, *mTradeButton;
diff --git a/src/gui/truetypefont.cpp b/src/gui/truetypefont.cpp
index f65b3446..8e6636df 100644
--- a/src/gui/truetypefont.cpp
+++ b/src/gui/truetypefont.cpp
@@ -19,12 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "truetypefont.h"
-
#include <list>
#include <guichan/exception.hpp>
+#include "truetypefont.h"
+
#include "../graphics.h"
#include "../resources/image.h"
@@ -74,7 +74,6 @@ class TextChunk
gcn::Color color;
};
-
// Word surfaces cache
static std::list<TextChunk> cache;
typedef std::list<TextChunk>::iterator CacheIterator;
@@ -92,7 +91,7 @@ TrueTypeFont::TrueTypeFont(const std::string &filename, int size)
++fontCounter;
mFont = TTF_OpenFont(filename.c_str(), size);
- if (mFont == NULL)
+ if (!mFont)
{
throw GCN_EXCEPTION("SDLTrueTypeFont::SDLTrueTypeFont: " +
std::string(TTF_GetError()));
diff --git a/src/gui/truetypefont.h b/src/gui/truetypefont.h
index 6f0671a2..cd68a94e 100644
--- a/src/gui/truetypefont.h
+++ b/src/gui/truetypefont.h
@@ -25,7 +25,6 @@
#include <string>
#include <guichan/font.hpp>
-#include <guichan/graphics.hpp>
#ifndef __APPLE__
#include <SDL/SDL_ttf.h>
#else
diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp
index 96c2e95c..b3861b27 100644
--- a/src/gui/updatewindow.cpp
+++ b/src/gui/updatewindow.cpp
@@ -19,8 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "updatewindow.h"
-
#include <iostream>
#include <SDL.h>
#include <SDL_thread.h>
@@ -28,23 +26,26 @@
#include <guichan/widgets/label.hpp>
+// Curl should be included after Guichan to avoid Windows redefinitions
+#include <curl/curl.h>
+
#include "browserbox.h"
#include "button.h"
#include "progressbar.h"
#include "scrollarea.h"
+#include "updatewindow.h"
-// Curl should be included after Guichan to avoid Windows redefinitions
-#include <curl/curl.h>
+#include "widgets/layout.h"
#include "../configuration.h"
#include "../log.h"
#include "../main.h"
+#include "../resources/resourcemanager.h"
+
#include "../utils/gettext.h"
#include "../utils/tostring.h"
-#include "../resources/resourcemanager.h"
-
/**
* Calculates the Alder-32 checksum for the given file.
*/
@@ -68,8 +69,7 @@ static unsigned long fadler32(FILE *file)
/**
* Load the given file into a vector of strings.
*/
-std::vector<std::string>
-loadTextFile(const std::string &fileName)
+std::vector<std::string> loadTextFile(const std::string &fileName)
{
std::vector<std::string> lines;
std::ifstream fin(fileName.c_str());
@@ -107,34 +107,29 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost,
{
mCurlError[0] = 0;
- const int h = 240;
- const int w = 320;
- setContentSize(w, h);
-
mBrowserBox = new BrowserBox();
mScrollArea = new ScrollArea(mBrowserBox);
mLabel = new gcn::Label(_("Connecting..."));
- mProgressBar = new ProgressBar(0.0, w - 10, 20, 37, 70, 200);
+ mProgressBar = new ProgressBar(0.0, 310, 20, 168, 116, 31);
mCancelButton = new Button(_("Cancel"), "cancel", this);
mPlayButton = new Button(_("Play"), "play", this);
mBrowserBox->setOpaque(false);
mPlayButton->setEnabled(false);
- mCancelButton->setPosition(5, h - 5 - mCancelButton->getHeight());
- mPlayButton->setPosition(
- mCancelButton->getX() + mCancelButton->getWidth() + 5,
- h - 5 - mPlayButton->getHeight());
- mProgressBar->setPosition(5, mCancelButton->getY() - 20 - 5);
- mLabel->setPosition(5, mProgressBar->getY() - mLabel->getHeight() - 5);
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
+
+ place(0, 0, mScrollArea, 5, 3).setPadding(3);
+ place(0, 3, mLabel, 5);
+ place(0, 4, mProgressBar, 5);
+ place(3, 5, mCancelButton);
+ place(4, 5, mPlayButton);
- mScrollArea->setDimension(gcn::Rectangle(5, 5, 310, mLabel->getY() - 12));
+ reflowLayout(320, 240);
- add(mScrollArea);
- add(mLabel);
- add(mProgressBar);
- add(mCancelButton);
- add(mPlayButton);
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
setLocationRelativeTo(getParent());
setVisible(true);
@@ -210,7 +205,7 @@ void UpdaterWindow::loadNews()
// Tokenize and add each line separately
char *line = strtok(mMemoryBuffer, "\n");
- while (line != NULL)
+ while (line)
{
mBrowserBox->addRow(line);
line = strtok(NULL, "\n");
@@ -246,8 +241,7 @@ int UpdaterWindow::updateProgress(void *ptr,
return 0;
}
-size_t
-UpdaterWindow::memoryWrite(void *ptr, size_t size, size_t nmemb, FILE *stream)
+size_t UpdaterWindow::memoryWrite(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
UpdaterWindow *uw = reinterpret_cast<UpdaterWindow *>(stream);
size_t totalMem = size * nmemb;
@@ -330,8 +324,8 @@ int UpdaterWindow::downloadThread(void *ptr)
{
case CURLE_COULDNT_CONNECT:
default:
- std::cerr << "curl error " << res << ": "
- << uw->mCurlError << " host: " << url.c_str()
+ std::cerr << _("curl error ") << res << ": "
+ << uw->mCurlError << _(" host: ") << url.c_str()
<< std::endl;
break;
}
@@ -366,7 +360,7 @@ int UpdaterWindow::downloadThread(void *ptr)
// Remove the corrupted file
::remove(outFilename.c_str());
logger->log(
- "Checksum for file %s failed: (%lx/%lx)",
+ _("Checksum for file %s failed: (%lx/%lx)"),
uw->mCurrentFile.c_str(),
adler, uw->mCurrentChecksum);
attempts++;
@@ -414,7 +408,7 @@ void UpdaterWindow::download()
mDownloadComplete = false;
mThread = SDL_CreateThread(UpdaterWindow::downloadThread, this);
- if (mThread == NULL)
+ if (!mThread)
{
logger->log("Unable to create mThread");
mDownloadStatus = UPDATE_ERROR;
@@ -454,9 +448,9 @@ void UpdaterWindow::logic()
mThread = NULL;
}
mBrowserBox->addRow("");
- mBrowserBox->addRow("##1 The update process is incomplete.");
- mBrowserBox->addRow("##1 It is strongly recommended that");
- mBrowserBox->addRow("##1 you try again later");
+ mBrowserBox->addRow(_("##1 The update process is incomplete."));
+ mBrowserBox->addRow(_("##1 It is strongly recommended that"));
+ mBrowserBox->addRow(_("##1 you try again later"));
mBrowserBox->addRow(mCurlError);
mScrollArea->setVerticalScrollAmount(
mScrollArea->getVerticalMaxScroll());
diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h
index 3acbfb7e..4ada3c3a 100644
--- a/src/gui/updatewindow.h
+++ b/src/gui/updatewindow.h
@@ -23,13 +23,12 @@
#define _UPDATERWINDOW_H
#include <guichan/actionlistener.hpp>
+
#include <string>
#include <vector>
#include "window.h"
-#include "../guichanfwd.h"
-
#include "../utils/mutex.h"
class BrowserBox;
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index ff0883f7..f5a6edb4 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -19,33 +19,26 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "viewport.h"
-
-#include "gui.h"
-#include "popupmenu.h"
#include "ministatus.h"
+#include "popupmenu.h"
+#include "viewport.h"
-#include "../simpleanimation.h"
#include "../beingmanager.h"
#include "../configuration.h"
#include "../flooritemmanager.h"
#include "../graphics.h"
+#include "../keyboardconfig.h"
#include "../localplayer.h"
#include "../map.h"
#include "../monster.h"
#include "../npc.h"
#include "../textmanager.h"
-#include "../resources/animation.h"
#include "../resources/monsterinfo.h"
#include "../resources/resourcemanager.h"
-#include "../resources/image.h"
-#include "../resources/imageset.h"
#include "../utils/tostring.h"
-#include <cassert>
-
extern volatile int tick_time;
Viewport::Viewport():
@@ -70,76 +63,21 @@ Viewport::Viewport():
config.addListener("ScrollRadius", this);
mPopupMenu = new PopupMenu();
-
- // Load target cursors
- loadTargetCursor("graphics/gui/target-cursor-blue-s.png", 44, 35,
- false, Being::TC_SMALL);
- loadTargetCursor("graphics/gui/target-cursor-red-s.png", 44, 35,
- true, Being::TC_SMALL);
- loadTargetCursor("graphics/gui/target-cursor-blue-m.png", 62, 44,
- false, Being::TC_MEDIUM);
- loadTargetCursor("graphics/gui/target-cursor-red-m.png", 62, 44,
- true, Being::TC_MEDIUM);
- loadTargetCursor("graphics/gui/target-cursor-blue-l.png", 82, 60,
- false, Being::TC_LARGE);
- loadTargetCursor("graphics/gui/target-cursor-red-l.png", 82, 60,
- true, Being::TC_LARGE);
-}
-
-void
-Viewport::loadTargetCursor(std::string filename, int width, int height,
- bool outRange, Being::TargetCursorSize size)
-{
- assert(size > -1);
- assert(size < 3);
-
- ImageSet* currentImageSet;
- SimpleAnimation* currentCursor;
-
- ResourceManager *resman = ResourceManager::getInstance();
-
- currentImageSet = resman->getImageSet(filename, width, height);
- Animation *anim = new Animation();
- for (unsigned int i = 0; i < currentImageSet->size(); ++i)
- {
- anim->addFrame(currentImageSet->get(i), 75, 0, 0);
- }
- currentCursor = new SimpleAnimation(anim);
-
- if (outRange)
- {
- mOutRangeImages[size] = currentImageSet;
- mTargetCursorOutRange[size] = currentCursor;
- }
- else {
- mInRangeImages[size] = currentImageSet;
- mTargetCursorInRange[size] = currentCursor;
- }
}
Viewport::~Viewport()
{
delete mPopupMenu;
-
- for (int i = Being::TC_SMALL; i < Being::NUM_TC; i++)
- {
- delete mTargetCursorInRange[i];
- delete mTargetCursorOutRange[i];
- mInRangeImages[i]->decRef();
- mOutRangeImages[i]->decRef();
- }
}
-void
-Viewport::setMap(Map *map)
+void Viewport::setMap(Map *map)
{
mMap = map;
}
extern MiniStatusWindow *miniStatusWindow;
-void
-Viewport::draw(gcn::Graphics *gcnGraphics)
+void Viewport::draw(gcn::Graphics *gcnGraphics)
{
static int lastTick = tick_time;
@@ -148,6 +86,10 @@ Viewport::draw(gcn::Graphics *gcnGraphics)
Graphics *graphics = static_cast<Graphics*>(gcnGraphics);
+ // Ensure the client doesn't freak out if a feature localplayer uses
+ // is dependent on a map.
+ player_node->mMapInitialized = true;
+
// Avoid freaking out when tick_time overflows
if (tick_time < lastTick)
{
@@ -225,37 +167,39 @@ Viewport::draw(gcn::Graphics *gcnGraphics)
if (mMap)
{
mMap->draw(graphics, (int) mPixelViewX, (int) mPixelViewY);
- drawTargetCursor(graphics); // TODO: Draw the cursor with the sprite
- }
- // Find a path from the player to the mouse, and draw it. This is for debug
- // purposes.
- if (mShowDebugPath && mMap)
- {
- // Get the current mouse position
- int mouseX, mouseY;
- SDL_GetMouseState(&mouseX, &mouseY);
+ // Find a path from the player to the mouse, and draw it. This is for debug
+ // purposes.
+ if (mShowDebugPath)
+ {
+ // Get the current mouse position
+ int mouseX, mouseY;
+ SDL_GetMouseState(&mouseX, &mouseY);
- int mouseTileX = mouseX / 32 + mTileViewX;
- int mouseTileY = mouseY / 32 + mTileViewY;
+ int mouseTileX = mouseX / 32 + mTileViewX;
+ int mouseTileY = mouseY / 32 + mTileViewY;
- Path debugPath = mMap->findPath(
- player_node->mX, player_node->mY,
- mouseTileX, mouseTileY);
+ Path debugPath = mMap->findPath(player_node->mX, player_node->mY, mouseTileX, mouseTileY);
- graphics->setColor(gcn::Color(255, 0, 0));
- for (PathIterator i = debugPath.begin(); i != debugPath.end(); i++)
- {
- int squareX = i->x * 32 - (int) mPixelViewX + 12;
- int squareY = i->y * 32 - (int) mPixelViewY + 12;
+ graphics->setColor(gcn::Color(255, 0, 0));
+ for (PathIterator i = debugPath.begin(); i != debugPath.end(); i++)
+ {
+ int squareX = i->x * 32 - (int) mPixelViewX + 12;
+ int squareY = i->y * 32 - (int) mPixelViewY + 12;
- graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8));
- graphics->drawText(
- toString(mMap->getMetaTile(i->x, i->y)->Gcost),
- squareX + 4, squareY + 12, gcn::Graphics::CENTER);
+ graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8));
+ graphics->drawText(toString(mMap->getMetaTile(i->x, i->y)->Gcost), squareX + 4, squareY + 12, gcn::Graphics::CENTER);
+ }
}
}
+ if (player_node->mUpdateName)
+ {
+ player_node->mUpdateName = false;
+ player_node->setName(player_node->getName());
+ }
+
+
// Draw text
if (textManager)
{
@@ -266,6 +210,7 @@ Viewport::draw(gcn::Graphics *gcnGraphics)
Beings &beings = beingManager->getAll();
for (BeingIterator i = beings.begin(); i != beings.end(); i++)
{
+ (*i)->drawSpeech(-(int) mPixelViewX, -(int) mPixelViewY);
(*i)->drawEmotion(graphics, -(int) mPixelViewX, -(int) mPixelViewY);
}
@@ -276,8 +221,7 @@ Viewport::draw(gcn::Graphics *gcnGraphics)
WindowContainer::draw(gcnGraphics);
}
-void
-Viewport::logic()
+void Viewport::logic()
{
WindowContainer::logic();
@@ -294,49 +238,9 @@ Viewport::logic()
mouseY / 32 + mTileViewY);
mWalkTime = player_node->mWalkTime;
}
-
- for (int i = 0; i < 3; i++)
- {
- mTargetCursorInRange[i]->update(10);
- mTargetCursorOutRange[i]->update(10);
- }
-}
-
-void
-Viewport::drawTargetCursor(Graphics *graphics)
-{
- // Draw target marker if needed
- Being *target = player_node->getTarget();
- if (target)
- {
- // Calculate target circle position
-
- // Find whether target is in range
- int rangeX = abs(target->mX - player_node->mX);
- int rangeY = abs(target->mY - player_node->mY);
- int attackRange = player_node->getAttackRange();
-
- // Get the correct target cursors graphic
- Being::TargetCursorSize cursorSize = target->getTargetCursorSize();
- Image* targetCursor;
- if (rangeX > attackRange || rangeY > attackRange)
- {
- targetCursor = mTargetCursorOutRange[cursorSize]->getCurrentImage();
- }
- else {
- targetCursor = mTargetCursorInRange[cursorSize]->getCurrentImage();
- }
-
- // Draw the target cursor at the correct position
- int posX = target->getPixelX() + 16 - targetCursor->getWidth() / 2 - (int) mPixelViewX;
- int posY = target->getPixelY() + 16 - targetCursor->getHeight() / 2 - (int) mPixelViewY;
-
- graphics->drawImage(targetCursor, posX, posY);
- }
}
-void
-Viewport::mousePressed(gcn::MouseEvent &event)
+void Viewport::mousePressed(gcn::MouseEvent &event)
{
// Check if we are alive and kickin'
if (!mMap || !player_node || player_node->mAction == Being::DEAD)
@@ -348,8 +252,10 @@ Viewport::mousePressed(gcn::MouseEvent &event)
mPlayerFollowMouse = false;
- int tilex = event.getX() / 32 + mTileViewX;
- int tiley = event.getY() / 32 + mTileViewY;
+ const int tilex = event.getX() / 32 + mTileViewX;
+ const int tiley = event.getY() / 32 + mTileViewY;
+ const int x = (int)((float) event.getX() + mPixelViewX);
+ const int y = (int)((float) event.getY() + mPixelViewY);
// Right click might open a popup
if (event.getButton() == gcn::MouseEvent::RIGHT)
@@ -357,13 +263,14 @@ Viewport::mousePressed(gcn::MouseEvent &event)
Being *being;
FloorItem *floorItem;
- if ((being = beingManager->findBeing(tilex, tiley)) &&
- being != player_node)
+ if ((being = beingManager->findBeingByPixel(x, y)) &&
+ being != player_node)
{
- mPopupMenu->showPopup(event.getX(), event.getY(), being);
- return;
+ mPopupMenu->showPopup(event.getX(), event.getY(), being);
+ return;
}
- else if((floorItem = floorItemManager->findByCoordinates(tilex, tiley)))
+ else if ((floorItem = floorItemManager->findByCoordinates(tilex,
+ tiley)))
{
mPopupMenu->showPopup(event.getX(), event.getY(), floorItem);
return;
@@ -384,9 +291,7 @@ Viewport::mousePressed(gcn::MouseEvent &event)
FloorItem *item;
// Interact with some being
-// if ((being = beingManager->findBeing(tilex, tiley))
- int x = (int)((float) event.getX() + mPixelViewX);
- int y = (int)((float) event.getY() + mPixelViewY);
+// if ((being = beingManager->findBeing(tilex, tiley)))
if ((being = beingManager->findBeingByPixel(x, y)))
{
switch (being->getType())
@@ -400,59 +305,47 @@ Viewport::mousePressed(gcn::MouseEvent &event)
if (being->mAction == Being::DEAD)
break;
- if (player_node->withinAttackRange(being))
+ if (player_node->withinAttackRange(being) || keyboard.isKeyActive(keyboard.KEY_ATTACK))
{
- player_node->attack(being, true);
+ player_node->setGotoTarget(being);
+ player_node->attack(being, !keyboard.isKeyActive(keyboard.KEY_TARGET));
}
else
{
- Uint8 *keys = SDL_GetKeyState(NULL);
- if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]))
- {
- player_node->stopAttack();
- player_node->setGotoTarget(being);
- }
+ player_node->setDestination(tilex, tiley);
}
break;
default:
break;
- }
+ }
}
// Pick up some item
else if ((item = floorItemManager->findByCoordinates(tilex, tiley)))
{
- player_node->pickUp(item);
+ player_node->pickUp(item);
}
// Just walk around
else
{
- // XXX XXX XXX REALLY UGLY!
- Uint8 *keys = SDL_GetKeyState(NULL);
- if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]))
- {
- player_node->setDestination(tilex, tiley);
- player_node->stopAttack();
- }
+ player_node->stopAttack();
+ player_node->setDestination(tilex, tiley);
mPlayerFollowMouse = true;
}
}
else if (event.getButton() == gcn::MouseEvent::MIDDLE)
{
// Find the being nearest to the clicked position
- Being *target = beingManager->findNearestLivingBeing(
- tilex, tiley,
- 20, Being::MONSTER);
+ Being *target = beingManager->findBeingByPixel(x, y);
if (target)
{
- player_node->setTarget(target);
+ player_node->setTarget(target);
}
}
}
-void
-Viewport::mouseDragged(gcn::MouseEvent &event)
+void Viewport::mouseDragged(gcn::MouseEvent &event)
{
if (!mMap || !player_node)
return;
@@ -465,20 +358,17 @@ Viewport::mouseDragged(gcn::MouseEvent &event)
}
}
-void
-Viewport::mouseReleased(gcn::MouseEvent &event)
+void Viewport::mouseReleased(gcn::MouseEvent &event)
{
mPlayerFollowMouse = false;
}
-void
-Viewport::showPopup(int x, int y, Item *item)
+void Viewport::showPopup(int x, int y, Item *item)
{
mPopupMenu->showPopup(x, y, item);
}
-void
-Viewport::optionChanged(const std::string &name)
+void Viewport::optionChanged(const std::string &name)
{
mScrollLaziness = (int) config.getValue("ScrollLaziness", 32);
mScrollRadius = (int) config.getValue("ScrollRadius", 32);
diff --git a/src/gui/viewport.h b/src/gui/viewport.h
index 8965ad95..522ea734 100644
--- a/src/gui/viewport.h
+++ b/src/gui/viewport.h
@@ -27,15 +27,14 @@
#include "windowcontainer.h"
#include "../configlistener.h"
-#include "../being.h"
+#include "../position.h"
-class Map;
class FloorItem;
+class Graphics;
class ImageSet;
class Item;
+class Map;
class PopupMenu;
-class Graphics;
-class SimpleAnimation;
/**
* The viewport on the map. Displays the current map and handles mouse input
@@ -62,97 +61,65 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
/**
* Sets the map displayed by the viewport.
*/
- void
- setMap(Map *map);
+ void setMap(Map *map);
/**
* Draws the viewport.
*/
- void
- draw(gcn::Graphics *graphics);
+ void draw(gcn::Graphics *graphics);
/**
* Implements player to keep following mouse.
*/
- void
- logic();
+ void logic();
/**
* Toggles whether the path debug graphics are shown
*/
- void
- toggleDebugPath() { mShowDebugPath = !mShowDebugPath; }
+ void toggleDebugPath() { mShowDebugPath = !mShowDebugPath; }
/**
* Handles mouse press on map.
*/
- void
- mousePressed(gcn::MouseEvent &event);
+ void mousePressed(gcn::MouseEvent &event);
/**
* Handles mouse move on map
*/
- void
- mouseDragged(gcn::MouseEvent &event);
+ void mouseDragged(gcn::MouseEvent &event);
/**
* Handles mouse button release on map.
*/
- void
- mouseReleased(gcn::MouseEvent &event);
+ void mouseReleased(gcn::MouseEvent &event);
/**
* Shows a popup for an item.
* TODO Find some way to get rid of Item here
*/
- void
- showPopup(int x, int y, Item *item);
+ void showPopup(int x, int y, Item *item);
/**
* A relevant config option changed.
*/
- void
- optionChanged(const std::string &name);
+ void optionChanged(const std::string &name);
/**
- * Returns camera x offset in tiles.
+ * Returns camera x offset in pixels.
*/
- int
- getCameraX() { return mTileViewX; }
+ int getCameraX() const { return (int) mPixelViewX; }
/**
- * Returns camera y offset in tiles.
+ * Returns camera y offset in pixels.
*/
- int
- getCameraY() { return mTileViewY; }
+ int getCameraY() const { return (int) mPixelViewY; }
/**
* Changes viewpoint by relative pixel coordinates.
*/
- void
- scrollBy(float x, float y) { mPixelViewX += x; mPixelViewY += y; }
+ void scrollBy(float x, float y) { mPixelViewX += x; mPixelViewY += y; }
private:
- /**
- * Helper function for loading target cursors
- */
- void
- loadTargetCursor(std::string filename, int width, int height,
- bool outRange, Being::TargetCursorSize size);
-
- /**
- * Draws range based target cursor
- */
- void
- drawTargetCursor(Graphics *graphics);
-
- /**
- * Draws target name
- */
- void
- drawTargetName(Graphics *graphics);
-
-
Map *mMap; /**< The current map. */
int mScrollRadius;
@@ -165,22 +132,12 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
int mTileViewY; /**< Current viewpoint in tiles. */
bool mShowDebugPath; /**< Show a path from player to pointer. */
- /** Images of in range target cursor. */
- ImageSet *mInRangeImages[Being::NUM_TC];
-
- /** Images of out of range target cursor. */
- ImageSet *mOutRangeImages[Being::NUM_TC];
-
- /** Animated in range target cursor. */
- SimpleAnimation *mTargetCursorInRange[Being::NUM_TC];
-
- /** Animated out of range target cursor. */
- SimpleAnimation *mTargetCursorOutRange[Being::NUM_TC];
-
bool mPlayerFollowMouse;
int mWalkTime;
PopupMenu *mPopupMenu; /**< Popup menu. */
};
+extern Viewport *viewport; /**< The viewport */
+
#endif
diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp
new file mode 100644
index 00000000..29c6c69c
--- /dev/null
+++ b/src/gui/widgets/dropdown.cpp
@@ -0,0 +1,203 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <algorithm>
+
+#include "dropdown.h"
+
+#include "../color.h"
+#include "../listbox.h"
+#include "../scrollarea.h"
+
+#include "../../configuration.h"
+#include "../../graphics.h"
+
+#include "../../resources/image.h"
+#include "../../resources/resourcemanager.h"
+
+#include "../../utils/dtor.h"
+
+int DropDown::instances = 0;
+Image *DropDown::buttons[2][2];
+ImageRect DropDown::skin;
+float DropDown::mAlpha = config.getValue("guialpha", 0.8);
+
+DropDown::DropDown(gcn::ListModel *listModel, gcn::ScrollArea *scrollArea,
+ gcn::ListBox *listBox, bool opacity):
+ gcn::DropDown::DropDown(listModel, scrollArea, listBox),
+ mOpaque(opacity)
+{
+ setFrameSize(2);
+
+ // Initialize graphics
+ if (instances == 0)
+ {
+ // Load the background skin
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ // Get the button skin
+ buttons[1][0] =
+ resman->getImage("graphics/gui/vscroll_up_default.png");
+ buttons[0][0] =
+ resman->getImage("graphics/gui/vscroll_down_default.png");
+ buttons[1][1] =
+ resman->getImage("graphics/gui/vscroll_up_pressed.png");
+ buttons[0][1] =
+ resman->getImage("graphics/gui/vscroll_down_pressed.png");
+
+ buttons[0][0]->setAlpha(mAlpha);
+ buttons[0][1]->setAlpha(mAlpha);
+ buttons[1][0]->setAlpha(mAlpha);
+ buttons[1][1]->setAlpha(mAlpha);
+
+ // get the border skin
+ Image *boxBorder = resman->getImage("graphics/gui/deepbox.png");
+ int gridx[4] = {0, 3, 28, 31};
+ int gridy[4] = {0, 3, 28, 31};
+ int a = 0, x, y;
+
+ for (y = 0; y < 3; y++) {
+ for (x = 0; x < 3; x++) {
+ skin.grid[a] = boxBorder->getSubImage(
+ gridx[x], gridy[y],
+ gridx[x + 1] - gridx[x] + 1,
+ gridy[y + 1] - gridy[y] + 1);
+ skin.grid[a]->setAlpha(mAlpha);
+ a++;
+ }
+ }
+
+ boxBorder->decRef();
+ }
+
+ instances++;
+}
+
+DropDown::~DropDown()
+{
+ instances--;
+ // Free images memory
+ if (instances == 0)
+ {
+ buttons[0][0]->decRef();
+ buttons[0][1]->decRef();
+ buttons[1][0]->decRef();
+ buttons[1][1]->decRef();
+
+ for_each(skin.grid, skin.grid + 9, dtor<Image*>());
+ }
+}
+
+void DropDown::draw(gcn::Graphics* graphics)
+{
+ int h;
+
+ if (mDroppedDown)
+ {
+ h = mFoldedUpHeight;
+ }
+ else
+ {
+ h = getHeight();
+ }
+
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+
+ buttons[0][0]->setAlpha(mAlpha);
+ buttons[0][1]->setAlpha(mAlpha);
+ buttons[1][0]->setAlpha(mAlpha);
+ buttons[1][1]->setAlpha(mAlpha);
+
+ for (int a = 0; a < 9; a++)
+ {
+ skin.grid[a]->setAlpha(mAlpha);
+ }
+ }
+
+ bool valid;
+ const int alpha = mAlpha * 255;
+ gcn::Color faceColor = getBaseColor();
+ faceColor.a = alpha;
+ gcn::Color highlightColor = textColor->getColor('H', valid);
+ highlightColor.a = alpha;
+ gcn::Color shadowColor = faceColor - 0x303030;
+ shadowColor.a = alpha;
+
+ if (mOpaque)
+ {
+ int red = getBackgroundColor().r;
+ int green = getBackgroundColor().g;
+ int blue = getBackgroundColor().b;
+ graphics->setColor(gcn::Color(red, green, blue, alpha));
+ graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), h));
+
+ red = getForegroundColor().r;
+ green = getForegroundColor().g;
+ blue = getForegroundColor().b;
+ graphics->setColor(gcn::Color(red, green, blue, alpha));
+ }
+
+ graphics->setFont(getFont());
+
+ if (mListBox->getListModel() && mListBox->getSelected() >= 0)
+ {
+ graphics->drawText(mListBox->getListModel()->getElementAt(mListBox->getSelected()), 1, 0);
+ }
+
+ if (isFocused())
+ {
+ graphics->setColor(highlightColor);
+ graphics->drawRectangle(gcn::Rectangle(0, 0, getWidth() - h, h));
+ }
+
+ drawButton(graphics);
+
+ if (mDroppedDown)
+ {
+ drawChildren(graphics);
+
+ // Draw two lines separating the ListBox with selected
+ // element view.
+ graphics->setColor(highlightColor);
+ graphics->drawLine(0, h, getWidth(), h);
+ graphics->setColor(shadowColor);
+ graphics->drawLine(0, h + 1, getWidth(), h + 1);
+ }
+}
+
+void DropDown::drawFrame(gcn::Graphics *graphics)
+{
+ const int bs = getFrameSize();
+ const int w = getWidth() + bs * 2;
+ const int h = getHeight() + bs * 2;
+
+ static_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, skin);
+}
+
+void DropDown::drawButton(gcn::Graphics *graphics)
+{
+ int height = mDroppedDown ? mFoldedUpHeight : getHeight();
+
+ static_cast<Graphics*>(graphics)->
+ drawImage(buttons[mDroppedDown][mPushed], getWidth() - height + 2, 1);
+}
diff --git a/src/gui/widgets/dropdown.h b/src/gui/widgets/dropdown.h
new file mode 100644
index 00000000..e5919dc7
--- /dev/null
+++ b/src/gui/widgets/dropdown.h
@@ -0,0 +1,99 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DROPDOWN_H
+#define DROPDOWN_H
+
+#include <guichan/widgets/dropdown.hpp>
+
+class Image;
+class ImageRect;
+
+ /**
+ * A drop down box from which you can select different values. It is one of
+ * the most complicated Widgets you will find in Guichan. For drawing the
+ * DroppedDown box it uses one ScrollArea and one ListBox. It also uses an
+ * internal FocusHandler to handle the focus of the internal ScollArea and
+ * ListBox. DropDown uses a ListModel to handle the list. To be able to use
+ * DropDown you must give DropDown an implemented ListModel which represents
+ * your list.
+ */
+class DropDown : public gcn::DropDown
+{
+ public:
+ /**
+ * Contructor.
+ *
+ * @param listModel the ListModel to use.
+ * @param scrollArea the ScrollArea to use.
+ * @param listBox the listBox to use.
+ * @see ListModel, ScrollArea, ListBox.
+ */
+ DropDown(gcn::ListModel *listModel = NULL,
+ gcn::ScrollArea *scrollArea = NULL,
+ gcn::ListBox *listBox = NULL,
+ bool opacity = true);
+
+ /**
+ * Destructor.
+ */
+ ~DropDown();
+
+ void draw(gcn::Graphics* graphics);
+
+ void drawFrame(gcn::Graphics* graphics);
+
+ /**
+ * Sets the widget to be opaque, that is sets the widget to display its
+ * background.
+ *
+ * @param opaque True if the widget should be opaque, false otherwise.
+ */
+ void setOpaque(bool opaque) {mOpaque = opaque;}
+
+ /**
+ * Checks if the widget is opaque, that is if the widget area displays
+ * its background.
+ *
+ * @return True if the widget is opaque, false otherwise.
+ */
+ bool isOpaque() const {return mOpaque;}
+
+
+ protected:
+ /**
+ * Draws the button with the little down arrow.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ void drawButton(gcn::Graphics *graphics);
+
+ // Add own Images.
+ static int instances;
+ static Image *buttons[2][2];
+ static ImageRect skin;
+ static float mAlpha;
+
+ bool mOpaque;
+};
+
+#endif // end DROPDOWN_H
+
diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp
index 00689575..fa264e37 100644
--- a/src/gui/widgets/resizegrip.cpp
+++ b/src/gui/widgets/resizegrip.cpp
@@ -19,10 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "resizegrip.h"
-
#include <guichan/graphics.hpp>
+#include "resizegrip.h"
+
+#include "../../configuration.h"
#include "../../graphics.h"
#include "../../resources/image.h"
@@ -30,14 +31,16 @@
Image *ResizeGrip::gripImage = 0;
int ResizeGrip::mInstances = 0;
+float ResizeGrip::mAlpha = config.getValue("guialpha", 0.8);
-ResizeGrip::ResizeGrip()
+ResizeGrip::ResizeGrip(std::string image)
{
if (mInstances == 0)
{
// Load the grip image
ResourceManager *resman = ResourceManager::getInstance();
- gripImage = resman->getImage("graphics/gui/resize.png");
+ gripImage = resman->getImage(image);
+ gripImage->setAlpha(mAlpha);
}
mInstances++;
@@ -56,8 +59,13 @@ ResizeGrip::~ResizeGrip()
}
}
-void
-ResizeGrip::draw(gcn::Graphics *graphics)
+void ResizeGrip::draw(gcn::Graphics *graphics)
{
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ gripImage->setAlpha(mAlpha);
+ }
+
static_cast<Graphics*>(graphics)->drawImage(gripImage, 0, 0);
}
diff --git a/src/gui/widgets/resizegrip.h b/src/gui/widgets/resizegrip.h
index 5c6ea4bd..620c133f 100644
--- a/src/gui/widgets/resizegrip.h
+++ b/src/gui/widgets/resizegrip.h
@@ -39,7 +39,7 @@ class ResizeGrip : public gcn::Widget
/**
* Constructor.
*/
- ResizeGrip();
+ ResizeGrip(std::string image = "graphics/gui/resize.png");
/**
* Destructor.
@@ -54,6 +54,7 @@ class ResizeGrip : public gcn::Widget
private:
static Image *gripImage; /**< Resize grip image */
static int mInstances; /**< Number of resize grip instances */
+ static float mAlpha;
};
#endif
diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp
index c54b2390..21402c89 100644
--- a/src/gui/widgets/tab.cpp
+++ b/src/gui/widgets/tab.cpp
@@ -19,12 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <algorithm>
+#include <guichan/widgets/label.hpp>
#include "tab.h"
-
#include "tabbedarea.h"
+#include "../../configuration.h"
#include "../../graphics.h"
#include "../../resources/image.h"
@@ -33,6 +33,7 @@
#include "../../utils/dtor.h"
int Tab::mInstances = 0;
+float Tab::mAlpha = config.getValue("guialpha", 0.8);
enum{
TAB_STANDARD, // 0
@@ -50,10 +51,10 @@ struct TabData
};
static TabData const data[TAB_COUNT] = {
- {"graphics/gui/tab.png", 0, 0},
- {"graphics/gui/tab.png", 9, 4},
- {"graphics/gui/tabselected.png", 16, 19},
- {"graphics/gui/tab.png", 25, 23}
+ { "graphics/gui/tab.png", 0, 0 },
+ { "graphics/gui/tab.png", 9, 4 },
+ { "graphics/gui/tabselected.png", 16, 19 },
+ { "graphics/gui/tab.png", 25, 23 }
};
ImageRect Tab::tabImg[TAB_COUNT];
@@ -79,6 +80,7 @@ Tab::~Tab()
void Tab::init()
{
setFrameSize(0);
+ mHighlighted = false;
if (mInstances == 0)
{
@@ -98,6 +100,7 @@ void Tab::init()
data[x].gridX, data[y].gridY,
data[x + 1].gridX - data[x].gridX + 1,
data[y + 1].gridY - data[y].gridY + 1);
+ tabImg[mode].grid[a]->setAlpha(mAlpha);
a++;
}
}
@@ -109,16 +112,33 @@ void Tab::init()
void Tab::draw(gcn::Graphics *graphics)
{
- int mode;
+ int mode = TAB_STANDARD;
// check which type of tab to draw
- if (mTabbedArea && mTabbedArea->isTabSelected(this))
+ if (mTabbedArea)
{
- mode = TAB_SELECTED;
+ if (mTabbedArea->isTabSelected(this))
+ {
+ mode = TAB_SELECTED;
+ // if tab is selected, it doesnt need to highlight activity
+ mLabel->setForegroundColor(gcn::Color(0, 0, 0));
+ mHighlighted = false;
+ }
+ else if (mHighlighted)
+ {
+ mode = TAB_HIGHLIGHTED;
+ mLabel->setForegroundColor(gcn::Color(255, 0, 0));
+ }
}
- else
+
+ if (config.getValue("guialpha", 0.8) != mAlpha)
{
- mode = TAB_STANDARD;
+ mAlpha = config.getValue("guialpha", 0.8);
+ for (int a = 0; a < 9; a++)
+ {
+ tabImg[TAB_SELECTED].grid[a]->setAlpha(mAlpha);
+ tabImg[TAB_STANDARD].grid[a]->setAlpha(mAlpha);
+ }
}
// draw tab
@@ -128,3 +148,8 @@ void Tab::draw(gcn::Graphics *graphics)
// draw label
drawChildren(graphics);
}
+
+void Tab::setHighlighted(bool high)
+{
+ mHighlighted = high;
+}
diff --git a/src/gui/widgets/tab.h b/src/gui/widgets/tab.h
index 8382df83..3af4e2bf 100644
--- a/src/gui/widgets/tab.h
+++ b/src/gui/widgets/tab.h
@@ -47,12 +47,20 @@ class Tab : public gcn::Tab
*/
void draw(gcn::Graphics *graphics);
+ /**
+ * Set tab highlighted
+ */
+ void setHighlighted(bool high);
+
private:
/** Load images if no other instances exist yet */
void init();
static ImageRect tabImg[4]; /**< Tab state graphics */
static int mInstances; /**< Number of tab instances */
+ static float mAlpha;
+
+ bool mHighlighted;
};
#endif
diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp
index c4e22bff..5ff7c4bc 100644
--- a/src/gui/widgets/tabbedarea.cpp
+++ b/src/gui/widgets/tabbedarea.cpp
@@ -90,7 +90,7 @@ void TabbedArea::addTab(Tab *tab, gcn::Widget *widget)
mTabContainer->add(tab);
mTabs.push_back(std::pair<Tab*, gcn::Widget*>(tab, widget));
- if (mSelectedTab == NULL)
+ if (!mSelectedTab)
{
setSelectedTab(tab);
}
diff --git a/src/gui/window.cpp b/src/gui/window.cpp
index ed5bb8fc..797b4be9 100644
--- a/src/gui/window.cpp
+++ b/src/gui/window.cpp
@@ -24,11 +24,9 @@
#include <climits>
#include <guichan/exception.hpp>
-#include <guichan/widgets/icon.hpp>
-
-#include "window.h"
#include "gui.h"
+#include "window.h"
#include "windowcontainer.h"
#include "widgets/layout.h"
@@ -36,30 +34,30 @@
#include "../configlistener.h"
#include "../configuration.h"
-#include "../graphics.h"
#include "../log.h"
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
+#include "../utils/xml.h"
+
ConfigListener *Window::windowConfigListener = 0;
WindowContainer *Window::windowContainer = 0;
int Window::instances = 0;
int Window::mouseResize = 0;
-ImageRect Window::border;
+//ImageRect Window::border;
Image *Window::closeImage = NULL;
+bool Window::mAlphaChanged = false;
class WindowConfigListener : public ConfigListener
{
void optionChanged(const std::string &)
{
- for_each(Window::border.grid, Window::border.grid + 9,
- std::bind2nd(std::mem_fun(&Image::setAlpha),
- config.getValue("guialpha", 0.8)));
+ Window::mAlphaChanged = true;
}
};
-Window::Window(const std::string& caption, bool modal, Window *parent):
+Window::Window(const std::string& caption, bool modal, Window *parent, const std::string& skin):
gcn::Window(caption),
mGrip(0),
mParent(parent),
@@ -72,31 +70,23 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
mMinWinWidth(100),
mMinWinHeight(40),
mMaxWinWidth(INT_MAX),
- mMaxWinHeight(INT_MAX)
+ mMaxWinHeight(INT_MAX),
+ mSkin(skin)
{
logger->log("Window::Window(\"%s\")", caption.c_str());
- if (!windowContainer) {
+ if (!windowContainer)
+ {
throw GCN_EXCEPTION("Window::Window(): no windowContainer set");
}
+ // Loads the skin
+ loadSkin(mSkin);
+
+ setGuiAlpha();
+
if (instances == 0)
{
- // Load static resources
- ResourceManager *resman = ResourceManager::getInstance();
- Image *dBorders = resman->getImage("graphics/gui/vscroll_grey.png");
- border.grid[0] = dBorders->getSubImage(0, 0, 4, 4);
- border.grid[1] = dBorders->getSubImage(4, 0, 3, 4);
- border.grid[2] = dBorders->getSubImage(7, 0, 4, 4);
- border.grid[3] = dBorders->getSubImage(0, 4, 4, 10);
- border.grid[4] = resman->getImage("graphics/gui/bg_quad_dis.png");
- border.grid[5] = dBorders->getSubImage(7, 4, 4, 10);
- border.grid[6] = dBorders->getSubImage(0, 15, 4, 4);
- border.grid[7] = dBorders->getSubImage(4, 15, 3, 4);
- border.grid[8] = dBorders->getSubImage(7, 15, 4, 4);
- dBorders->decRef();
- closeImage = resman->getImage("graphics/gui/close_button.png");
-
windowConfigListener = new WindowConfigListener();
// Send GUI alpha changed for initialization
windowConfigListener->optionChanged("guialpha");
@@ -130,12 +120,14 @@ Window::~Window()
const std::string &name = mWindowName;
// Saving X, Y and Width and Height for resizables in the config
- if (!name.empty()) {
+ if (!name.empty())
+ {
config.setValue(name + "WinX", getX());
config.setValue(name + "WinY", getY());
config.setValue(name + "Visible", isVisible());
- if (mGrip) {
+ if (mGrip)
+ {
config.setValue(name + "WinWidth", getWidth());
config.setValue(name + "WinHeight", getHeight());
}
@@ -152,22 +144,19 @@ Window::~Window()
instances--;
+ // Clean up static resources
+ for (int i = 0; i < 9; i++)
+ {
+ delete border.grid[i];
+ border.grid[i] = NULL;
+ }
+
if (instances == 0)
{
config.removeListener("guialpha", windowConfigListener);
delete windowConfigListener;
windowConfigListener = NULL;
- // Clean up static resources
- delete border.grid[0];
- delete border.grid[1];
- delete border.grid[2];
- delete border.grid[3];
- border.grid[4]->decRef();
- delete border.grid[5];
- delete border.grid[6];
- delete border.grid[7];
- delete border.grid[8];
closeImage->decRef();
}
}
@@ -199,6 +188,15 @@ void Window::draw(gcn::Graphics *graphics)
getPadding()
);
}
+
+ // Update window alpha values
+ if (mAlphaChanged)
+ {
+ for_each(border.grid, border.grid + 9,
+ std::bind2nd(std::mem_fun(&Image::setAlpha),
+ config.getValue("guialpha", 0.8)));
+ closeImage->setAlpha(config.getValue("guialpha", 0.8));
+ }
drawChildren(graphics);
}
@@ -524,6 +522,187 @@ int Window::getResizeHandles(gcn::MouseEvent &event)
return resizeHandles;
}
+void Window::setGuiAlpha()
+{
+ //logger->log("Window::setGuiAlpha: Alpha Value %f", config.getValue("guialpha", 0.8));
+ for (int i = 0; i < 9; i++)
+ {
+ //logger->log("Window::setGuiAlpha: Border Image (%i)", i);
+ border.grid[i]->setAlpha(config.getValue("guialpha", 0.8));
+ }
+
+ mAlphaChanged = false;
+}
+
+void Window::loadSkin(const std::string &filename)
+{
+ const std::string windowId = Window::getId();
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ logger->log("Loading Window Skin '%s'.", filename.c_str());
+ logger->log("Loading Window ID '%s'.", windowId.c_str());
+
+
+ if (filename.empty())
+ logger->error("Window::loadSkin(): Invalid File Name.");
+
+ // TODO:
+ // If there is an error loading the specified file, we should try to revert
+ // to a 'default' skin file. Only if the 'default' skin file can't be loaded
+ // should we have a terminating error.
+ XML::Document doc(filename);
+ xmlNodePtr rootNode = doc.rootNode();
+
+ if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "skinset"))
+ {
+ logger->error("Widget Skinning error");
+ }
+
+ std::string skinSetImage;
+ skinSetImage = XML::getProperty(rootNode, "image", "");
+ Image *dBorders = NULL;
+ if (!skinSetImage.empty())
+ {
+ logger->log("Window::loadSkin(): <skinset> defines '%s' as a skin image.", skinSetImage.c_str());
+ dBorders = resman->getImage("graphics/gui/" + skinSetImage);//"graphics/gui/speech_bubble.png");
+ }
+ else
+ {
+ logger->error("Window::loadSkin(): Skinset does not define an image!");
+ }
+
+ //iterate <widget>'s
+ for_each_xml_child_node(widgetNode, rootNode)
+ {
+ if (!xmlStrEqual(widgetNode->name, BAD_CAST "widget"))
+ continue;
+
+ std::string widgetType;
+ widgetType = XML::getProperty(widgetNode, "type", "unknown");
+ if (widgetType == "Window")
+ {
+ // Iterate through <part>'s
+ // LEEOR / TODO:
+ // We need to make provisions to load in a CloseButton image. For now it
+ // can just be hard-coded.
+ for_each_xml_child_node(partNode, widgetNode)
+ {
+ if (!xmlStrEqual(partNode->name, BAD_CAST "part"))
+ {
+ continue;
+ }
+
+ std::string partType;
+ partType = XML::getProperty(partNode, "type", "unknown");
+ // TOP ROW
+ if (partType == "top-left-corner")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[0] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if (partType == "top-edge")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[1] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if (partType == "top-right-corner")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[2] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+
+ // MIDDLE ROW
+ else if (partType == "left-edge")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[3] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if (partType == "bg-quad")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[4] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if (partType == "right-edge")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[5] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+
+ // BOTTOM ROW
+ else if (partType == "bottom-left-corner")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[6] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if (partType == "bottom-edge")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[7] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if (partType == "bottom-right-corner")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[8] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+
+ // Part is of an uknown type.
+ else
+ {
+ logger->log("Window::loadSkin(): Unknown Part Type '%s'", partType.c_str());
+ }
+ }
+ }
+ // Widget is of an uknown type.
+ else
+ {
+ logger->log("Window::loadSkin(): Unknown Widget Type '%s'", widgetType.c_str());
+ }
+ }
+ dBorders->decRef();
+
+ logger->log("Finished loading Window Skin.");
+
+ // Hard-coded for now until we update the above code to look for window buttons.
+ closeImage = resman->getImage("graphics/gui/close_button.png");
+}
+
Layout &Window::getLayout()
{
if (!mLayout) mLayout = new Layout;
diff --git a/src/gui/window.h b/src/gui/window.h
index 19d59c26..518de6e9 100644
--- a/src/gui/window.h
+++ b/src/gui/window.h
@@ -22,9 +22,11 @@
#ifndef WINDOW_H
#define WINDOW_H
-#include <guichan/widgets/window.hpp>
#include <guichan/widgetlistener.hpp>
+#include <guichan/widgets/window.hpp>
+
+#include "../graphics.h"
#include "../guichanfwd.h"
class ConfigListener;
@@ -56,9 +58,10 @@ class Window : public gcn::Window, gcn::WidgetListener
* @param parent The parent window. This is the window standing above
* this one in the window hiearchy. When reordering,
* a window will never go below its parent window.
+ * @param skin The location where the window's skin XML can be found.
*/
Window(const std::string &caption = "Window", bool modal = false,
- Window *parent = NULL);
+ Window *parent = NULL, const std::string &skin = "graphics/gui/gui.xml");
/**
* Destructor. Deletes all the added widgets.
@@ -126,6 +129,26 @@ class Window : public gcn::Window, gcn::WidgetListener
void setMaxHeight(unsigned int height);
/**
+ * Gets the minimum width of the window.
+ */
+ int getMinWidth() { return mMinWinWidth; }
+
+ /**
+ * Gets the minimum height of the window.
+ */
+ int getMinHeight() { return mMinWinHeight; }
+
+ /**
+ * Gets the maximum width of the window.
+ */
+ int getMaxWidth() { return mMaxWinWidth; }
+
+ /**
+ * Gets the minimum height of the window.
+ */
+ int getMaxHeight() { return mMaxWinHeight; }
+
+ /**
* Sets flag to show a title or not.
*/
void setShowTitle(bool flag)
@@ -238,6 +261,11 @@ class Window : public gcn::Window, gcn::WidgetListener
void reflowLayout(int w = 0, int h = 0);
/**
+ * Loads a window skin
+ */
+ void loadSkin(const std::string &filename);
+
+ /**
* Adds a widget to the window and sets it at given cell.
*/
LayoutCell &place(int x, int y, gcn::Widget *, int w = 1, int h = 1);
@@ -269,6 +297,8 @@ class Window : public gcn::Window, gcn::WidgetListener
*/
int getResizeHandles(gcn::MouseEvent &event);
+ void setGuiAlpha();
+
ResizeGrip *mGrip; /**< Resize grip */
Window *mParent; /**< The parent window */
Layout *mLayout; /**< Layout handler */
@@ -277,6 +307,7 @@ class Window : public gcn::Window, gcn::WidgetListener
bool mModal; /**< Window is modal */
bool mCloseButton; /**< Window has a close button */
bool mSticky; /**< Window resists minimization */
+ static bool mAlphaChanged; /**< Whether the alpha percent was changed */
int mMinWinWidth; /**< Minimum window width */
int mMinWinHeight; /**< Minimum window height */
int mMaxWinWidth; /**< Maximum window width */
@@ -285,6 +316,7 @@ class Window : public gcn::Window, gcn::WidgetListener
int mDefaultY; /**< Default window Y position */
int mDefaultWidth; /**< Default window width */
int mDefaultHeight; /**< Default window height */
+ std::string mSkin; /**< Name of the skin to use */
/**
* The config listener that listens to changes relevant to all windows.
@@ -293,7 +325,7 @@ class Window : public gcn::Window, gcn::WidgetListener
static int mouseResize; /**< Active resize handles */
static int instances; /**< Number of Window instances */
- static ImageRect border; /**< The window border and background */
+ ImageRect border; /**< The window border and background */
static Image *closeImage; /**< Close Button Image */
/**
diff --git a/src/gui/windowcontainer.h b/src/gui/windowcontainer.h
index a25f2037..62704d1b 100644
--- a/src/gui/windowcontainer.h
+++ b/src/gui/windowcontainer.h
@@ -30,7 +30,8 @@
*
* \ingroup GUI
*/
-class WindowContainer : public gcn::Container {
+class WindowContainer : public gcn::Container
+{
public:
/**
* Do GUI logic. This functions adds automatic deletion of objects that
diff --git a/src/guichanfwd.h b/src/guichanfwd.h
index 2e97db68..4863421c 100644
--- a/src/guichanfwd.h
+++ b/src/guichanfwd.h
@@ -22,7 +22,8 @@
#ifndef GUICHANFWD_H
#define GUICHANFWD_H
-namespace gcn {
+namespace gcn
+{
class ActionListener;
class AllegroGraphics;
class AllegroImage;
diff --git a/src/imageparticle.cpp b/src/imageparticle.cpp
index 845cf258..557b3553 100644
--- a/src/imageparticle.cpp
+++ b/src/imageparticle.cpp
@@ -19,9 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "imageparticle.h"
-
#include "graphics.h"
+#include "imageparticle.h"
#include "resources/image.h"
diff --git a/src/inventory.cpp b/src/inventory.cpp
index 7b9ec07c..3ca26e1e 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -19,30 +19,30 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "inventory.h"
-
#include <algorithm>
-#include <cassert>
+#include "inventory.h"
#include "item.h"
#include "log.h"
struct SlotUsed : public std::unary_function<Item*, bool>
{
- bool operator()(const Item *item) const {
+ bool operator()(const Item *item) const
+ {
return item && item->getId() != -1 && item->getQuantity() > 0;
}
};
-Inventory::Inventory()
+Inventory::Inventory(int size):
+ mSize(size)
{
- mItems = new Item*[INVENTORY_SIZE];
- std::fill_n(mItems, INVENTORY_SIZE, (Item*) 0);
+ mItems = new Item*[mSize];
+ std::fill_n(mItems, mSize, (Item*) 0);
}
Inventory::~Inventory()
{
- for (int i = 0; i < INVENTORY_SIZE; i++)
+ for (int i = 0; i < mSize; i++)
delete mItems[i];
delete [] mItems;
@@ -58,11 +58,10 @@ Item* Inventory::getItem(int index) const
Item* Inventory::findItem(int itemId) const
{
- for (int i = 0; i < INVENTORY_SIZE; i++)
- {
+ for (int i = 0; i < mSize; i++)
if (mItems[i] && mItems[i]->getId() == itemId)
return mItems[i];
- }
+
return NULL;
}
@@ -73,46 +72,41 @@ void Inventory::addItem(int id, int quantity, bool equipment)
void Inventory::setItem(int index, int id, int quantity, bool equipment)
{
- if (index < 0 || index >= INVENTORY_SIZE) {
+ if (index < 0 || index >= mSize)
+ {
logger->log("Warning: invalid inventory index: %d", index);
return;
}
- /* TODO: Check where to reenable this code.
- // Dont stack equipment other than arrows.
- if (equipment && !(id == 1199 || id == 529))
- mItems[index].setQuantity(quantity);
- else
- mItems[index].increaseQuantity(quantity);
- */
-
- if (!mItems[index] && id > 0) {
+ if (!mItems[index] && id > 0)
+ {
Item *item = new Item(id, quantity, equipment);
item->setInvIndex(index);
mItems[index] = item;
- } else if (id > 0) {
+ }
+ else if (id > 0)
+ {
mItems[index]->setId(id);
mItems[index]->setQuantity(quantity);
mItems[index]->setEquipment(equipment);
- } else if (mItems[index]) {
+ }
+ else if (mItems[index])
+ {
removeItemAt(index);
}
}
void Inventory::clear()
{
- for (int i = 0; i < INVENTORY_SIZE; i++) {
+ for (int i = 0; i < mSize; i++)
removeItemAt(i);
- }
}
void Inventory::removeItem(int id)
{
- for (int i = 0; i < INVENTORY_SIZE; i++) {
- if (mItems[i] && mItems[i]->getId() == id) {
+ for (int i = 0; i < mSize; i++)
+ if (mItems[i] && mItems[i]->getId() == id)
removeItemAt(i);
- }
- }
}
void Inventory::removeItemAt(int index)
@@ -123,34 +117,30 @@ void Inventory::removeItemAt(int index)
bool Inventory::contains(Item *item) const
{
- for (int i = 0; i < INVENTORY_SIZE; i++) {
- if (mItems[i] && mItems[i]->getId() == item->getId()) {
+ for (int i = 0; i < mSize; i++)
+ if (mItems[i] && mItems[i]->getId() == item->getId())
return true;
- }
- }
return false;
}
int Inventory::getFreeSlot() const
{
- Item **i = std::find_if(mItems + 2, mItems + INVENTORY_SIZE,
+ Item **i = std::find_if(mItems + 2, mItems + mSize,
std::not1(SlotUsed()));
- return (i == mItems + INVENTORY_SIZE) ? -1 : (i - mItems);
+ return (i == mItems + mSize) ? -1 : (i - mItems);
}
int Inventory::getNumberOfSlotsUsed() const
{
- return count_if(mItems, mItems + INVENTORY_SIZE, SlotUsed());
+ return count_if(mItems, mItems + mSize, SlotUsed());
}
int Inventory::getLastUsedSlot() const
{
- for (int i = INVENTORY_SIZE - 1; i >= 0; i--) {
- if (SlotUsed()(mItems[i])) {
+ for (int i = mSize - 1; i >= 0; i--)
+ if (SlotUsed()(mItems[i]))
return i;
- }
- }
return -1;
}
diff --git a/src/inventory.h b/src/inventory.h
index 1d2ba296..2c5d99e3 100644
--- a/src/inventory.h
+++ b/src/inventory.h
@@ -32,7 +32,7 @@ class Inventory
/**
* Constructor.
*/
- Inventory();
+ Inventory(int size);
/**
* Destructor.
@@ -40,6 +40,11 @@ class Inventory
~Inventory();
/**
+ * Returns the size that this instance is configured for
+ */
+ int getSize() { return mSize; }
+
+ /**
* Returns the item at the specified index.
*/
Item* getItem(int index) const;
@@ -104,6 +109,7 @@ class Inventory
protected:
Item **mItems; /**< The holder of items */
+ int mSize; /**< The max number of inventory items */
};
#endif
diff --git a/src/item.h b/src/item.h
index b663880c..3ea4a905 100644
--- a/src/item.h
+++ b/src/item.h
@@ -46,14 +46,12 @@ class Item
/**
* Sets the item id, identifying the item type.
*/
- void
- setId(int id);
+ void setId(int id);
/**
* Returns the item id.
*/
- int
- getId() const { return mId; }
+ int getId() const { return mId; }
/**
* Returns the item image.
@@ -63,62 +61,52 @@ class Item
/**
* Sets the number of items.
*/
- void
- setQuantity(int quantity) { mQuantity = quantity; }
+ void setQuantity(int quantity) { mQuantity = quantity; }
/**
* Increases the number of items by the given amount.
*/
- void
- increaseQuantity(int amount) { mQuantity += amount; }
+ void increaseQuantity(int amount) { mQuantity += amount; }
/**
* Returns the number of items.
*/
- int
- getQuantity() const { return mQuantity; }
+ int getQuantity() const { return mQuantity; }
/**
* Sets whether this item is considered equipment.
*/
- void
- setEquipment(bool equipment) { mEquipment = equipment; }
+ void setEquipment(bool equipment) { mEquipment = equipment; }
/**
* Returns whether this item is considered equipment.
*/
- bool
- isEquipment() const { return mEquipment; }
+ bool isEquipment() const { return mEquipment; }
/**
* Sets whether this item is equipped.
*/
- void
- setEquipped(bool equipped) { mEquipped = equipped; }
+ void setEquipped(bool equipped) { mEquipped = equipped; }
/**
* Returns whether this item is equipped.
*/
- bool
- isEquipped() const { return mEquipped; }
+ bool isEquipped() const { return mEquipped; }
/**
* Sets the inventory index of this item.
*/
- void
- setInvIndex(int index) { mInvIndex = index; }
+ void setInvIndex(int index) { mInvIndex = index; }
/**
* Returns the inventory index of this item.
*/
- int
- getInvIndex() const { return mInvIndex; }
+ int getInvIndex() const { return mInvIndex; }
/**
* Returns information about this item type.
*/
- const ItemInfo&
- getInfo() const { return ItemDB::get(mId); }
+ const ItemInfo& getInfo() const { return ItemDB::get(mId); }
protected:
int mId; /**< Item type id. */
diff --git a/src/itemshortcut.cpp b/src/itemshortcut.cpp
index ee887c73..3404b0e3 100644
--- a/src/itemshortcut.cpp
+++ b/src/itemshortcut.cpp
@@ -19,11 +19,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "itemshortcut.h"
-
#include "configuration.h"
#include "inventory.h"
#include "item.h"
+#include "itemshortcut.h"
#include "localplayer.h"
#include "utils/tostring.h"
@@ -34,9 +33,8 @@ ItemShortcut::ItemShortcut():
mItemSelected(-1)
{
for (int i = 0; i < SHORTCUT_ITEMS; i++)
- {
mItems[i] = -1;
- }
+
load();
}
@@ -52,9 +50,7 @@ void ItemShortcut::load()
int itemId = (int) config.getValue("shortcut" + toString(i), -1);
if (itemId != -1)
- {
mItems[i] = itemId;
- }
}
}
@@ -74,13 +70,15 @@ void ItemShortcut::useItem(int index)
Item *item = player_node->getInventory()->findItem(mItems[index]);
if (item && item->getQuantity())
{
- if (item->isEquipment()) {
- if (item->isEquipped()) {
+ if (item->isEquipment())
+ {
+ if (item->isEquipped())
player_node->unequipItem(item);
- } else {
+ else
player_node->equipItem(item);
- }
- } else {
+ }
+ else
+ {
player_node->useItem(item);
}
}
diff --git a/src/itemshortcut.h b/src/itemshortcut.h
index bc3f32ca..95e17f44 100644
--- a/src/itemshortcut.h
+++ b/src/itemshortcut.h
@@ -22,7 +22,7 @@
#ifndef ITEMSHORTCUT_H
#define ITEMSHORTCUT_H
-#define SHORTCUT_ITEMS 10
+#define SHORTCUT_ITEMS 12
class Item;
diff --git a/src/joystick.cpp b/src/joystick.cpp
index 6874e9cd..7e9a2285 100644
--- a/src/joystick.cpp
+++ b/src/joystick.cpp
@@ -19,13 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "joystick.h"
+#include <cassert>
#include "configuration.h"
+#include "joystick.h"
#include "log.h"
-#include <cassert>
-
int Joystick::joystickCount = 0;
void Joystick::init()
diff --git a/src/joystick.h b/src/joystick.h
index aebd4b5f..4c5390c2 100644
--- a/src/joystick.h
+++ b/src/joystick.h
@@ -30,12 +30,16 @@ class Joystick
/**
* Number of buttons we can handle.
*/
- enum { MAX_BUTTONS = 6 };
+ enum
+ {
+ MAX_BUTTONS = 6
+ };
/**
* Directions, to be used as bitmask values.
*/
- enum {
+ enum
+ {
UP = 1,
DOWN = 2,
LEFT = 4,
diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp
index 9ae7ed68..5a0c0678 100644
--- a/src/keyboardconfig.cpp
+++ b/src/keyboardconfig.cpp
@@ -1,6 +1,6 @@
/*
- * The Mana World
- * Copyright (C) 2007 The Mana World Development Team
+ * Custom keyboard shortcuts configuration
+ * Copyright (C) 2007 Joshua Langley <joshlangley@optusnet.com.au>
*
* This file is part of The Mana World.
*
@@ -19,52 +19,83 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "keyboardconfig.h"
#include "configuration.h"
+#include "keyboardconfig.h"
#include "log.h"
+#include "gui/sdlinput.h"
#include "gui/setup_keyboard.h"
+#include "utils/gettext.h"
+#include "utils/strprintf.h"
+
struct KeyData
{
const char *configField;
int defaultValue;
- const char *caption;
+ std::string caption;
};
// keyData must be in same order as enum keyAction.
static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = {
- {"keyMoveUp", SDLK_UP, "Move Up"},
- {"keyMoveDown", SDLK_DOWN, "Move Down"},
- {"keyMoveLeft", SDLK_LEFT, "Move Left"},
- {"keyMoveRight", SDLK_RIGHT, "Move Right"},
- {"keyAttack", SDLK_LCTRL, "Attack"},
- {"keySmilie", SDLK_LALT, "Smilie"},
- {"keyTarget", SDLK_LSHIFT, "Target"},
- {"keyTargetClosest", SDLK_a, "Target Closest"},
- {"keyTargetPlayer", SDLK_q, "Target Player"},
- {"keyPickup", SDLK_z, "Pickup"},
- {"keyHideWindows", SDLK_h, "Hide Windows"},
- {"keyBeingSit", SDLK_s, "Sit"},
- {"keyShortcut0", SDLK_0, "Item Shortcut 0"},
- {"keyShortcut1", SDLK_1, "Item Shortcut 1"},
- {"keyShortcut2", SDLK_2, "Item Shortcut 2"},
- {"keyShortcut3", SDLK_3, "Item Shortcut 3"},
- {"keyShortcut4", SDLK_4, "Item Shortcut 4"},
- {"keyShortcut5", SDLK_5, "Item Shortcut 5"},
- {"keyShortcut6", SDLK_6, "Item Shortcut 6"},
- {"keyShortcut7", SDLK_7, "Item Shortcut 7"},
- {"keyShortcut8", SDLK_8, "Item Shortcut 8"},
- {"keyShortcut9", SDLK_9, "Item Shortcut 9"},
- {"keyWindowStatus", SDLK_F2, "Status Window"},
- {"keyWindowInventory", SDLK_F3, "Inventory Window"},
- {"keyWindowEquipment", SDLK_F4, "Equipment WIndow"},
- {"keyWindowSkill", SDLK_F5, "Skill Window"},
- {"keyWindowMinimap", SDLK_F6, "Minimap Window"},
- {"keyWindowChat", SDLK_F7, "Chat Window"},
- {"keyWindowShortcut", SDLK_F8, "Item Shortcut Window"},
- {"keyWindowSetup", SDLK_F9, "Setup Window"},
- {"keyWindowDebug", SDLK_F10, "Debug Window"}
+ {"keyMoveUp", SDLK_UP, _("Move Up")},
+ {"keyMoveDown", SDLK_DOWN, _("Move Down")},
+ {"keyMoveLeft", SDLK_LEFT, _("Move Left")},
+ {"keyMoveRight", SDLK_RIGHT, _("Move Right")},
+ {"keyAttack", SDLK_LCTRL, _("Attack")},
+ {"keySmilie", SDLK_LALT, _("Smilie")},
+ {"keyTalk", SDLK_t, _("Talk")},
+ {"keyTarget", SDLK_LSHIFT, _("Stop Attack")},
+ {"keyTargetClosest", SDLK_a, _("Target Closest")},
+ {"keyTargetNPC", SDLK_n, _("Target NPC")},
+ {"keyTargetPlayer", SDLK_q, _("Target Player")},
+ {"keyPickup", SDLK_z, _("Pickup")},
+ {"keyHideWindows", SDLK_h, _("Hide Windows")},
+ {"keyBeingSit", SDLK_s, _("Sit")},
+ {"keyScreenshot", SDLK_p, _("Screenshot")},
+ {"keyTrade", SDLK_r, _("Enable/Disable Trading")},
+ {"keyPathfind", SDLK_f, _("Find Path to Mouse")},
+ {"keyShortcut1", SDLK_1, strprintf(_("Item Shortcut %d"), 1)},
+ {"keyShortcut2", SDLK_2, strprintf(_("Item Shortcut %d"), 2)},
+ {"keyShortcut3", SDLK_3, strprintf(_("Item Shortcut %d"), 3)},
+ {"keyShortcut4", SDLK_4, strprintf(_("Item Shortcut %d"), 4)},
+ {"keyShortcut5", SDLK_5, strprintf(_("Item Shortcut %d"), 5)},
+ {"keyShortcut6", SDLK_6, strprintf(_("Item Shortcut %d"), 6)},
+ {"keyShortcut7", SDLK_7, strprintf(_("Item Shortcut %d"), 7)},
+ {"keyShortcut8", SDLK_8, strprintf(_("Item Shortcut %d"), 8)},
+ {"keyShortcut9", SDLK_9, strprintf(_("Item Shortcut %d"), 9)},
+ {"keyShortcut10", SDLK_0, strprintf(_("Item Shortcut %d"), 10)},
+ {"keyShortcut11", SDLK_MINUS, strprintf(_("Item Shortcut %d"), 11)},
+ {"keyShortcut12", SDLK_EQUALS, strprintf(_("Item Shortcut %d"), 12)},
+ {"keyWindowHelp", SDLK_F1, _("Help Window")},
+ {"keyWindowStatus", SDLK_F2, _("Status Window")},
+ {"keyWindowInventory", SDLK_F3, _("Inventory Window")},
+ {"keyWindowEquipment", SDLK_F4, _("Equipment WIndow")},
+ {"keyWindowSkill", SDLK_F5, _("Skill Window")},
+ {"keyWindowMinimap", SDLK_F6, _("Minimap Window")},
+ {"keyWindowChat", SDLK_F7, _("Chat Window")},
+ {"keyWindowShortcut", SDLK_F8, _("Item Shortcut Window")},
+ {"keyWindowSetup", SDLK_F9, _("Setup Window")},
+ {"keyWindowDebug", SDLK_F10, _("Debug Window")},
+ {"keyWindowEmote", SDLK_F11, _("Emote Window")},
+ {"keyWindowEmoteBar", SDLK_F12, _("Emote Shortcut Window")},
+ {"keyEmoteShortcut1", SDLK_1, strprintf(_("Emote Shortcut %d"), 1)},
+ {"keyEmoteShortcut2", SDLK_2, strprintf(_("Emote Shortcut %d"), 2)},
+ {"keyEmoteShortcut3", SDLK_3, strprintf(_("Emote Shortcut %d"), 3)},
+ {"keyEmoteShortcut4", SDLK_4, strprintf(_("Emote Shortcut %d"), 4)},
+ {"keyEmoteShortcut5", SDLK_5, strprintf(_("Emote Shortcut %d"), 5)},
+ {"keyEmoteShortcut6", SDLK_6, strprintf(_("Emote Shortcut %d"), 6)},
+ {"keyEmoteShortcut7", SDLK_7, strprintf(_("Emote Shortcut %d"), 7)},
+ {"keyEmoteShortcut8", SDLK_8, strprintf(_("Emote Shortcut %d"), 8)},
+ {"keyEmoteShortcut9", SDLK_9, strprintf(_("Emote Shortcut %d"), 9)},
+ {"keyEmoteShortcut10", SDLK_0, strprintf(_("Emote Shortcut %d"), 10)},
+ {"keyEmoteShortcut11", SDLK_MINUS, strprintf(_("Emote Shortcut %d"), 11)},
+ {"keyEmoteShortcut12", SDLK_EQUALS, strprintf(_("Emote Shortcut %d"), 12)},
+ {"keyChat", SDLK_RETURN, _("Toggle Chat")},
+ {"keyChatScrollUp", SDLK_PAGEUP, _("Scroll Chat Up")},
+ {"keyChatScrollDown", SDLK_PAGEDOWN, _("Scroll Chat Down")},
+ {"keyOK", SDLK_RETURN, _("Select OK")},
+ {"keyQuit", SDLK_ESCAPE, _("Quit")}
};
void KeyboardConfig::init()
@@ -110,11 +141,20 @@ void KeyboardConfig::makeDefault()
bool KeyboardConfig::hasConflicts()
{
int i, j;
+ /**
+ * No need to parse the square matrix: only check one triangle
+ * that's enough to detect conflicts
+ */
for (i = 0; i < KEY_TOTAL; i++)
{
- for (j = 0; j < KEY_TOTAL; j++)
+ for (j = i, j++; j < KEY_TOTAL; j++)
{
- if (i != j && mKey[i].value == mKey[j].value)
+ // Allow for item shortcut and emote keys to overlap, but no other keys
+ if (!((((i >= KEY_SHORTCUT_1) && (i <= KEY_SHORTCUT_12)) &&
+ ((j >= KEY_EMOTE_1) && (j <= KEY_EMOTE_12))) ||
+ ((i == KEY_TOGGLE_CHAT) && (j == KEY_OK))) &&
+ (mKey[i].value == mKey[j].value)
+ )
{
return true;
}
@@ -132,7 +172,7 @@ int KeyboardConfig::getKeyIndex(int keyValue) const
{
for (int i = 0; i < KEY_TOTAL; i++)
{
- if(keyValue == mKey[i].value)
+ if (keyValue == mKey[i].value)
{
return i;
}
@@ -140,6 +180,19 @@ int KeyboardConfig::getKeyIndex(int keyValue) const
return KEY_NO_VALUE;
}
+
+int KeyboardConfig::getKeyEmoteOffset(int keyValue) const
+{
+ for (int i = KEY_EMOTE_1; i <= KEY_EMOTE_12; i++)
+ {
+ if (keyValue == mKey[i].value)
+ {
+ return 1 + i - KEY_EMOTE_1;
+ }
+ }
+ return 0;
+}
+
bool KeyboardConfig::isKeyActive(int index)
{
return mActiveKeys[ mKey[index].value];
diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h
index 3317460f..8949a48e 100644
--- a/src/keyboardconfig.h
+++ b/src/keyboardconfig.h
@@ -1,6 +1,6 @@
/*
- * The Mana World
- * Copyright (C) 2007 The Mana World Development Team
+ * Custom keyboard shortcuts configuration
+ * Copyright (C) 2007 Joshua Langley <joshlangley@optusnet.com.au>
*
* This file is part of The Mana World.
*
@@ -22,11 +22,9 @@
#ifndef KEYBOARDCONFIG_H
#define KEYBOARDCONFIG_H
+#include <SDL_types.h>
#include <string>
-#include "gui/sdlinput.h"
-#include "gui/setup_keyboard.h"
-
/**
* Each key represents a key function. Such as 'Move up', 'Attack' etc.
*/
@@ -38,6 +36,8 @@ struct KeyFunction
int value; /** The actual value that is used. */
};
+class Setup_Keyboard;
+
class KeyboardConfig
{
public:
@@ -101,6 +101,11 @@ class KeyboardConfig
int getKeyIndex(int keyValue) const;
/**
+ * Get the key function index for an emote by providing the offset value.
+ */
+ int getKeyEmoteOffset(int keyValue) const;
+
+ /**
* Set the enable flag, which will stop the user from doing actions.
*/
void setEnabled(bool flag)
@@ -141,21 +146,26 @@ class KeyboardConfig
* The key assignment view gets arranged according to the order of
* these values.
*/
- enum KeyAction {
+ enum KeyAction
+ {
KEY_NO_VALUE = -1,
KEY_MOVE_UP,
KEY_MOVE_DOWN,
KEY_MOVE_LEFT,
KEY_MOVE_RIGHT,
KEY_ATTACK,
- KEY_SMILIE,
+ KEY_EMOTE,
+ KEY_TALK,
KEY_TARGET,
KEY_TARGET_CLOSEST,
+ KEY_TARGET_NPC,
KEY_TARGET_PLAYER,
KEY_PICKUP,
KEY_HIDE_WINDOWS,
KEY_SIT,
- KEY_SHORTCUT_0,
+ KEY_SCREENSHOT,
+ KEY_TRADE,
+ KEY_PATHFIND,
KEY_SHORTCUT_1,
KEY_SHORTCUT_2,
KEY_SHORTCUT_3,
@@ -165,6 +175,10 @@ class KeyboardConfig
KEY_SHORTCUT_7,
KEY_SHORTCUT_8,
KEY_SHORTCUT_9,
+ KEY_SHORTCUT_10,
+ KEY_SHORTCUT_11,
+ KEY_SHORTCUT_12,
+ KEY_WINDOW_HELP,
KEY_WINDOW_STATUS,
KEY_WINDOW_INVENTORY,
KEY_WINDOW_EQUIPMENT,
@@ -174,6 +188,25 @@ class KeyboardConfig
KEY_WINDOW_SHORTCUT,
KEY_WINDOW_SETUP,
KEY_WINDOW_DEBUG,
+ KEY_WINDOW_EMOTE,
+ KEY_WINDOW_EMOTE_SHORTCUT,
+ KEY_EMOTE_1,
+ KEY_EMOTE_2,
+ KEY_EMOTE_3,
+ KEY_EMOTE_4,
+ KEY_EMOTE_5,
+ KEY_EMOTE_6,
+ KEY_EMOTE_7,
+ KEY_EMOTE_8,
+ KEY_EMOTE_9,
+ KEY_EMOTE_10,
+ KEY_EMOTE_11,
+ KEY_EMOTE_12,
+ KEY_TOGGLE_CHAT,
+ KEY_SCROLL_CHAT_UP,
+ KEY_SCROLL_CHAT_DOWN,
+ KEY_OK,
+ KEY_QUIT,
KEY_TOTAL
};
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 07044ce7..a02a8b1b 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -18,19 +18,23 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <cassert>
-#include "localplayer.h"
-
+#include "configuration.h"
#include "equipment.h"
#include "floor_item.h"
#include "game.h"
+#include "graphics.h"
#include "inventory.h"
#include "item.h"
-#include "main.h"
+#include "localplayer.h"
+#include "map.h"
+#include "monster.h"
#include "particle.h"
+#include "simpleanimation.h"
#include "sound.h"
-#include "monster.h"
#include "statuseffect.h"
+#include "text.h"
#include "gui/gui.h"
#include "gui/ministatus.h"
@@ -38,10 +42,18 @@
#include "net/messageout.h"
#include "net/protocol.h"
+#include "resources/animation.h"
+#include "resources/image.h"
+#include "resources/imageset.h"
+#include "resources/resourcemanager.h"
+
#include "utils/tostring.h"
LocalPlayer *player_node = NULL;
+static const int NAME_X_OFFSET = 15;
+static const int NAME_Y_OFFSET = 30;
+
LocalPlayer::LocalPlayer(Uint32 id, Uint16 job, Map *map):
Player(id, job, map),
mCharId(0),
@@ -57,23 +69,56 @@ LocalPlayer::LocalPlayer(Uint32 id, Uint16 job, Map *map):
ATK_BONUS(0), MATK_BONUS(0), DEF_BONUS(0), MDEF_BONUS(0), FLEE_BONUS(0),
mStatPoint(0), mSkillPoint(0),
mStatsPointsToAttribute(0),
+ mEquipment(new Equipment()),
mXp(0), mNetwork(0),
mTarget(NULL), mPickUpTarget(NULL),
mTrading(false), mGoingToTarget(false),
- mLastAction(-1),
- mWalkingDir(0), mDestX(0), mDestY(0),
- mInventory(new Inventory)
+ mTargetTime(-1), mLastAction(-1),
+ mLastTarget(-1), mWalkingDir(0),
+ mDestX(0), mDestY(0),
+ mInventory(new Inventory(INVENTORY_SIZE)),
+ mStorage(new Inventory(STORAGE_SIZE))
{
+ // Variable to keep the local player from doing certain actions before a map
+ // is initialized. e.g. drawing a player's name using the TextManager, since
+ // it appears to be dependant upon map coordinates for updating drawing.
+ mMapInitialized = false;
+
+ mUpdateName = true;
+
+ initTargetCursor();
}
LocalPlayer::~LocalPlayer()
{
delete mInventory;
+ delete mStorage;
+ delete mName;
+
+ for (int i = Being::TC_SMALL; i < Being::NUM_TC; i++)
+ {
+ delete mTargetCursorInRange[i];
+ delete mTargetCursorOutRange[i];
+ mInRangeImages[i]->decRef();
+ mOutRangeImages[i]->decRef();
+ }
}
void LocalPlayer::logic()
{
switch (mAction) {
+ case STAND:
+ break;
+
+ case SIT:
+ break;
+
+ case DEAD:
+ break;
+
+ case HURT:
+ break;
+
case WALK:
mFrame = (get_elapsed_time(mWalkTime) * 6) / mWalkSpeed;
if (mFrame >= 6) {
@@ -91,7 +136,6 @@ void LocalPlayer::logic()
mFrame = (get_elapsed_time(mWalkTime) * frames) / mAttackSpeed;
if (mFrame >= frames) {
nextStep();
- attack();
}
break;
}
@@ -100,10 +144,65 @@ void LocalPlayer::logic()
if (get_elapsed_time(mLastAction) >= 1000) {
mLastAction = -1;
}
+ // Targeting allowed 4 times a second
+ if (get_elapsed_time(mLastTarget) >= 250) {
+ mLastTarget = -1;
+ }
+ // Remove target if its been on a being for more than a minute
+ if (get_elapsed_time(mTargetTime) >= 60000)
+ {
+ mTargetTime = -1;
+ setTarget(NULL);
+ mLastTarget = -1;
+ }
+
+ if (mTarget)
+ {
+ if (mTarget->mAction == DEAD)
+ {
+ stopAttack();
+ }
+ if (mKeepAttacking && mTarget)
+ {
+ attack(mTarget, true);
+ }
+
+ for (int i = Being::TC_SMALL; i < Being::NUM_TC; i++)
+ {
+ player_node->mTargetCursorInRange[i]->update(10);
+ player_node->mTargetCursorOutRange[i]->update(10);
+ }
+ }
Being::logic();
}
+void LocalPlayer::setGM()
+{
+ mIsGM = !mIsGM;
+ mNameColor = mIsGM ? 0x009000: 0x202020;
+ setName(getName());
+ config.setValue(getName() + "GMassert", mIsGM);
+}
+
+void LocalPlayer::setName(const std::string &name)
+{
+ if (mName)
+ {
+ delete mName;
+ mName = 0;
+ }
+
+ if (config.getValue("showownname", false) && mMapInitialized)
+ {
+ Player::setName(name);
+ }
+ else
+ {
+ Being::setName(name);
+ }
+}
+
void LocalPlayer::nextStep()
{
if (mPath.empty())
@@ -240,9 +339,19 @@ void LocalPlayer::walk(unsigned char dir)
void LocalPlayer::setTarget(Being *target)
{
- if (target == mTarget)
- {
+ if (mLastTarget != -1 || target == this)
return;
+ mLastTarget = tick_time;
+
+ if (!target || target == mTarget)
+ {
+ target = NULL;
+ mKeepAttacking = false;
+ mTargetTime = -1;
+ }
+ if (target)
+ {
+ mTargetTime = tick_time;
}
if (mTarget && mTarget->getType() == Being::MONSTER)
{
@@ -384,25 +493,25 @@ bool LocalPlayer::tradeRequestOk() const
void LocalPlayer::attack(Being *target, bool keep)
{
- // Can only attack when standing still
- if (mAction != STAND)
+ mKeepAttacking = keep;
+
+ if (!target)
return;
- if (keep && target)
+ if ((mTarget != target) || !mTarget)
{
+ mLastTarget = -1;
setTarget(target);
}
- else if (mTarget)
- {
- target = mTarget;
- }
-
- if (!target)
- return;
int dist_x = target->mX - mX;
int dist_y = target->mY - mY;
+ // Must be standing and be within attack range to continue
+ if ((mAction != STAND) || (mAttackRange < abs(dist_x)) ||
+ (mAttackRange < abs(dist_y)))
+ return;
+
if (abs(dist_y) >= abs(dist_x))
{
if (dist_y > 0)
@@ -418,13 +527,19 @@ void LocalPlayer::attack(Being *target, bool keep)
setDirection(LEFT);
}
- setAction(ATTACK);
+ // Implement charging attacks here
+ mLastAttackTime = 0;
+
mWalkTime = tick_time;
+ mTargetTime = tick_time;
+
+ setAction(ATTACK);
if (mEquippedWeapon)
{
std::string soundFile = mEquippedWeapon->getSound(EQUIP_EVENT_STRIKE);
- if (soundFile != "") sound.playSfx(soundFile);
+ if (!soundFile.empty())
+ sound.playSfx(soundFile);
}
else {
sound.playSfx("sfx/fist-swish.ogg");
@@ -434,11 +549,22 @@ void LocalPlayer::attack(Being *target, bool keep)
outMsg.writeInt16(0x0089);
outMsg.writeInt32(target->getId());
outMsg.writeInt8(0);
+
+ if (!keep)
+ {
+ stopAttack();
+ }
}
void LocalPlayer::stopAttack()
{
+ if (mTarget)
+ {
+ setAction(STAND);
+ mLastTarget = -1;
+ }
setTarget(NULL);
+ mLastTarget = -1;
}
Being* LocalPlayer::getTarget() const
@@ -481,6 +607,7 @@ bool LocalPlayer::withinAttackRange(Being *target)
void LocalPlayer::setGotoTarget(Being *target)
{
+ mLastTarget = -1;
setTarget(target);
mGoingToTarget = true;
setDestination(target->mX, target->mY);
@@ -527,3 +654,85 @@ void LocalPlayer::handleStatusEffect(StatusEffect *effect, int effectId)
}
}
}
+
+void LocalPlayer::initTargetCursor()
+{
+ // Load target cursors
+ loadTargetCursor("graphics/gui/target-cursor-blue-s.png", 44, 35,
+ false, TC_SMALL);
+ loadTargetCursor("graphics/gui/target-cursor-red-s.png", 44, 35,
+ true, TC_SMALL);
+ loadTargetCursor("graphics/gui/target-cursor-blue-m.png", 62, 44,
+ false, TC_MEDIUM);
+ loadTargetCursor("graphics/gui/target-cursor-red-m.png", 62, 44,
+ true, TC_MEDIUM);
+ loadTargetCursor("graphics/gui/target-cursor-blue-l.png", 82, 60,
+ false, TC_LARGE);
+ loadTargetCursor("graphics/gui/target-cursor-red-l.png", 82, 60,
+ true, TC_LARGE);
+}
+
+void LocalPlayer::loadTargetCursor(std::string filename, int width, int height,
+ bool outRange, TargetCursorSize size)
+{
+ assert(size > -1);
+ assert(size < 3);
+
+ ImageSet* currentImageSet;
+ SimpleAnimation* currentCursor;
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ currentImageSet = resman->getImageSet(filename, width, height);
+ Animation *anim = new Animation();
+ for (unsigned int i = 0; i < currentImageSet->size(); ++i)
+ {
+ anim->addFrame(currentImageSet->get(i), 75, 0, 0);
+ }
+ currentCursor = new SimpleAnimation(anim);
+
+ if (outRange)
+ {
+ mOutRangeImages[size] = currentImageSet;
+ mTargetCursorOutRange[size] = currentCursor;
+ }
+ else
+ {
+ mInRangeImages[size] = currentImageSet;
+ mTargetCursorInRange[size] = currentCursor;
+ }
+}
+
+void LocalPlayer::drawTargetCursor(Graphics *graphics, int scrollX, int scrollY)
+{
+
+ // Draw target marker if needed
+ if (mTarget)
+ {
+ // Calculate target circle position
+
+ // Find whether target is in range
+ int rangeX = abs(mTarget->mX - mX);
+ int rangeY = abs(mTarget->mY - mY);
+ int attackRange = getAttackRange();
+
+ // Get the correct target cursors graphic
+ TargetCursorSize cursorSize = mTarget->getTargetCursorSize();
+
+ if (rangeX > attackRange || rangeY > attackRange)
+ {
+ mTarget->mTargetCursor = mTargetCursorOutRange[cursorSize]->getCurrentImage();
+ }
+ else
+ {
+ mTarget->mTargetCursor = mTargetCursorInRange[cursorSize]->getCurrentImage();
+ }
+
+ // Draw the target cursor at the correct position
+ int posX = mTarget->getPixelX() + 16 - mTarget->mTargetCursor->getWidth() / 2 - scrollX;
+ int posY = mTarget->getPixelY() + 16 - mTarget->mTargetCursor->getHeight() / 2 - scrollY;
+
+ graphics->drawImage(mTarget->mTargetCursor, posX, posY);
+ }
+ return;
+}
diff --git a/src/localplayer.h b/src/localplayer.h
index 6b6486e5..c128f4a4 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -22,6 +22,7 @@
#ifndef LOCALPLAYER_H
#define LOCALPLAYER_H
+#include <memory>
#include <vector>
#include "player.h"
@@ -29,10 +30,17 @@
// TODO move into some sane place...
#define MAX_SLOT 2
+#define INVENTORY_SIZE 102
+#define STORAGE_SIZE 301
+
+class Equipment;
class FloorItem;
+class ImageSet;
class Inventory;
class Item;
+class Map;
class Network;
+class SimpleAnimation;
/**
* The local player character.
@@ -40,7 +48,8 @@ class Network;
class LocalPlayer : public Player
{
public:
- enum Attribute {
+ enum Attribute
+ {
STR = 0, AGI, VIT, INT, DEX, LUK
};
@@ -54,7 +63,7 @@ class LocalPlayer : public Player
*/
~LocalPlayer();
- void setName(const std::string &name) {Being::setName(name); }
+ virtual void setName(const std::string &name);
void setNetwork(Network *network) { mNetwork = network; }
Network *getNetwork() {return mNetwork; }
virtual void logic();
@@ -71,6 +80,11 @@ class LocalPlayer : public Player
Inventory* getInventory() const { return mInventory; }
/**
+ * Returns the player's storage
+ */
+ Inventory* getStorage() const { return mStorage; }
+
+ /**
* Equips an item.
*/
void equipItem(Item *item);
@@ -118,6 +132,14 @@ class LocalPlayer : public Player
void attack(Being *target = NULL, bool keep = false);
+ /**
+ * Triggers whether or not to show the name as a GM name.
+ * NOTE: This doesn't mean that just anyone can use this.
+ * If the server doesn't acknowlege you, you won't be shown
+ * as a GM on other people's clients.
+ */
+ virtual void setGM();
+
void stopAttack();
Being* getTarget() const;
@@ -166,6 +188,12 @@ class LocalPlayer : public Player
void revive();
/**
+ * Accessors for mInStorage
+ */
+ bool getInStorage() { return mInStorage; }
+ void setInStorage(bool inStorage) { mInStorage = inStorage; }
+
+ /**
* Sets the amount of XP. Shows XP gaining effect if the player is on
* a map.
*/
@@ -198,6 +226,22 @@ class LocalPlayer : public Player
Uint16 mStatPoint, mSkillPoint;
Uint16 mStatsPointsToAttribute;
+ bool mUpdateName; /** Whether or not the name settings have changed */
+
+ bool mMapInitialized; /** Whether or not the map is available yet */
+
+ float mLastAttackTime; /**< Used to synchronize the charge dialog */
+
+ void drawTargetCursor(Graphics *graphics, int offsetX, int offsetY);
+
+ /** Animated in range target cursor. */
+ SimpleAnimation *mTargetCursorInRange[NUM_TC];
+
+ /** Animated out of range target cursor. */
+ SimpleAnimation *mTargetCursorOutRange[NUM_TC];
+
+ const std::auto_ptr<Equipment> mEquipment;
+
protected:
virtual void
handleStatusEffect(StatusEffect *effect, int effectId);
@@ -211,15 +255,35 @@ class LocalPlayer : public Player
FloorItem *mPickUpTarget;
bool mTrading;
+ bool mInStorage; /**< Whether storage is currently accessible */
bool mGoingToTarget;
- int mLastAction; /**< Time stamp of the last action, -1 if none. */
- int mWalkingDir; /**< The direction the player is walking in. */
- int mDestX; /**< X coordinate of destination. */
- int mDestY; /**< Y coordinate of destination. */
+ bool mKeepAttacking; /** Whether or not to continue to attack */
+ int mTargetTime; /** How long the being has been targeted **/
+ int mLastAction; /**< Time stamp of the last action, -1 if none. */
+ int mLastTarget; /** Time stamp of last targeting action, -1 if none. */
+ int mWalkingDir; /**< The direction the player is walking in. */
+ int mDestX; /**< X coordinate of destination. */
+ int mDestY; /**< Y coordinate of destination. */
std::vector<int> mStatusEffectIcons;
Inventory *mInventory;
+ Inventory *mStorage;
+
+ /**
+ * Helper function for loading target cursors
+ */
+ void loadTargetCursor(std::string filename, int width, int height,
+ bool outRange, Being::TargetCursorSize size);
+
+ /** Images of in range target cursor. */
+ ImageSet *mInRangeImages[NUM_TC];
+
+ /** Images of out of range target cursor. */
+ ImageSet *mOutRangeImages[NUM_TC];
+
+ // Load the target cursors into memory
+ void initTargetCursor();
};
extern LocalPlayer *player_node;
diff --git a/src/log.cpp b/src/log.cpp
index e50edeb2..b0024f80 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -19,8 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <cstdarg>
-#include <cstdlib>
#include <iostream>
#include <sstream>
diff --git a/src/log.h b/src/log.h
index fcd48757..b06bdc89 100644
--- a/src/log.h
+++ b/src/log.h
@@ -22,7 +22,6 @@
#ifndef _LOG_H
#define _LOG_H
-#include <iosfwd>
#include <fstream>
class ChatWindow;
diff --git a/src/main.cpp b/src/main.cpp
index 0291fd86..aa8e2805 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -19,48 +19,43 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "main.h"
-
#include <getopt.h>
#include <iostream>
#include <physfs.h>
+#include <SDL_image.h>
#include <unistd.h>
#include <vector>
-#include <SDL_image.h>
#include <guichan/actionlistener.hpp>
+
#include <guichan/widgets/label.hpp>
#include <libxml/parser.h>
-#ifdef WIN32
-#include <SDL_syswm.h>
-#endif
-#ifndef WIN32
-#include <cerrno>
-#include <sys/stat.h>
-#endif
-#if defined __APPLE__
-#include <CoreFoundation/CFBundle.h>
-#endif
+#include <SDL/SDL_ttf.h>
#include "configuration.h"
-#include "keyboardconfig.h"
-#include "player_relations.h"
+#include "emoteshortcut.h"
#include "game.h"
#include "graphics.h"
#include "itemshortcut.h"
-#include "lockedarray.h"
+#include "keyboardconfig.h"
#include "localplayer.h"
+#include "lockedarray.h"
#include "log.h"
#include "logindata.h"
+#include "main.h"
#ifdef USE_OPENGL
#include "openglgraphics.h"
#endif
+#include "player_relations.h"
+#include "serverinfo.h"
#include "sound.h"
+#include "gui/button.h"
#include "gui/char_server.h"
#include "gui/char_select.h"
+#include "gui/color.h"
#include "gui/gui.h"
#include "gui/login.h"
#include "gui/ok_dialog.h"
@@ -68,7 +63,6 @@
#include "gui/register.h"
#include "gui/sdlinput.h"
#include "gui/setup.h"
-#include "gui/textfield.h"
#include "gui/updatewindow.h"
#include "net/charserverhandler.h"
@@ -77,17 +71,35 @@
#include "net/messageout.h"
#include "net/network.h"
+#include "resources/colordb.h"
+#include "resources/emotedb.h"
#include "resources/image.h"
#include "resources/itemdb.h"
#include "resources/monsterdb.h"
#include "resources/npcdb.h"
#include "resources/resourcemanager.h"
-#include "utils/dtor.h"
#include "utils/gettext.h"
#include "utils/tostring.h"
-namespace {
+#ifdef __APPLE__
+#include <CoreFoundation/CFBundle.h>
+#endif
+
+#ifdef __MINGW32__
+#include <windows.h>
+#define usleep(usec) (Sleep ((usec) / 1000), 0)
+#endif
+
+#ifdef WIN32
+#include <SDL_syswm.h>
+#else
+#include <cerrno>
+#include <sys/stat.h>
+#endif
+
+namespace
+{
Window *setupWindow = 0;
struct SetupListener : public gcn::ActionListener
@@ -123,6 +135,7 @@ CharServerHandler charServerHandler;
LoginData loginData;
LockedArray<LocalPlayer*> charInfo(MAX_SLOT + 1);
+Color *textColor;
// This anonymous namespace hides whatever is inside from other modules.
namespace {
@@ -168,10 +181,13 @@ struct Options
*/
void setUpdatesDir()
{
+ std::stringstream updates;
+
// If updatesHost is currently empty, fill it from config file
- if (updateHost.empty()) {
+ if (updateHost.empty())
+ {
updateHost =
- config.getValue("updatehost", "http://updates.themanaworld.org");
+ config.getValue("updatehost", "http://updates.themanaworld.org/");
}
// Remove any trailing slash at the end of the update host
@@ -181,29 +197,59 @@ void setUpdatesDir()
// Parse out any "http://" or "ftp://", and set the updates directory
size_t pos;
pos = updateHost.find("://");
- if (pos != updateHost.npos) {
- if (pos + 3 < updateHost.length()) {
- updatesDir =
- "updates/" + updateHost.substr(pos + 3);
- } else {
+ if (pos != updateHost.npos)
+ {
+ if (pos + 3 < updateHost.length())
+ {
+ updates << "updates/" << updateHost.substr(pos + 3)
+ << "/" << loginData.port;
+ updatesDir = updates.str();
+ }
+ else
+ {
logger->log("Error: Invalid update host: %s", updateHost.c_str());
- errorMessage = "Invalid update host: " + updateHost;
+ errorMessage = _("Invalid update host: ") + updateHost;
state = ERROR_STATE;
}
- } else {
+ }
+ else
+ {
logger->log("Warning: no protocol was specified for the update host");
- updatesDir = "updates/" + updateHost;
+ updates << "updates/" << updateHost << "/" << loginData.port;
+ updatesDir = updates.str();
}
ResourceManager *resman = ResourceManager::getInstance();
// Verify that the updates directory exists. Create if necessary.
- if (!resman->isDirectory("/" + updatesDir)) {
- if (!resman->mkdir("/" + updatesDir)) {
+ if (!resman->isDirectory("/" + updatesDir))
+ {
+ if (!resman->mkdir("/" + updatesDir))
+ {
+#if defined WIN32
+ std::string newDir = homeDir + "\\" + updatesDir;
+ std::string::size_type loc = newDir.find("/", 0);
+
+ while (loc != std::string::npos)
+ {
+ newDir.replace(loc, 1, "\\");
+ loc = newDir.find("/", loc);
+ }
+
+ if (!CreateDirectory(newDir.c_str(), 0) &&
+ GetLastError() != ERROR_ALREADY_EXISTS)
+ {
+ logger->log("Error: %s can't be made, but doesn't exist!",
+ newDir.c_str());
+ errorMessage = _("Error creating updates directory!");
+ state = ERROR_STATE;
+ }
+#else
logger->log("Error: %s/%s can't be made, but doesn't exist!",
- homeDir.c_str(), updatesDir.c_str());
- errorMessage = "Error creating updates directory!";
+ homeDir.c_str(), updatesDir.c_str());
+ errorMessage = _("Error creating updates directory!");
state = ERROR_STATE;
+#endif
}
}
}
@@ -219,7 +265,7 @@ void init_engine(const Options &options)
GetLastError() != ERROR_ALREADY_EXISTS)
#elif defined __APPLE__
// Use Application Directory instead of .tmw
- homeDir = std::string(PHYSFS_getUserDir()) +
+ homeDir = std::string(PHYSFS_getUserDir()) +
"/Library/Application Support/The Mana World";
if ((mkdir(homeDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) &&
(errno != EEXIST))
@@ -230,7 +276,7 @@ void init_engine(const Options &options)
#endif
{
std::cout << homeDir
- << " can't be created, but it doesn't exist! Exiting."
+ << _(" can't be created, but it doesn't exist! Exiting.")
<< std::endl;
exit(1);
}
@@ -247,7 +293,7 @@ void init_engine(const Options &options)
// Initialize SDL
logger->log("Initializing SDL...");
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) {
- std::cerr << "Could not initialize SDL: " <<
+ std::cerr << _("Could not initialize SDL: ") <<
SDL_GetError() << std::endl;
exit(1);
}
@@ -260,7 +306,7 @@ void init_engine(const Options &options)
if (!resman->setWriteDir(homeDir)) {
std::cout << homeDir
- << " couldn't be set as home directory! Exiting."
+ << _(" couldn't be set as home directory! Exiting.")
<< std::endl;
exit(1);
}
@@ -280,18 +326,18 @@ void init_engine(const Options &options)
if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path,
PATH_MAX))
{
- fprintf(stderr, "Can't find Resources directory\n");
+ fprintf(stderr, _("Can't find Resources directory\n"));
}
CFRelease(resourcesURL);
strncat(path, "/data", PATH_MAX - 1);
resman->addToSearchPath(path, true);
#else
- resman->addToSearchPath(TMW_DATADIR "data", true);
+ resman->addToSearchPath(PKG_DATADIR "data", true);
#endif
// Fill configuration with defaults
logger->log("Initializing configuration...");
- config.setValue("host", "server.themanaworld.org");
+ config.setValue("host", "www.themanaworld.org");
config.setValue("port", 6901);
config.setValue("hwaccel", 0);
#if (defined __APPLE__ || defined WIN32) && defined USE_OPENGL
@@ -312,24 +358,24 @@ void init_engine(const Options &options)
// Checking if the configuration file exists... otherwise creates it with
// default options !
- FILE *tmwFile = 0;
+ FILE *configFile = 0;
std::string configPath = options.configPath;
if (configPath.empty())
configPath = homeDir + "/config.xml";
- tmwFile = fopen(configPath.c_str(), "r");
+ configFile = fopen(configPath.c_str(), "r");
// If we can't read it, it doesn't exist !
- if (tmwFile == NULL) {
+ if (configFile == NULL) {
// We reopen the file in write mode and we create it
- tmwFile = fopen(configPath.c_str(), "wt");
+ configFile = fopen(configPath.c_str(), "wt");
}
- if (tmwFile == NULL) {
+ if (configFile == NULL) {
std::cout << "Can't create " << configPath << ". "
"Using Defaults." << std::endl;
} else {
- fclose(tmwFile);
+ fclose(configFile);
config.init(configPath);
}
@@ -343,7 +389,7 @@ void init_engine(const Options &options)
SetClassLong(pInfo.window, GCL_HICON, (LONG) icon);
}
#else
- SDL_Surface *icon = IMG_Load(TMW_DATADIR "data/icons/tmw.png");
+ SDL_Surface *icon = IMG_Load(PKG_DATADIR "data/icons/tmw.png");
if (icon)
{
SDL_SetAlpha(icon, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
@@ -364,17 +410,17 @@ void init_engine(const Options &options)
graphics = new Graphics();
#endif
- int width = (int) config.getValue("screenwidth", defaultScreenWidth);
- int height = (int) config.getValue("screenheight", defaultScreenHeight);
- int bpp = 0;
- bool fullscreen = ((int) config.getValue("screen", 0) == 1);
- bool hwaccel = ((int) config.getValue("hwaccel", 0) == 1);
+ const int width = (int) config.getValue("screenwidth", defaultScreenWidth);
+ const int height = (int) config.getValue("screenheight", defaultScreenHeight);
+ const int bpp = 0;
+ const bool fullscreen = ((int) config.getValue("screen", 0) == 1);
+ const bool hwaccel = ((int) config.getValue("hwaccel", 0) == 1);
// Try to set the desired video mode
if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel))
{
- std::cerr << "Couldn't set "
- << width << "x" << height << "x" << bpp << " video mode: "
+ std::cerr << _("Couldn't set ")
+ << width << "x" << height << "x" << bpp << _(" video mode: ")
<< SDL_GetError() << std::endl;
exit(1);
}
@@ -385,6 +431,9 @@ void init_engine(const Options &options)
// Initialize the item shortcuts.
itemShortcut = new ItemShortcut();
+ // Initialize the emote shortcuts.
+ emoteShortcut = new EmoteShortcut();
+
gui = new Gui(graphics);
state = LOGIN_STATE; /**< Initial game state */
@@ -416,6 +465,7 @@ void exit_engine()
{
// Before config.write() since it writes the shortcuts to the config
delete itemShortcut;
+ delete emoteShortcut;
config.write();
@@ -429,6 +479,8 @@ void exit_engine()
sound.close();
// Unload XML databases
+ ColorDB::unload();
+ EmoteDB::unload();
ItemDB::unload();
MonsterDB::unload();
NPCDB::unload();
@@ -440,27 +492,27 @@ void exit_engine()
void printHelp()
{
std::cout
- << "tmw" << std::endl << std::endl
- << "Options: " << std::endl
- << " -h --help : Display this help" << std::endl
- << " -v --version : Display the version" << std::endl
- << " -u --skipupdate : Skip the update process" << std::endl
- << " -d --data : Directory to load game data from" << std::endl
- << " -U --username : Login with this username" << std::endl
- << " -P --password : Login with this password" << std::endl
- << " -D --default : Bypass the login process with default settings" << std::endl
- << " -p --playername : Login with this player" << std::endl
- << " -C --configfile : Configuration file to use" << std::endl
- << " -H --updatehost : Use this update host" << std::endl;
+ << _("tmw") << std::endl << std::endl
+ << _("Options: ") << std::endl
+ << _(" -C --configfile : Configuration file to use") << std::endl
+ << _(" -d --data : Directory to load game data from") << std::endl
+ << _(" -D --default : Bypass the login process with default settings") << std::endl
+ << _(" -h --help : Display this help") << std::endl
+ << _(" -H --updatehost : Use this update host") << std::endl
+ << _(" -p --playername : Login with this player") << std::endl
+ << _(" -P --password : Login with this password") << std::endl
+ << _(" -u --skipupdate : Skip the update downloads") << std::endl
+ << _(" -U --username : Login with this username") << std::endl
+ << _(" -v --version : Display the version") << std::endl;
}
void printVersion()
{
#ifdef PACKAGE_VERSION
- std::cout << "The Mana World version " << PACKAGE_VERSION << std::endl;
+ std::cout << _("The Mana World version ") << PACKAGE_VERSION << std::endl;
#else
- std::cout << "The Mana World version " <<
- "(local build?, PACKAGE_VERSION is not defined)" << std::endl;
+ std::cout << _("The Mana World version ") <<
+ _"(local build?, PACKAGE_VERSION is not defined)") << std::endl;
#endif
}
@@ -469,16 +521,16 @@ void parseOptions(int argc, char *argv[], Options &options)
const char *optstring = "hvud:U:P:Dp:C:H:";
const struct option long_options[] = {
- { "help", no_argument, 0, 'h' },
- { "version", no_argument, 0, 'v' },
- { "skipupdate", no_argument, 0, 'u' },
+ { "configfile", required_argument, 0, 'C' },
{ "data", required_argument, 0, 'd' },
- { "username", required_argument, 0, 'U' },
- { "password", required_argument, 0, 'P' },
{ "default", no_argument, 0, 'D' },
{ "playername", required_argument, 0, 'p' },
- { "configfile", required_argument, 0, 'C' },
+ { "password", required_argument, 0, 'P' },
+ { "help", no_argument, 0, 'h' },
{ "updatehost", required_argument, 0, 'H' },
+ { "skipupdate", no_argument, 0, 'u' },
+ { "username", required_argument, 0, 'U' },
+ { "version", no_argument, 0, 'v' },
{ 0 }
};
@@ -490,36 +542,36 @@ void parseOptions(int argc, char *argv[], Options &options)
break;
switch (result) {
- default: // Unknown option
- case 'h':
- options.printHelp = true;
- break;
- case 'v':
- options.printVersion = true;
- break;
- case 'u':
- options.skipUpdate = true;
+ case 'C':
+ options.configPath = optarg;
break;
case 'd':
options.dataPath = optarg;
break;
- case 'U':
- options.username = optarg;
- break;
- case 'P':
- options.password = optarg;
- break;
case 'D':
options.chooseDefault = true;
break;
+ default: // Unknown option
+ case 'h':
+ options.printHelp = true;
+ break;
+ case 'H':
+ options.updateHost = optarg;
+ break;
case 'p':
options.playername = optarg;
break;
- case 'C':
- options.configPath = optarg;
+ case 'P':
+ options.password = optarg;
break;
- case 'H':
- options.updateHost = optarg;
+ case 'u':
+ options.skipUpdate = true;
+ break;
+ case 'U':
+ options.username = optarg;
+ break;
+ case 'v':
+ options.printVersion = true;
break;
}
}
@@ -597,6 +649,13 @@ void accountLogin(Network *network, LoginData *loginData)
config.setValue("remember", loginData->remember);
}
+static void positionDialog(Window *dialog, int screenWidth, int screenHeight)
+{
+ dialog->setPosition(
+ (screenWidth - dialog->getWidth()) / 2,
+ (screenHeight - dialog->getHeight()) / 2);
+}
+
void charLogin(Network *network, LoginData *loginData)
{
logger->log("Trying to connect to char server...");
@@ -672,9 +731,12 @@ int main(int argc, char *argv[])
#if ENABLE_NLS
#ifdef WIN32
putenv(("LANG=" + std::string(_nl_locale_name_default())).c_str());
+ // mingw doesn't like LOCALEDIR to be defined for some reason
+ bindtextdomain("tmw", "translations/");
+#else
+ bindtextdomain("tmw", LOCALEDIR);
#endif
setlocale(LC_MESSAGES, "");
- bindtextdomain("tmw", LOCALEDIR);
bind_textdomain_codeset("tmw", "UTF-8");
textdomain("tmw");
#endif
@@ -697,6 +759,9 @@ int main(int argc, char *argv[])
unsigned int oldstate = !state; // We start with a status change.
+ // Needs to be created in main, as the updater uses it
+ textColor = new Color();
+
Game *game = NULL;
Window *currentDialog = NULL;
Image *login_wallpaper = NULL;
@@ -707,7 +772,7 @@ int main(int argc, char *argv[])
gcn::Label *versionLabel = new gcn::Label(PACKAGE_VERSION);
top->add(versionLabel, 2, 2);
#endif
- ProgressBar *progressBar = new ProgressBar(0.0f, 100, 20);
+ ProgressBar *progressBar = new ProgressBar(0.0f, 100, 20, 168, 116, 31);
gcn::Label *progressLabel = new gcn::Label();
top->add(progressBar, 5, top->getHeight() - 5 - progressBar->getHeight());
top->add(progressLabel, 15 + progressBar->getWidth(),
@@ -729,12 +794,37 @@ int main(int argc, char *argv[])
loginData.password = options.password;
}
loginData.hostname = config.getValue("host", "server.themanaworld.org");
- loginData.port = (short)config.getValue("port", 0);
+ loginData.port = (short)config.getValue("port", 6901);
loginData.remember = config.getValue("remember", 0);
loginData.registerLogin = false;
SDLNet_Init();
Network *network = new Network();
+
+ // Set the most appropriate wallpaper, based on screen width
+ int screenWidth = (int) config.getValue("screenwidth", defaultScreenWidth);
+ int screenHeight = static_cast<int>(config.getValue("screenheight",
+ defaultScreenHeight));
+ std::string wallpaperName;
+
+ wallpaperName = "graphics/images/login_wallpaper.png";
+ if (screenWidth >= 1024 && screenWidth < 1280)
+ wallpaperName = "graphics/images/login_wallpaper_1024x768.png";
+ else if (screenWidth >= 1280 && screenWidth < 1440)
+ wallpaperName = "graphics/images/login_wallpaper_1280x960.png";
+ else if (screenWidth >= 1440 && screenWidth < 1600)
+ wallpaperName = "graphics/images/login_wallpaper_1440x1080.png";
+ else if (screenWidth >= 1600)
+ wallpaperName = "graphics/images/login_wallpaper_1600x1200.png";
+
+ if (!ResourceManager::getInstance()->exists(wallpaperName))
+ wallpaperName = "graphics/images/login_wallpaper.png";
+
+ login_wallpaper = ResourceManager::getInstance()->getImage(wallpaperName);
+
+ if (!login_wallpaper)
+ logger->log("Couldn't load %s as wallpaper", wallpaperName.c_str());
+
while (state != EXIT_STATE)
{
// Handle SDL events
@@ -770,16 +860,6 @@ int main(int argc, char *argv[])
}
}
- if (!login_wallpaper)
- {
- login_wallpaper = ResourceManager::getInstance()->
- getImage("graphics/images/login_wallpaper.png");
- if (!login_wallpaper)
- {
- logger->error("Couldn't load login_wallpaper.png");
- }
- }
-
if (progressBar->isVisible())
{
progressBar->setProgress(progressBar->getProgress() + 0.005f);
@@ -808,7 +888,7 @@ int main(int argc, char *argv[])
// Reload the wallpaper in case that it was updated
login_wallpaper->decRef();
login_wallpaper = ResourceManager::getInstance()->
- getImage("graphics/images/login_wallpaper.png");
+ getImage(wallpaperName);
break;
// Those states don't cause a network disconnect
@@ -847,9 +927,12 @@ int main(int argc, char *argv[])
false);
// Load XML databases
+ ColorDB::load();
ItemDB::load();
MonsterDB::load();
NPCDB::load();
+ EmoteDB::load();
+
state = CHAR_CONNECT_STATE;
break;
@@ -861,33 +944,50 @@ int main(int argc, char *argv[])
state = ACCOUNT_STATE;
} else {
currentDialog = new LoginDialog(&loginData);
+ positionDialog(currentDialog, screenWidth,
+ screenHeight);
}
break;
case REGISTER_STATE:
logger->log("State: REGISTER");
currentDialog = new RegisterDialog(&loginData);
+ positionDialog(currentDialog, screenWidth, screenHeight);
break;
case CHAR_SERVER_STATE:
logger->log("State: CHAR_SERVER");
+
+ if (n_server == 1)
+ {
+ SERVER_INFO *si = *server_info;
+ loginData.hostname = iptostring(si->address);
+ loginData.port = si->port;
+ loginData.updateHost = si->updateHost;
+ state = UPDATE_STATE;
+ }
+ else
{
int nextState = (options.skipUpdate) ?
LOADDATA_STATE : UPDATE_STATE;
currentDialog = new ServerSelectDialog(&loginData,
- nextState);
- }
- if (options.chooseDefault || options.playername != "") {
- ((ServerSelectDialog*) currentDialog)->action(
- gcn::ActionEvent(NULL, "ok"));
+ nextState);
+ positionDialog(currentDialog, screenWidth,
+ screenHeight);
+ if (options.chooseDefault
+ || !options.playername.empty())
+ {
+ ((ServerSelectDialog*) currentDialog)->action(
+ gcn::ActionEvent(NULL, "ok"));
+ }
}
break;
-
case CHAR_SELECT_STATE:
logger->log("State: CHAR_SELECT");
currentDialog = new CharSelectDialog(network, &charInfo,
(loginData.sex == 0) ?
GENDER_FEMALE : GENDER_MALE);
+ positionDialog(currentDialog, screenWidth, screenHeight);
if (((CharSelectDialog*) currentDialog)->
selectByName(options.playername))
@@ -899,6 +999,7 @@ int main(int argc, char *argv[])
if (options.chooseDefault)
((CharSelectDialog*) currentDialog)->action(
gcn::ActionEvent(NULL, "ok"));
+
break;
case GAME_STATE:
@@ -936,13 +1037,21 @@ int main(int argc, char *argv[])
setUpdatesDir();
logger->log("State: UPDATE");
- currentDialog = new UpdaterWindow(updateHost,
- homeDir + "/" + updatesDir);
+
+ if (options.skipUpdate) {
+ state = LOADDATA_STATE;
+ } else {
+ currentDialog = new UpdaterWindow(updateHost,
+ homeDir + "/" + updatesDir);
+ positionDialog(currentDialog, screenWidth,
+ screenHeight);
+ }
break;
case ERROR_STATE:
logger->log("State: ERROR");
currentDialog = new OkDialog(_("Error"), errorMessage);
+ positionDialog(currentDialog, screenWidth, screenHeight);
currentDialog->addActionListener(&errorListener);
currentDialog = NULL; // OkDialog deletes itself
network->disconnect();
@@ -979,8 +1088,15 @@ int main(int argc, char *argv[])
break;
}
}
+ /*
+ * This loop can really stress the CPU, for no reason since it's
+ * just constantly redrawing the wallpaper. Added the following
+ * usleep to limit it to 20 FPS during the login sequence
+ */
+ usleep(50000);
}
+ delete textColor;
#ifdef PACKAGE_VERSION
delete versionLabel;
#endif
diff --git a/src/main.h b/src/main.h
index 69929957..1e02cf2a 100644
--- a/src/main.h
+++ b/src/main.h
@@ -32,8 +32,8 @@
#define PACKAGE_VERSION "0.0.28"
#endif
-#ifndef TMW_DATADIR
-#define TMW_DATADIR ""
+#ifndef PKG_DATADIR
+#define PKG_DATADIR ""
#endif
/*
diff --git a/src/map.cpp b/src/map.cpp
index f0c84159..b5e815f3 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -19,21 +19,21 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "map.h"
-
#include <queue>
#include "beingmanager.h"
#include "configuration.h"
#include "game.h"
#include "graphics.h"
+#include "localplayer.h"
+#include "map.h"
#include "particle.h"
#include "sprite.h"
#include "tileset.h"
-#include "resources/resourcemanager.h"
#include "resources/ambientoverlay.h"
#include "resources/image.h"
+#include "resources/resourcemanager.h"
#include "utils/dtor.h"
#include "utils/tostring.h"
@@ -68,6 +68,7 @@ TileAnimation::TileAnimation(Animation *ani):
{
}
+
void TileAnimation::update()
{
//update animation
@@ -136,6 +137,7 @@ void MapLayer::draw(Graphics *graphics,
// If drawing the fringe layer, make sure all sprites above this row of
// tiles have been drawn
if (mIsFringeLayer) {
+ player_node->drawTargetCursor(graphics, scrollX, scrollY);
while (si != sprites.end() && (*si)->getPixelY() <= y * 32 - 32) {
(*si)->draw(graphics, -scrollX, -scrollY);
si++;
@@ -256,7 +258,8 @@ void Map::draw(Graphics *graphics, int scrollX, int scrollY)
// draw the game world
Layers::const_iterator layeri = mLayers.begin();
- for (; layeri != mLayers.end(); ++layeri) {
+ for (; layeri != mLayers.end(); ++layeri)
+ {
(*layeri)->draw(graphics,
startX, startY, endX, endY,
scrollX, scrollY,
@@ -547,12 +550,15 @@ void Map::addParticleEffect(const std::string &effectFile, int x, int y)
void Map::initializeParticleEffects(Particle* particleEngine)
{
- for (std::list<ParticleEffectData>::iterator i = particleEffects.begin();
- i != particleEffects.end();
- i++
- )
+ if (config.getValue("particleeffects", 1))
{
- particleEngine->addEffect(i->file, i->x, i->y);
+ for (std::list<ParticleEffectData>::iterator i = particleEffects.begin();
+ i != particleEffects.end();
+ i++
+ )
+ {
+ particleEngine->addEffect(i->file, i->x, i->y);
+ }
}
}
diff --git a/src/map.h b/src/map.h
index 33133ac4..3beab350 100644
--- a/src/map.h
+++ b/src/map.h
@@ -27,9 +27,9 @@
#include "position.h"
#include "properties.h"
-
#include "simpleanimation.h"
+class Animation;
class AmbientOverlay;
class Graphics;
class Image;
@@ -186,8 +186,7 @@ class Map : public Properties
/**
* Finds the tile set that a tile with the given global id is part of.
*/
- Tileset*
- getTilesetWithGid(int gid) const;
+ Tileset* getTilesetWithGid(int gid) const;
/**
* Get tile reference.
@@ -207,26 +206,22 @@ class Map : public Properties
/**
* Returns the width of this map.
*/
- int
- getWidth() const { return mWidth; }
+ int getWidth() const { return mWidth; }
/**
* Returns the height of this map.
*/
- int
- getHeight() const { return mHeight; }
+ int getHeight() const { return mHeight; }
/**
* Returns the tile width of this map.
*/
- int
- getTileWidth() const { return mTileWidth; }
+ int getTileWidth() const { return mTileWidth; }
/**
* Returns the tile height used by this map.
*/
- int
- getTileHeight() const { return mTileHeight; }
+ int getTileHeight() const { return mTileHeight; }
/**
* Find a path from one location to the next.
@@ -236,14 +231,12 @@ class Map : public Properties
/**
* Adds a sprite to the map.
*/
- SpriteIterator
- addSprite(Sprite *sprite);
+ SpriteIterator addSprite(Sprite *sprite);
/**
* Removes a sprite from the map.
*/
- void
- removeSprite(SpriteIterator iterator);
+ void removeSprite(SpriteIterator iterator);
/**
* Adds a particle effect
@@ -270,9 +263,8 @@ class Map : public Properties
/**
* Draws the overlay graphic to the given graphics output.
*/
- void
- drawOverlay(Graphics *graphics, float scrollX, float scrollY,
- int detail);
+ void drawOverlay(Graphics *graphics, float scrollX, float scrollY,
+ int detail);
/**
* Tells whether a tile is occupied by a being.
diff --git a/src/monster.cpp b/src/monster.cpp
index f50855ca..8f56560b 100644
--- a/src/monster.cpp
+++ b/src/monster.cpp
@@ -19,18 +19,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "monster.h"
-
#include "animatedsprite.h"
#include "game.h"
-#include "sound.h"
+#include "localplayer.h"
+#include "monster.h"
#include "particle.h"
+#include "sound.h"
#include "text.h"
-#include "localplayer.h"
#include "resources/monsterdb.h"
-
-#include "utils/tostring.h"
+#include "resources/monsterinfo.h"
static const int NAME_X_OFFSET = 16;
static const int NAME_Y_OFFSET = 16;
@@ -44,6 +42,7 @@ Monster::Monster(Uint32 id, Uint16 job, Map *map):
// Setup Monster sprites
int c = BASE_SPRITE;
const std::list<std::string> &sprites = info.getSprites();
+
for (std::list<std::string>::const_iterator i = sprites.begin();
i != sprites.end();
i++)
@@ -61,21 +60,26 @@ Monster::Monster(Uint32 id, Uint16 job, Map *map):
mSprites[c] = AnimatedSprite::load("graphics/sprites/error.xml");
}
- const std::list<std::string> &particleEffects = info.getParticleEffects();
- for ( std::list<std::string>::const_iterator i = particleEffects.begin();
- i != particleEffects.end();
- i++
- )
+ if (mParticleEffects)
{
- controlParticle(particleEngine->addEffect((*i), 0, 0));
+ const std::list<std::string> &particleEffects = info.getParticleEffects();
+ for ( std::list<std::string>::const_iterator i = particleEffects.begin();
+ i != particleEffects.end(); i++
+ )
+ {
+ controlParticle(particleEngine->addEffect((*i), 0, 0));
+ }
}
+
+ mNameColor = 0xff2020;
}
Monster::~Monster()
{
if (mText)
{
- player_node->setTarget(0);
+ delete mText;
+ player_node->setTarget(NULL);
}
}
@@ -99,9 +103,11 @@ Being::Type Monster::getType() const
return MONSTER;
}
-void Monster::setAction(Uint8 action)
+void Monster::setAction(Action action)
{
SpriteAction currentAction = ACTION_INVALID;
+ int rotation = 0;
+ std::string particleEffect;
switch (action)
{
@@ -115,13 +121,34 @@ void Monster::setAction(Uint8 action)
case ATTACK:
currentAction = ACTION_ATTACK;
mSprites[BASE_SPRITE]->reset();
+
+ //attack particle effect
+ particleEffect = getInfo().getAttackParticleEffect();
+ if (!particleEffect.empty() && mParticleEffects)
+ {
+ switch (mDirection)
+ {
+ case DOWN: rotation = 0; break;
+ case LEFT: rotation = 90; break;
+ case UP: rotation = 180; break;
+ case RIGHT: rotation = 270; break;
+ default: break;
+ }
+ Particle *p;
+ p = particleEngine->addEffect(
+ particleEffect, 0, 0, rotation);
+ controlParticle(p);
+ }
break;
case STAND:
- currentAction = ACTION_STAND;
- break;
+ currentAction = ACTION_STAND;
+ break;
case HURT:
- // Not implemented yet
- break;
+ // Not implemented yet
+ break;
+ case SIT:
+ // Also not implemented yet
+ break;
}
if (currentAction != ACTION_INVALID)
@@ -164,13 +191,15 @@ const MonsterInfo &Monster::getInfo() const
void Monster::showName(bool show)
{
- delete mText;
+ if (mText)
+ {
+ delete mText;
+ }
if (show)
{
mText = new Text(getInfo().getName(), mPx + NAME_X_OFFSET,
mPy + NAME_Y_OFFSET - getHeight(),
- gcn::Graphics::CENTER,
- gcn::Color(255, 64, 64));
+ gcn::Graphics::CENTER, gcn::Color(255, 64, 64));
}
else
{
diff --git a/src/monster.h b/src/monster.h
index 36812f41..8d7f8ae7 100644
--- a/src/monster.h
+++ b/src/monster.h
@@ -36,7 +36,7 @@ class Monster : public Being
virtual void logic();
- virtual void setAction(Uint8 action);
+ virtual void setAction(Action action);
virtual Type getType() const;
@@ -62,8 +62,7 @@ class Monster : public Being
/**
* Returns the MonsterInfo, with static data about this monster.
*/
- const MonsterInfo&
- getInfo() const;
+ const MonsterInfo& getInfo() const;
/**
* Determine whether the mob should show it's name
diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp
index e0ade2ae..0db8fcbf 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/beinghandler.cpp
@@ -19,24 +19,23 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "beinghandler.h"
-
+#include <iostream>
#include <SDL_types.h>
+#include "beinghandler.h"
#include "messagein.h"
#include "protocol.h"
#include "../being.h"
#include "../beingmanager.h"
+#include "../effectmanager.h"
#include "../game.h"
#include "../localplayer.h"
#include "../log.h"
-#include "../main.h"
+#include "../npc.h"
#include "../particle.h"
-#include "../sound.h"
-#include <iostream>
#include "../player_relations.h"
-#include "../npc.h"
+#include "../sound.h"
const int EMOTION_TIME = 150; /**< Duration of emotion icon */
@@ -73,6 +72,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
Uint16 headTop, headMid, headBottom;
Uint16 shoes, gloves;
Uint16 weapon, shield;
+ Uint16 gmstatus;
Sint16 param1;
int stunMode;
Uint32 statusEffects;
@@ -211,22 +211,17 @@ void BeingHandler::handleMessage(MessageIn *msg)
if (!dstBeing)
break;
+ // If this is player's current target, clear it.
if (dstBeing == player_node->getTarget())
- {
player_node->stopAttack();
- }
if (dstBeing == current_npc)
current_npc = NULL;
if (msg->readInt8() == 1)
- {
dstBeing->setAction(Being::DEAD);
- }
else
- {
beingManager->destroyBeing(dstBeing);
- }
break;
@@ -244,28 +239,26 @@ void BeingHandler::handleMessage(MessageIn *msg)
switch (type)
{
case 0x0a: // Critical Damage
- if (dstBeing) {
- dstBeing->controlParticle(particleEngine->addEffect(
- "graphics/particles/crit.particle.xml", 0, 0));
- }
+ if (dstBeing)
+ dstBeing->showCrit();
case 0x00: // Damage
- if (dstBeing) {
+ if (dstBeing)
dstBeing->takeDamage(param1);
- }
- if (srcBeing) {
+ if (srcBeing)
srcBeing->handleAttack(dstBeing, param1);
- }
break;
case 0x02: // Sit
- if (srcBeing) {
+ if (srcBeing)
+ {
srcBeing->mFrame = 0;
srcBeing->setAction(Being::SIT);
}
break;
case 0x03: // Stand up
- if (srcBeing) {
+ if (srcBeing)
+ {
srcBeing->mFrame = 0;
srcBeing->setAction(Being::STAND);
}
@@ -279,8 +272,9 @@ void BeingHandler::handleMessage(MessageIn *msg)
break;
int effectType = msg->readInt32();
+ Being* being = beingManager->findBeing(id);
- beingManager->findBeing(id)->triggerEffect(effectType);
+ effectManager->trigger(effectType, being);
break;
}
@@ -450,18 +444,22 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setDirection(dir);
}
- msg->readInt16(); // GM status
+ gmstatus = msg->readInt16();
+ if (gmstatus & 0x80)
+ dstBeing->setGM();
if (msg->getId() == SMSG_PLAYER_UPDATE_1)
{
- switch (msg->readInt8()) {
-
- case 1: dstBeing->setAction(Being::DEAD);
- break;
-
- case 2: dstBeing->setAction(Being::SIT);
- break;
-
+ switch (msg->readInt8())
+ {
+ case 1:
+ if (dstBeing->getType() != Being::NPC)
+ dstBeing->setAction(Being::DEAD);
+ break;
+
+ case 2:
+ dstBeing->setAction(Being::SIT);
+ break;
}
}
else if (msg->getId() == SMSG_PLAYER_MOVE)
@@ -482,16 +480,16 @@ void BeingHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_STOP:
/*
- * Instruction from server to stop walking at x, y.
- *
- * Some people like having this enabled. Others absolutely
- * despise it. So I'm setting to so that it only affects the
- * local player if the person has set a key "EnableSync" to "1"
- * in their config.xml file.
- *
- * This packet will be honored for all other beings, regardless
- * of the config setting.
- */
+ * Instruction from server to stop walking at x, y.
+ *
+ * Some people like having this enabled. Others absolutely
+ * despise it. So I'm setting to so that it only affects the
+ * local player if the person has set a key "EnableSync" to "1"
+ * in their config.xml file.
+ *
+ * This packet will be honored for all other beings, regardless
+ * of the config setting.
+ */
id = msg->readInt32();
if (mSync || id != player_node->getId()) {
@@ -509,11 +507,11 @@ void BeingHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_MOVE_TO_ATTACK:
/*
- * This is an *advisory* message, telling the client that
- * it needs to move the character before attacking
- * a target (out of range, obstruction in line of fire).
- * We can safely ignore this...
- */
+ * This is an *advisory* message, telling the client that
+ * it needs to move the character before attacking
+ * a target (out of range, obstruction in line of fire).
+ * We can safely ignore this...
+ */
break;
case 0x0119:
@@ -544,4 +542,3 @@ void BeingHandler::handleMessage(MessageIn *msg)
break;
}
}
-
diff --git a/src/net/beinghandler.h b/src/net/beinghandler.h
index f72f0380..54b82075 100644
--- a/src/net/beinghandler.h
+++ b/src/net/beinghandler.h
@@ -27,7 +27,7 @@
class BeingHandler : public MessageHandler
{
public:
- BeingHandler(bool);
+ BeingHandler(bool enableSync);
void handleMessage(MessageIn *msg);
diff --git a/src/net/buysellhandler.cpp b/src/net/buysellhandler.cpp
index b7f3ecd4..67c79ec4 100644
--- a/src/net/buysellhandler.cpp
+++ b/src/net/buysellhandler.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "buysellhandler.h"
-
#include <SDL_types.h>
+#include "buysellhandler.h"
#include "messagein.h"
#include "protocol.h"
@@ -36,9 +35,11 @@
#include "../gui/chat.h"
#include "../gui/sell.h"
+#include "../utils/gettext.h"
+
extern BuyDialog *buyDialog;
-extern SellDialog *sellDialog;
extern Window *buySellDialog;
+extern SellDialog *sellDialog;
BuySellHandler::BuySellHandler()
{
@@ -105,27 +106,27 @@ void BuySellHandler::handleMessage(MessageIn *msg)
}
}
else {
- chatWindow->chatLog("Nothing to sell", BY_SERVER);
+ chatWindow->chatLog(_("Nothing to sell"), BY_SERVER);
current_npc = 0;
}
break;
case SMSG_NPC_BUY_RESPONSE:
if (msg->readInt8() == 0) {
- chatWindow->chatLog("Thanks for buying", BY_SERVER);
+ chatWindow->chatLog(_("Thanks for buying"), BY_SERVER);
} else {
// Reset player money since buy dialog already assumed purchase
// would go fine
buyDialog->setMoney(player_node->mGp);
- chatWindow->chatLog("Unable to buy", BY_SERVER);
+ chatWindow->chatLog(_("Unable to buy"), BY_SERVER);
}
break;
case SMSG_NPC_SELL_RESPONSE:
if (msg->readInt8() == 0) {
- chatWindow->chatLog("Thanks for selling", BY_SERVER);
+ chatWindow->chatLog(_("Thanks for selling"), BY_SERVER);
} else {
- chatWindow->chatLog("Unable to sell", BY_SERVER);
+ chatWindow->chatLog(_("Unable to sell"), BY_SERVER);
}
break;
}
diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp
index cfa52c38..932cf705 100644
--- a/src/net/charserverhandler.cpp
+++ b/src/net/charserverhandler.cpp
@@ -20,9 +20,7 @@
*/
#include "charserverhandler.h"
-
#include "messagein.h"
-#include "network.h"
#include "protocol.h"
#include "../game.h"
@@ -31,13 +29,17 @@
#include "../logindata.h"
#include "../main.h"
-#include "../gui/ok_dialog.h"
#include "../gui/char_select.h"
+#include "../gui/ok_dialog.h"
+
+#include "../utils/gettext.h"
+#include "../utils/tostring.h"
CharServerHandler::CharServerHandler():
mCharCreateDialog(0)
{
static const Uint16 _messages[] = {
+ SMSG_CONNECTION_PROBLEM,
0x006b,
0x006c,
0x006d,
@@ -45,7 +47,6 @@ CharServerHandler::CharServerHandler():
0x006f,
0x0070,
0x0071,
- 0x0081,
0
};
handledMessages = _messages;
@@ -53,16 +54,45 @@ CharServerHandler::CharServerHandler():
void CharServerHandler::handleMessage(MessageIn *msg)
{
- int slot;
+ int slot, flags, code;
LocalPlayer *tempPlayer;
logger->log("CharServerHandler: Packet ID: %x, Length: %d",
msg->getId(), msg->getLength());
switch (msg->getId())
{
+ case SMSG_CONNECTION_PROBLEM:
+ code = msg->readInt8();
+ logger->log("Connection problem: %i", code);
+
+ switch (code) {
+ case 0:
+ errorMessage = _("Authentication failed");
+ break;
+ case 1:
+ errorMessage = _("Map server(s) offline");
+ break;
+ case 2:
+ errorMessage = _("This account is already logged in");
+ break;
+ case 3:
+ errorMessage = _("Speed hack detected");
+ break;
+ case 8:
+ errorMessage = _("Duplicated login");
+ break;
+ default:
+ errorMessage = _("Unknown connection error");
+ break;
+ }
+ state = ERROR_STATE;
+ break;
+
case 0x006b:
- // Skip length word and an additional mysterious 20 bytes
- msg->skip(2 + 20);
+ msg->skip(2); // Length word
+ flags = msg->readInt32(); // Aethyra extensions flags
+ logger->log("Server flags are: %x", flags);
+ msg->skip(16); // Unused
// Derive number of characters from message length
n_character = (msg->getLength() - 24) / 106;
@@ -73,7 +103,7 @@ void CharServerHandler::handleMessage(MessageIn *msg)
mCharInfo->select(slot);
mCharInfo->setEntry(tempPlayer);
logger->log("CharServer: Player: %s (%d)",
- tempPlayer->getName().c_str(), slot);
+ tempPlayer->getName().c_str(), slot);
}
state = CHAR_SELECT_STATE;
@@ -82,13 +112,13 @@ void CharServerHandler::handleMessage(MessageIn *msg)
case 0x006c:
switch (msg->readInt8()) {
case 0:
- errorMessage = "Access denied";
+ errorMessage = _("Access denied");
break;
case 1:
- errorMessage = "Cannot use this ID";
+ errorMessage = _("Cannot use this ID");
break;
default:
- errorMessage = "Unknown failure to select character";
+ errorMessage = _("Unknown failure to select character");
break;
}
mCharInfo->unlock();
@@ -110,8 +140,8 @@ void CharServerHandler::handleMessage(MessageIn *msg)
break;
case 0x006e:
- new OkDialog("Error", "Failed to create character. Most likely"
- " the name is already taken.");
+ new OkDialog(_("Error"), _("Failed to create character. Most likely"
+ " the name is already taken."));
if (mCharCreateDialog)
mCharCreateDialog->unlock();
@@ -122,12 +152,12 @@ void CharServerHandler::handleMessage(MessageIn *msg)
mCharInfo->setEntry(0);
mCharInfo->unlock();
n_character--;
- new OkDialog("Info", "Player deleted");
+ new OkDialog(_("Info"), _("Player deleted"));
break;
case 0x0070:
mCharInfo->unlock();
- new OkDialog("Error", "Failed to delete character.");
+ new OkDialog(_("Error"), _("Failed to delete character."));
break;
case 0x0071:
@@ -154,25 +184,6 @@ void CharServerHandler::handleMessage(MessageIn *msg)
mCharInfo->select(slot);
state = CONNECTING_STATE;
break;
-
- case 0x0081:
- switch (msg->readInt8()) {
- case 1:
- errorMessage = "Map server offline";
- break;
- case 3:
- errorMessage = "Speed hack detected";
- break;
- case 8:
- errorMessage = "Duplicated login";
- break;
- default:
- errorMessage = "Unknown error with 0x0081";
- break;
- }
- mCharInfo->unlock();
- state = ERROR_STATE;
- break;
}
}
diff --git a/src/net/chathandler.cpp b/src/net/chathandler.cpp
index d25d4bcd..25877907 100644
--- a/src/net/chathandler.cpp
+++ b/src/net/chathandler.cpp
@@ -19,11 +19,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "chathandler.h"
-
#include <SDL_types.h>
#include <string>
+#include "chathandler.h"
#include "messagein.h"
#include "protocol.h"
@@ -34,6 +33,7 @@
#include "../gui/chat.h"
+#include "../utils/gettext.h"
#include "../utils/tostring.h"
#include "../utils/trim.h"
@@ -73,10 +73,10 @@ void ChatHandler::handleMessage(MessageIn *msg)
//chatWindow->chatLog("Whisper sent", BY_SERVER);
break;
case 0x01:
- chatWindow->chatLog("Whisper could not be sent, user is offline", BY_SERVER);
+ chatWindow->chatLog(_("Whisper could not be sent, user is offline"), BY_SERVER);
break;
case 0x02:
- chatWindow->chatLog("Whisper could not be sent, ignored by user", BY_SERVER);
+ chatWindow->chatLog(_("Whisper could not be sent, ignored by user"), BY_SERVER);
break;
}
break;
diff --git a/src/net/equipmenthandler.cpp b/src/net/equipmenthandler.cpp
index e5bbf6fe..9a3c396a 100644
--- a/src/net/equipmenthandler.cpp
+++ b/src/net/equipmenthandler.cpp
@@ -20,11 +20,9 @@
*/
#include "equipmenthandler.h"
-
#include "messagein.h"
#include "protocol.h"
-#include "../beingmanager.h"
#include "../equipment.h"
#include "../inventory.h"
#include "../item.h"
@@ -33,6 +31,8 @@
#include "../gui/chat.h"
+#include "../utils/gettext.h"
+
EquipmentHandler::EquipmentHandler()
{
static const Uint16 _messages[] = {
@@ -98,7 +98,7 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
logger->log("Equipping: %i %i %i", index, equipPoint, type);
if (!type) {
- chatWindow->chatLog("Unable to equip.", BY_SERVER);
+ chatWindow->chatLog(_("Unable to equip."), BY_SERVER);
break;
}
@@ -107,7 +107,10 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
}
- // Unequip any existing equipped item in this position
+ /*
+ * An item may occupy more than 1 slot. If so, it's
+ * only shown as equipped on the *first* slot.
+ */
mask = 1;
position = 0;
while (!(equipPoint & mask)) {
@@ -115,7 +118,10 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
position++;
}
logger->log("Position %i", position);
- item = player_node->getInventory()->getItem(player_node->mEquipment->getEquipment(position));
+
+ item = player_node->getInventory()->getItem(player_node->mEquipment->getEquipment(position));
+
+ // Unequip any existing equipped item in this position
if (item) {
item->setEquipped(false);
}
@@ -130,7 +136,7 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
type = msg->readInt8();
if (!type) {
- chatWindow->chatLog("Unable to unequip.", BY_SERVER);
+ chatWindow->chatLog(_("Unable to unequip."), BY_SERVER);
break;
}
@@ -152,24 +158,11 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
item->setEquipped(false);
- switch (item->getId()) {
- case 529:
- case 1199:
- player_node->mEquipment->setArrows(0);
- break;
- case 521:
- case 522:
- case 530:
- case 536:
- case 1200:
- case 1201:
- player_node->setSprite(Being::WEAPON_SPRITE, 0);
- // TODO: Why this break? Shouldn't a weapon be
- // unequipped in inventory too?
- break;
- default:
- player_node->mEquipment->removeEquipment(position);
- break;
+ if (equipPoint & 0x8000) { // Arrows
+ player_node->mEquipment->setArrows(0);
+ }
+ else {
+ player_node->mEquipment->removeEquipment(position);
}
logger->log("Unequipping: %i %i(%i) %i",
index, equipPoint, type, position);
@@ -186,12 +179,12 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
item = inventory->getItem(index);
- if (!item)
- break;
- item->setEquipped(true);
- player_node->mEquipment->setArrows(index);
- logger->log("Arrows equipped: %i", index);
+ if (item) {
+ item->setEquipped(true);
+ player_node->mEquipment->setArrows(index);
+ logger->log("Arrows equipped: %i", index);
+ }
break;
}
}
diff --git a/src/net/inventoryhandler.cpp b/src/net/inventoryhandler.cpp
index cd9b5ce0..46f03e28 100644
--- a/src/net/inventoryhandler.cpp
+++ b/src/net/inventoryhandler.cpp
@@ -19,22 +19,24 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "inventoryhandler.h"
-
#include <SDL_types.h>
+#include "inventoryhandler.h"
#include "messagein.h"
#include "protocol.h"
-#include "../resources/iteminfo.h"
+#include "../inventory.h"
#include "../item.h"
#include "../itemshortcut.h"
#include "../localplayer.h"
#include "../log.h"
-#include "../inventory.h"
#include "../gui/chat.h"
+#include "../resources/iteminfo.h"
+
+#include "../utils/gettext.h"
+#include "../utils/strprintf.h"
#include "../utils/tostring.h"
InventoryHandler::InventoryHandler()
@@ -45,6 +47,12 @@ InventoryHandler::InventoryHandler()
SMSG_PLAYER_INVENTORY_REMOVE,
SMSG_PLAYER_INVENTORY_USE,
SMSG_ITEM_USE_RESPONSE,
+ SMSG_PLAYER_STORAGE_ITEMS,
+ SMSG_PLAYER_STORAGE_EQUIP,
+ SMSG_PLAYER_STORAGE_STATUS,
+ SMSG_PLAYER_STORAGE_ADD,
+ SMSG_PLAYER_STORAGE_REMOVE,
+ SMSG_PLAYER_STORAGE_CLOSE,
0
};
handledMessages = _messages;
@@ -53,35 +61,69 @@ InventoryHandler::InventoryHandler()
void InventoryHandler::handleMessage(MessageIn *msg)
{
Sint32 number;
- Sint16 index, amount, itemId, equipType;
+ Sint16 index, amount, itemId, equipType, arrow;
+ Sint16 identified, cards[4], itemType;
Inventory *inventory = player_node->getInventory();
+ Inventory *storage = player_node->getStorage();
switch (msg->getId())
{
case SMSG_PLAYER_INVENTORY:
- // Only called on map load / warp. First reset all items
- // to not load them twice on map change.
- inventory->clear();
+ case SMSG_PLAYER_STORAGE_ITEMS:
+ case SMSG_PLAYER_STORAGE_EQUIP:
+ switch (msg->getId()) {
+ case SMSG_PLAYER_INVENTORY:
+ // Clear inventory - this will be a complete refresh
+ inventory->clear();
+ break;
+ case SMSG_PLAYER_STORAGE_ITEMS:
+ /*
+ * This packet will always be followed by a
+ * SMSG_PLAYER_STORAGE_EQUIP packet. The two packets
+ * together comprise a complete refresh of storage, so
+ * clear storage here
+ */
+ storage->clear();
+ logger->log("Received SMSG_PLAYER_STORAGE_ITEMS");
+ break;
+ default:
+ logger->log("Received SMSG_PLAYER_STORAGE_EQUIP");
+ break;
+ }
msg->readInt16(); // length
number = (msg->getLength() - 4) / 18;
- for (int loop = 0; loop < number; loop++)
- {
+ for (int loop = 0; loop < number; loop++) {
index = msg->readInt16();
itemId = msg->readInt16();
- msg->readInt8(); // type
- msg->readInt8(); // identify flag
- amount = msg->readInt16();
- msg->skip(2); // unknown
- msg->skip(8); // card (4 shorts)
-
- inventory->setItem(index, itemId, amount, false);
-
- // Trick because arrows are not considered equipment
- if (itemId == 1199 || itemId == 529)
- {
- if (Item *item = inventory->getItem(index))
- item->setEquipment(true);
+ itemType = msg->readInt8();
+ identified = msg->readInt8();
+ if (msg->getId() == SMSG_PLAYER_STORAGE_EQUIP) {
+ amount = 1;
+ msg->readInt16(); // Equip Point?
+ } else {
+ amount = msg->readInt16();
+ }
+ arrow = msg->readInt16();
+ if (msg->getId() == SMSG_PLAYER_STORAGE_EQUIP) {
+ msg->readInt8(); // Attribute (broken)
+ msg->readInt8(); // Refine level
+ }
+ for (int i = 0; i < 4; i++)
+ cards[i] = msg->readInt16();
+
+ if (msg->getId() == SMSG_PLAYER_INVENTORY) {
+ inventory->setItem(index, itemId, amount, false);
+
+ // Trick because arrows are not considered equipment
+ if (arrow & 0x8000) {
+ if (Item *item = inventory->getItem(index))
+ item->setEquipment(true);
+ }
+ } else {
+ logger->log("Index:%d, ID:%d, Type:%d, Identified:%d, Qty:%d, Cards:%d, %d, %d, %d",
+ index, itemId, itemType, identified, amount, cards[0], cards[1], cards[2], cards[3]);
+ storage->setItem(index, itemId, amount, false);
}
}
break;
@@ -90,21 +132,22 @@ void InventoryHandler::handleMessage(MessageIn *msg)
index = msg->readInt16();
amount = msg->readInt16();
itemId = msg->readInt16();
- msg->readInt8(); // identify flag
+ identified = msg->readInt8();
msg->readInt8(); // attribute
msg->readInt8(); // refine
- msg->skip(8); // card
+ for (int i = 0; i < 4; i++)
+ cards[i] = msg->readInt16();
equipType = msg->readInt16();
- msg->readInt8(); // type
+ itemType = msg->readInt8();
if (msg->readInt8() > 0) {
- chatWindow->chatLog("Unable to pick up item", BY_SERVER);
+ chatWindow->chatLog(_("Unable to pick up item"), BY_SERVER);
} else {
const ItemInfo &itemInfo = ItemDB::get(itemId);
const std::string amountStr =
(amount > 1) ? toString(amount) : "a";
- chatWindow->chatLog("You picked up " + amountStr + " " +
- itemInfo.getName(), BY_SERVER);
+ chatWindow->chatLog(strprintf(_("You picked up %s %s"),
+ amountStr.c_str(), itemInfo.getName().c_str()), BY_SERVER);
if (Item *item = inventory->getItem(index)) {
item->setId(itemId);
@@ -141,11 +184,44 @@ void InventoryHandler::handleMessage(MessageIn *msg)
amount = msg->readInt16();
if (msg->readInt8() == 0) {
- chatWindow->chatLog("Failed to use item", BY_SERVER);
+ chatWindow->chatLog(_("Failed to use item"), BY_SERVER);
} else {
if (Item *item = inventory->getItem(index))
item->setQuantity(amount);
}
break;
+
+ case SMSG_PLAYER_STORAGE_STATUS:
+ /*
+ * Basic slots used vs total slots info
+ * We don't really need this information, but this is
+ * the closest we get to an "Open Storage" packet
+ * from the server. It always comes after the two
+ * SMSG_PLAYER_STORAGE_... packets that update
+ * storage contents.
+ */
+ logger->log("Received SMSG_PLAYER_STORAGE_STATUS");
+ player_node->setInStorage(true);
+ break;
+
+ case SMSG_PLAYER_STORAGE_ADD:
+ /*
+ * Move an item into storage
+ */
+ break;
+
+ case SMSG_PLAYER_STORAGE_REMOVE:
+ /*
+ * Move an item out of storage
+ */
+ break;
+
+ case SMSG_PLAYER_STORAGE_CLOSE:
+ /*
+ * Storage access has been closed
+ */
+ player_node->setInStorage(false);
+ logger->log("Received SMSG_PLAYER_STORAGE_CLOSE");
+ break;
}
}
diff --git a/src/net/itemhandler.cpp b/src/net/itemhandler.cpp
index 03313a55..8c4af4e4 100644
--- a/src/net/itemhandler.cpp
+++ b/src/net/itemhandler.cpp
@@ -20,7 +20,6 @@
*/
#include "itemhandler.h"
-
#include "messagein.h"
#include "protocol.h"
diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp
index 646c5f3c..41314d16 100644
--- a/src/net/loginhandler.cpp
+++ b/src/net/loginhandler.cpp
@@ -20,9 +20,7 @@
*/
#include "loginhandler.h"
-
#include "messagein.h"
-#include "network.h"
#include "protocol.h"
#include "../log.h"
@@ -30,11 +28,16 @@
#include "../main.h"
#include "../serverinfo.h"
+#include "../utils/gettext.h"
+#include "../utils/strprintf.h"
+#include "../utils/tostring.h"
+
extern SERVER_INFO **server_info;
LoginHandler::LoginHandler()
{
static const Uint16 _messages[] = {
+ SMSG_CONNECTION_PROBLEM,
SMSG_UPDATE_HOST,
0x0069,
0x006a,
@@ -45,9 +48,32 @@ LoginHandler::LoginHandler()
void LoginHandler::handleMessage(MessageIn *msg)
{
+ int code;
+
switch (msg->getId())
{
- case 0x0063:
+ case SMSG_CONNECTION_PROBLEM:
+ code = msg->readInt8();
+ logger->log("Connection problem: %i", code);
+
+ switch (code) {
+ case 0:
+ errorMessage = _("Authentication failed");
+ break;
+ case 1:
+ errorMessage = _("No servers available");
+ break;
+ case 2:
+ errorMessage = _("This account is already logged in");
+ break;
+ default:
+ errorMessage = _("Unknown connection error");
+ break;
+ }
+ state = ERROR_STATE;
+ break;
+
+ case SMSG_UPDATE_HOST:
int len;
len = msg->readInt16() - 4;
@@ -91,35 +117,39 @@ void LoginHandler::handleMessage(MessageIn *msg)
break;
case 0x006a:
- int loginError = msg->readInt8();
- logger->log("Login::error code: %i", loginError);
+ code = msg->readInt8();
+ logger->log("Login::error code: %i", code);
- switch (loginError) {
+ switch (code) {
case 0:
- errorMessage = "Unregistered ID";
+ errorMessage = _("Unregistered ID");
break;
case 1:
- errorMessage = "Wrong password";
+ errorMessage = _("Wrong password");
break;
case 2:
- errorMessage = "Account expired";
+ errorMessage = _("Account expired");
break;
case 3:
- errorMessage = "Rejected from server";
+ errorMessage = _("Rejected from server");
break;
case 4:
- errorMessage = "You have been permanently banned from the game. Please contact the GM Team";
+ errorMessage = _("You have been permanently banned from the"
+ " game. Please contact the GM Team");
break;
case 6:
- errorMessage = "You have been temporarily banned from the game until "
- + msg->readString(20) + ".\n Please contact the GM team via the forums";
+ errorMessage = strprintf(_("You have been temporarily "
+ "banned from the game until %s.\n"
+ " Please contact the GM team via "
+ "the forums"),
+ msg->readString(20).c_str());
break;
case 9:
- errorMessage = "This user name is already taken";
+ errorMessage = _("This user name is already taken");
break;
default:
- errorMessage = "Unknown error";
+ errorMessage = _("Unknown error");
break;
}
state = ERROR_STATE;
diff --git a/src/net/loginhandler.h b/src/net/loginhandler.h
index a380c767..df86b634 100644
--- a/src/net/loginhandler.h
+++ b/src/net/loginhandler.h
@@ -22,9 +22,10 @@
#ifndef NET_LOGINHANDLER_H
#define NET_LOGINHANDLER_H
-#include "messagehandler.h"
#include <string>
+#include "messagehandler.h"
+
struct LoginData;
class LoginHandler : public MessageHandler
diff --git a/src/net/maploginhandler.cpp b/src/net/maploginhandler.cpp
index 0d349a6d..b5192bd7 100644
--- a/src/net/maploginhandler.cpp
+++ b/src/net/maploginhandler.cpp
@@ -20,7 +20,6 @@
*/
#include "maploginhandler.h"
-
#include "messagein.h"
#include "protocol.h"
@@ -28,11 +27,13 @@
#include "../log.h"
#include "../main.h"
+#include "../utils/gettext.h"
+
MapLoginHandler::MapLoginHandler()
{
static const Uint16 _messages[] = {
+ SMSG_CONNECTION_PROBLEM,
SMSG_LOGIN_SUCCESS,
- 0x0081,
0
};
handledMessages = _messages;
@@ -40,10 +41,29 @@ MapLoginHandler::MapLoginHandler()
void MapLoginHandler::handleMessage(MessageIn *msg)
{
+ int code;
unsigned char direction;
switch (msg->getId())
{
+ case SMSG_CONNECTION_PROBLEM:
+ code = msg->readInt8();
+ logger->log("Connection problem: %i", code);
+
+ switch (code) {
+ case 0:
+ errorMessage = _("Authentication failed");
+ break;
+ case 2:
+ errorMessage = _("This account is already logged in");
+ break;
+ default:
+ errorMessage = _("Unknown connection error");
+ break;
+ }
+ state = ERROR_STATE;
+ break;
+
case SMSG_LOGIN_SUCCESS:
msg->readInt32(); // server tick
msg->readCoordinates(player_node->mX, player_node->mY, direction);
@@ -52,10 +72,5 @@ void MapLoginHandler::handleMessage(MessageIn *msg)
player_node->mX, player_node->mY, direction);
state = GAME_STATE;
break;
-
- case 0x0081:
- logger->log("Warning: Map server D/C");
- state = ERROR_STATE;
- break;
}
}
diff --git a/src/net/messagehandler.cpp b/src/net/messagehandler.cpp
index 063532d4..f1561a31 100644
--- a/src/net/messagehandler.cpp
+++ b/src/net/messagehandler.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "messagehandler.h"
-
#include <cassert>
+#include "messagehandler.h"
#include "network.h"
MessageHandler::MessageHandler():
diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp
index cbcde3fe..a288d936 100644
--- a/src/net/messagein.cpp
+++ b/src/net/messagein.cpp
@@ -19,17 +19,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "messagein.h"
-
#include <cassert>
#include <SDL.h>
#include <SDL_endian.h>
+#include "messagein.h"
+
#define MAKEWORD(low,high) \
((unsigned short)(((unsigned char)(low)) | \
((unsigned short)((unsigned char)(high))) << 8))
-
MessageIn::MessageIn(const char *data, unsigned int length):
mData(data),
mLength(length),
@@ -39,15 +38,13 @@ MessageIn::MessageIn(const char *data, unsigned int length):
mId = readInt16();
}
-Sint8
-MessageIn::readInt8()
+Sint8 MessageIn::readInt8()
{
assert(mPos < mLength);
return mData[mPos++];
}
-Sint16
-MessageIn::readInt16()
+Sint16 MessageIn::readInt16()
{
assert(mPos + 2 <= mLength);
mPos += 2;
@@ -58,8 +55,7 @@ MessageIn::readInt16()
#endif
}
-Sint32
-MessageIn::readInt32()
+Sint32 MessageIn::readInt32()
{
assert(mPos + 4 <= mLength);
mPos += 4;
@@ -70,8 +66,7 @@ MessageIn::readInt32()
#endif
}
-void
-MessageIn::readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction)
+void MessageIn::readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction)
{
assert(mPos + 3 <= mLength);
@@ -120,8 +115,7 @@ MessageIn::readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction)
mPos += 3;
}
-void
-MessageIn::readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
+void MessageIn::readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
Uint16 &dstX, Uint16 &dstY)
{
assert(mPos + 5 <= mLength);
@@ -143,15 +137,13 @@ MessageIn::readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
mPos += 5;
}
-void
-MessageIn::skip(unsigned int length)
+void MessageIn::skip(unsigned int length)
{
assert(mPos + length <= mLength);
mPos += length;
}
-std::string
-MessageIn::readString(int length)
+std::string MessageIn::readString(int length)
{
// Get string length
if (length < 0) {
diff --git a/src/net/messagein.h b/src/net/messagein.h
index 1788aa97..0ff6e78a 100644
--- a/src/net/messagein.h
+++ b/src/net/messagein.h
@@ -22,8 +22,8 @@
#ifndef MESSAGEIN_
#define MESSAGEIN_
-#include <string>
#include <SDL_types.h>
+#include <string>
/**
* Used for parsing an incoming message.
@@ -43,14 +43,12 @@ class MessageIn
/**
* Returns the message ID.
*/
- short
- getId() { return mId; }
+ short getId() { return mId; }
/**
* Returns the message length.
*/
- unsigned int
- getLength() { return mLength; }
+ unsigned int getLength() { return mLength; }
Sint8 readInt8(); /**< Reads a byte. */
Sint16 readInt16(); /**< Reads a short. */
@@ -60,30 +58,26 @@ class MessageIn
* Reads a special 3 byte block used by eAthena, containing x and y
* coordinates and direction.
*/
- void
- readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction);
+ void readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction);
/**
* Reads a special 5 byte block used by eAthena, containing a source
* and destination coordinate pair.
*/
- void
- readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
- Uint16 &dstX, Uint16 &dstY);
+ void readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
+ Uint16 &dstX, Uint16 &dstY);
/**
* Skips a given number of bytes.
*/
- void
- skip(unsigned int length);
+ void skip(unsigned int length);
/**
* Reads a string. If a length is not given (-1), it is assumed
* that the length of the string is stored in a short at the
* start of the string.
*/
- std::string
- readString(int length = -1);
+ std::string readString(int length = -1);
private:
const char* mData; /**< The message data. */
diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp
index 8f361e5e..bf4957be 100644
--- a/src/net/messageout.cpp
+++ b/src/net/messageout.cpp
@@ -20,13 +20,12 @@
*/
#include <cstring>
-#include <string>
#include <SDL.h>
#include <SDL_endian.h>
-
-#include "network.h"
+#include <string>
#include "messageout.h"
+#include "network.h"
MessageOut::MessageOut(Network *network):
mNetwork(network),
diff --git a/src/net/network.cpp b/src/net/network.cpp
index 1463c696..059da779 100644
--- a/src/net/network.cpp
+++ b/src/net/network.cpp
@@ -19,14 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "network.h"
+#include <sstream>
#include "messagehandler.h"
#include "messagein.h"
+#include "network.h"
#include "../log.h"
-
-#include <sstream>
+#include "../utils/tostring.h"
/** Warning: buffers and other variables are shared,
so there can be only one connection active at a time */
@@ -419,21 +419,7 @@ void Network::receive()
SDLNet_FreeSocketSet(set);
}
-char *iptostring(int address)
-{
- static char asciiIP[16];
-
- sprintf(asciiIP, "%i.%i.%i.%i",
- (unsigned char)(address),
- (unsigned char)(address >> 8),
- (unsigned char)(address >> 16),
- (unsigned char)(address >> 24));
-
- return asciiIP;
-}
-
-void
-Network::setError(const std::string& error)
+void Network::setError(const std::string& error)
{
logger->log("Network error: %s", error.c_str());
mError = error;
diff --git a/src/net/network.h b/src/net/network.h
index c942a819..02fe7538 100644
--- a/src/net/network.h
+++ b/src/net/network.h
@@ -48,47 +48,33 @@ class Network
~Network();
- bool
- connect(const std::string &address, short port);
+ bool connect(const std::string &address, short port);
- void
- disconnect();
+ void disconnect();
- void
- registerHandler(MessageHandler *handler);
+ void registerHandler(MessageHandler *handler);
- void
- unregisterHandler(MessageHandler *handler);
+ void unregisterHandler(MessageHandler *handler);
- void
- clearHandlers();
+ void clearHandlers();
- int
- getState() const { return mState; }
+ int getState() const { return mState; }
- const std::string&
- getError() const { return mError; }
+ const std::string& getError() const { return mError; }
- bool
- isConnected() const { return mState == CONNECTED; }
+ bool isConnected() const { return mState == CONNECTED; }
- int
- getInSize() const { return mInSize; }
+ int getInSize() const { return mInSize; }
- void
- skip(int len);
+ void skip(int len);
- bool
- messageReady();
+ bool messageReady();
- MessageIn
- getNextMessage();
+ MessageIn getNextMessage();
- void
- dispatchMessages();
+ void dispatchMessages();
- void
- flush();
+ void flush();
// ERROR replaced by NET_ERROR because already defined in Windows
enum {
@@ -100,17 +86,13 @@ class Network
};
protected:
- void
- setError(const std::string& error);
+ void setError(const std::string& error);
- Uint16
- readWord(int pos);
+ Uint16 readWord(int pos);
- bool
- realConnect();
+ bool realConnect();
- void
- receive();
+ void receive();
TCPsocket mSocket;
@@ -133,7 +115,4 @@ class Network
MessageHandlers mMessageHandlers;
};
-/** Convert an address from int format to string */
-char *iptostring(int address);
-
#endif
diff --git a/src/net/npchandler.cpp b/src/net/npchandler.cpp
index b0314e47..ea03537f 100644
--- a/src/net/npchandler.cpp
+++ b/src/net/npchandler.cpp
@@ -19,18 +19,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "npchandler.h"
-
#include "messagein.h"
+#include "npchandler.h"
#include "protocol.h"
#include "../beingmanager.h"
+#include "../localplayer.h"
#include "../npc.h"
+#include "../gui/npc_text.h"
#include "../gui/npcintegerdialog.h"
#include "../gui/npclistdialog.h"
#include "../gui/npcstringdialog.h"
-#include "../gui/npc_text.h"
extern NpcIntegerDialog *npcIntegerDialog;
extern NpcListDialog *npcListDialog;
@@ -60,6 +60,7 @@ void NPCHandler::handleMessage(MessageIn *msg)
case SMSG_NPC_CHOICE:
msg->readInt16(); // length
id = msg->readInt32();
+ player_node->setAction(LocalPlayer::STAND);
current_npc = dynamic_cast<NPC*>(beingManager->findBeing(id));
npcListDialog->parseItems(msg->readString(msg->getLength() - 8));
npcListDialog->setVisible(true);
@@ -68,17 +69,17 @@ void NPCHandler::handleMessage(MessageIn *msg)
case SMSG_NPC_MESSAGE:
msg->readInt16(); // length
id = msg->readInt32();
+ player_node->setAction(LocalPlayer::STAND);
current_npc = dynamic_cast<NPC*>(beingManager->findBeing(id));
npcTextDialog->addText(msg->readString(msg->getLength() - 8));
npcListDialog->setVisible(false);
npcTextDialog->setVisible(true);
break;
- case SMSG_NPC_CLOSE:
+ case SMSG_NPC_CLOSE:
id = msg->readInt32();
- dynamic_cast<NPC*>(beingManager->findBeing(id));
if (current_npc == dynamic_cast<NPC*>(beingManager->findBeing(id)))
- current_npc = NULL;
+ current_npc = NULL;
break;
case SMSG_NPC_NEXT:
@@ -91,6 +92,7 @@ void NPCHandler::handleMessage(MessageIn *msg)
current_npc = dynamic_cast<NPC*>(beingManager->findBeing(id));
npcIntegerDialog->setRange(0, 2147483647);
npcIntegerDialog->setVisible(true);
+ npcIntegerDialog->requestFocus();
break;
case SMSG_NPC_STR_INPUT:
@@ -99,6 +101,7 @@ void NPCHandler::handleMessage(MessageIn *msg)
current_npc = dynamic_cast<NPC*>(beingManager->findBeing(id));
npcStringDialog->setValue("");
npcStringDialog->setVisible(true);
+ npcStringDialog->requestFocus();
break;
}
}
diff --git a/src/net/partyhandler.cpp b/src/net/partyhandler.cpp
new file mode 100644
index 00000000..fe7db55d
--- /dev/null
+++ b/src/net/partyhandler.cpp
@@ -0,0 +1,122 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <guichan/actionlistener.hpp>
+
+#include "partyhandler.h"
+#include "protocol.h"
+#include "messagein.h"
+
+#include "../gui/chat.h"
+#include "../gui/confirm_dialog.h"
+
+#include "../beingmanager.h"
+#include "../party.h"
+
+PartyHandler::PartyHandler(Party *party) : mParty(party)
+{
+ static const Uint16 _messages[] = {
+ SMSG_PARTY_CREATE,
+ SMSG_PARTY_INFO,
+ SMSG_PARTY_INVITE,
+ SMSG_PARTY_INVITED,
+ SMSG_PARTY_SETTINGS,
+ SMSG_PARTY_MEMBER_INFO,
+ SMSG_PARTY_LEAVE,
+ SMSG_PARTY_UPDATE_HP,
+ SMSG_PARTY_UPDATE_COORDS,
+ SMSG_PARTY_MESSAGE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void PartyHandler::handleMessage(MessageIn *msg)
+{
+ switch (msg->getId())
+ {
+ case SMSG_PARTY_CREATE:
+ mParty->createResponse(msg->readInt8());
+ break;
+ case SMSG_PARTY_INFO:
+ break;
+ case SMSG_PARTY_INVITE:
+ {
+ std::string nick = msg->readString(24);
+ int status = msg->readInt8();
+ mParty->inviteResponse(nick, status);
+ break;
+ }
+ case SMSG_PARTY_INVITED:
+ {
+ int id = msg->readInt32();
+ Being *being = beingManager->findBeing(id);
+ if (!being)
+ {
+ break;
+ }
+ std::string nick;
+ int gender = 0;
+ std::string partyName = "";
+ if (being->getType() != Being::PLAYER)
+ {
+ nick = "";
+ }
+ else
+ {
+ nick = being->getName();
+ gender = being->getGender();
+ partyName = msg->readString(24);
+ }
+ mParty->invitedAsk(nick, gender, partyName);
+ break;
+ }
+ case SMSG_PARTY_SETTINGS:
+ break;
+ case SMSG_PARTY_MEMBER_INFO:
+ break;
+ case SMSG_PARTY_LEAVE:
+ {
+ /*int id = */msg->readInt32();
+ std::string nick = msg->readString(24);
+ /*int fail = */msg->readInt8();
+ mParty->leftResponse(nick);
+ break;
+ }
+ case SMSG_PARTY_UPDATE_HP:
+ break;
+ case SMSG_PARTY_UPDATE_COORDS:
+ break;
+ case SMSG_PARTY_MESSAGE:
+ { // new block to enable local variables
+ int msgLength = msg->readInt16() - 8;
+ if (msgLength <= 0)
+ {
+ return;
+ }
+ int id = msg->readInt32();
+ Being *being = beingManager->findBeing(id);
+ std::string chatMsg = msg->readString(msgLength);
+ mParty->receiveChat(being, chatMsg);
+ }
+ break;
+ }
+}
diff --git a/src/net/partyhandler.h b/src/net/partyhandler.h
new file mode 100644
index 00000000..048da9b1
--- /dev/null
+++ b/src/net/partyhandler.h
@@ -0,0 +1,39 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PARTYHANDLER_H
+#define PARTYHANDLER_H
+
+#include "messagehandler.h"
+
+class Party;
+
+class PartyHandler : public MessageHandler
+{
+ public:
+ PartyHandler(Party *party);
+
+ void handleMessage(MessageIn *msg);
+ private:
+ Party *mParty;
+};
+
+#endif
diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp
index 5d989a66..470a4aa4 100644
--- a/src/net/playerhandler.cpp
+++ b/src/net/playerhandler.cpp
@@ -19,16 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "playerhandler.h"
-
#include "messagein.h"
+#include "playerhandler.h"
#include "protocol.h"
#include "../engine.h"
#include "../localplayer.h"
#include "../log.h"
#include "../npc.h"
-#include "../utils/tostring.h"
#include "../gui/buy.h"
#include "../gui/chat.h"
@@ -40,6 +38,9 @@
#include "../gui/skill.h"
#include "../gui/viewport.h"
+#include "../utils/tostring.h"
+#include "../utils/gettext.h"
+
// TODO Move somewhere else
OkDialog *weightNotice = NULL;
OkDialog *deathNotice = NULL;
@@ -51,7 +52,7 @@ extern SellDialog *sellDialog;
extern Window *buySellDialog;
static const int MAP_TELEPORT_SCROLL_DISTANCE = 8; /* Max. distance we are willing to scroll after a teleport;
- ** everything beyond will reset the port hard. */
+ * everything beyond will reset the port hard. */
/**
* Listener used for handling the overweigth message.
@@ -110,10 +111,11 @@ void PlayerHandler::handleMessage(MessageIn *msg)
switch (msg->getId())
{
case SMSG_WALK_RESPONSE:
- // It is assumed by the client any request to walk actually
- // succeeds on the server. The plan is to have a correction
- // message when the server senses the client has the wrong
- // idea.
+ /*
+ * This client assumes that all walk messages succeed,
+ * and that the server will send a correction notice
+ * otherwise.
+ */
break;
case SMSG_PLAYER_WARP:
@@ -132,6 +134,7 @@ void PlayerHandler::handleMessage(MessageIn *msg)
player_node->stopAttack();
nearby = (engine->getCurrentMapName() == mapPath);
+
// Switch the actual map, deleting the previous one if necessary
engine->changeMap(mapPath);
@@ -143,7 +146,8 @@ void PlayerHandler::handleMessage(MessageIn *msg)
/* Scroll if neccessary */
if (!nearby
|| (abs(x - player_node->mX) > MAP_TELEPORT_SCROLL_DISTANCE)
- || (abs(y - player_node->mY) > MAP_TELEPORT_SCROLL_DISTANCE)) {
+ || (abs(y - player_node->mY) > MAP_TELEPORT_SCROLL_DISTANCE))
+ {
scrollOffsetX = (x - player_node->mX) * 32;
scrollOffsetY = (y - player_node->mY) * 32;
}
@@ -173,6 +177,9 @@ void PlayerHandler::handleMessage(MessageIn *msg)
case 0x0006: player_node->mMaxHp = value; break;
case 0x0007: player_node->mMp = value; break;
case 0x0008: player_node->mMaxMp = value; break;
+ case 0x0009:
+ player_node->mStatsPointsToAttribute = value;
+ break;
case 0x000b: player_node->mLevel = value; break;
case 0x000c:
player_node->mSkillPoint = value;
@@ -183,20 +190,16 @@ void PlayerHandler::handleMessage(MessageIn *msg)
player_node->mTotalWeight <
player_node->mMaxWeight / 2)
{
- weightNotice = new OkDialog("Message",
- "You are carrying more then half "
- "your weight. You are unable to "
- "regain health.");
+ weightNotice = new OkDialog(_("Message"),
+ _("You are carrying more then "
+ "half your weight. You are "
+ "unable to regain health."));
weightNotice->addActionListener(
&weightListener);
}
player_node->mTotalWeight = value;
break;
case 0x0019: player_node->mMaxWeight = value; break;
- case 0x0037: player_node->mJobLevel = value; break;
- case 0x0009:
- player_node->mStatsPointsToAttribute = value;
- break;
case 0x0029: player_node->ATK = value; break;
case 0x002b: player_node->MATK = value; break;
case 0x002d: player_node->DEF = value; break;
@@ -205,12 +208,44 @@ void PlayerHandler::handleMessage(MessageIn *msg)
case 0x0031: player_node->HIT = value; break;
case 0x0032: player_node->FLEE = value; break;
case 0x0035: player_node->mAttackSpeed = value; break;
+ case 0x0037: player_node->mJobLevel = value; break;
}
if (player_node->mHp == 0 && deathNotice == NULL)
{
- deathNotice = new OkDialog("Message",
- "You're now dead, press ok to restart");
+ static char const *const deadMsg[] =
+ {
+ _("You are dead."),
+ _("We regret to inform you that your character was killed in battle."),
+ _("You are not that alive anymore."),
+ _("The cold hands of the grim reaper are grabbing for your soul."),
+ _("Game Over!"),
+ _("Insert coin to continue"),
+ _("No, kids. Your character did not really die. It... err... went to a better place."),
+ _("Your plan of breaking your enemies weapon by bashing it with your throat failed."),
+ _("I guess this did not run too well."),
+ _("Do you want your possessions identified?"), // Nethack reference
+ _("Sadly, no trace of you was ever found..."), // Secret of Mana reference
+ _("Annihilated."), // Final Fantasy VI reference
+ _("Looks like you got your head handed to you."), //Earthbound reference
+ _("You screwed up again, dump your body down the tubes and get you another one."), // Leisure Suit Larry 1 Reference
+ _("You're not dead yet. You're just resting."), // Monty Python reference from a couple of skits
+ _("You are no more."), // Monty Python reference from the dead parrot sketch starting now
+ _("You have ceased to be."),
+ _("You've expired and gone to meet your maker."),
+ _("You're a stiff."),
+ _("Bereft of life, you rest in peace."),
+ _("If you weren't so animated, you'd be pushing up the daisies."),
+ _("Your metabolic processes are now history."),
+ _("You're off the twig."),
+ _("You've kicked the bucket."),
+ _("You've shuffled off your mortal coil, run down the curtain and joined the bleedin' choir invisibile."),
+ _("You are an ex-player."),
+ _("You're pining for the fjords.") // Monty Python reference from the dead parrot sketch
+ };
+ std::string message(deadMsg[rand()%27]);
+
+ deathNotice = new OkDialog(_("Message"), message);
deathNotice->addActionListener(&deathListener);
player_node->setAction(Being::DEAD);
}
@@ -229,7 +264,7 @@ void PlayerHandler::handleMessage(MessageIn *msg)
Uint32 curGp = player_node->mGp;
player_node->mGp = msg->readInt32();
if (player_node->mGp > curGp)
- chatWindow->chatLog("You picked up " +
+ chatWindow->chatLog(_("You picked up ") +
toString(player_node->mGp - curGp) + " GP",
BY_SERVER);
}
@@ -293,7 +328,7 @@ void PlayerHandler::handleMessage(MessageIn *msg)
}
break;
- // Updates stats and status points
+ // Updates stats and status points
case SMSG_PLAYER_STAT_UPDATE_5:
player_node->mStatsPointsToAttribute = msg->readInt16();
player_node->mAttr[LocalPlayer::STR] = msg->readInt8();
@@ -352,7 +387,7 @@ void PlayerHandler::handleMessage(MessageIn *msg)
switch (type) {
case 0:
- chatWindow->chatLog("Equip arrows first",
+ chatWindow->chatLog(_("Equip arrows first"),
BY_SERVER);
break;
default:
@@ -361,18 +396,5 @@ void PlayerHandler::handleMessage(MessageIn *msg)
}
}
break;
-
- //Stop walking
- //case 0x0088: // Disabled because giving some problems
- //if (being = beingManager->findBeing(readInt32(2))) {
- // if (being->getId() != player_node->getId()) {
- // being->action = STAND;
- // being->mFrame = 0;
- // set_coordinates(being->coordinates,
- // readWord(6), readWord(8),
- // get_direction(being->coordinates));
- // }
- //}
- //break;
}
}
diff --git a/src/net/protocol.h b/src/net/protocol.h
index b70834c6..e9053451 100644
--- a/src/net/protocol.h
+++ b/src/net/protocol.h
@@ -22,8 +22,12 @@
#ifndef PROTOCOL_
#define PROTOCOL_
-// Packets from server to client
+/*********************************
+ * Packets from server to client *
+ *********************************/
#define SMSG_LOGIN_SUCCESS 0x0073 /**< Contains starting location */
+#define SMSG_SERVER_PING 0x007f /**< Contains server tick */
+#define SMSG_CONNECTION_PROBLEM 0x0081
#define SMSG_UPDATE_HOST 0x0063 /**< Custom update host packet */
#define SMSG_PLAYER_UPDATE_1 0x01d8
#define SMSG_PLAYER_UPDATE_2 0x01d9
@@ -66,6 +70,7 @@
#define SMSG_BEING_ACTION 0x008a /**< Attack, sit, stand up, ... */
#define SMSG_BEING_CHAT 0x008d /**< A being talks */
#define SMSG_BEING_NAME_RESPONSE 0x0095 /**< Has to be requested */
+
#define SMSG_NPC_MESSAGE 0x00b4
#define SMSG_NPC_NEXT 0x00b5
#define SMSG_NPC_CLOSE 0x00b6
@@ -82,6 +87,7 @@
#define SMSG_WHISPER_RESPONSE 0x0098
#define SMSG_GM_CHAT 0x009a /**< GM announce */
#define SMSG_WALK_RESPONSE 0x0087
+
#define SMSG_TRADE_REQUEST 0x00e5 /**< Receiving a request to trade */
#define SMSG_TRADE_RESPONSE 0x00e7
#define SMSG_TRADE_ITEM_ADD 0x00e9
@@ -90,7 +96,27 @@
#define SMSG_TRADE_CANCEL 0x00ee
#define SMSG_TRADE_COMPLETE 0x00f0
-// Packets from client to server
+#define SMSG_PARTY_CREATE 0x00fa
+#define SMSG_PARTY_INFO 0x00fb
+#define SMSG_PARTY_INVITE 0x00fd
+#define SMSG_PARTY_INVITED 0x00fe
+#define SMSG_PARTY_SETTINGS 0x0102
+#define SMSG_PARTY_MEMBER_INFO 0x0104
+#define SMSG_PARTY_LEAVE 0x0105
+#define SMSG_PARTY_UPDATE_HP 0x0106
+#define SMSG_PARTY_UPDATE_COORDS 0x0107
+#define SMSG_PARTY_MESSAGE 0x0109
+
+#define SMSG_PLAYER_STORAGE_ITEMS 0x01f0 /**< Item list for storage */
+#define SMSG_PLAYER_STORAGE_EQUIP 0x00a6 /**< Equipment list for storage */
+#define SMSG_PLAYER_STORAGE_STATUS 0x00f2 /**< Slots used and total slots */
+#define SMSG_PLAYER_STORAGE_ADD 0x00f4 /**< Add item/equip to storage */
+#define SMSG_PLAYER_STORAGE_REMOVE 0x00f6 /**< Remove item/equip from storage */
+#define SMSG_PLAYER_STORAGE_CLOSE 0x00f8 /**< Storage access closed */
+
+/**********************************
+ * Packets from client to server *
+ **********************************/
#define CMSG_CLIENT_PING 0x007e /**< Send to server with tick */
#define CMSG_TRADE_RESPONSE 0x00e6
#define CMSG_ITEM_PICKUP 0x009f
@@ -99,6 +125,8 @@
#define CMSG_NPC_BUY_SELL_REQUEST 0x00c5
#define CMSG_CHAT_MESSAGE 0x008c
#define CMSG_CHAT_WHISPER 0x0096
+#define CMSG_CHAT_ANNOUNCE 0x0099
+#define CMSG_CHAT_WHO 0x00c1
#define CMSG_NPC_LIST_CHOICE 0x00b8
#define CMSG_NPC_NEXT_REQUEST 0x00b9
#define CMSG_NPC_SELL_REQUEST 0x00c9
@@ -117,6 +145,17 @@
#define CMSG_PLAYER_EQUIP 0x00a9
#define CMSG_PLAYER_UNEQUIP 0x00ab
+#define CMSG_PARTY_CREATE 0x00f9
+#define CMSG_PARTY_INVITE 0x00fc
+#define CMSG_PARTY_INVITED 0x00ff
+#define CMSG_PARTY_LEAVE 0x0100 /** Undocumented */
+#define CMSG_PARTY_SETTINGS 0x0101
+#define CMSG_PARTY_MESSAGE 0x0108
+
+#define CMSG_MOVE_TO_STORAGE 0x00f3 /** Move item to storage */
+#define CSMG_MOVE_FROM_STORAGE 0x00f5 /** Remove item from storage */
+#define CMSG_CLOSE_STORAGE 0x00f7 /** Request storage close */
+
/** Encodes coords and direction in 3 bytes data */
void set_coordinates(char *data, unsigned short x, unsigned short y, unsigned char direction);
diff --git a/src/net/skillhandler.cpp b/src/net/skillhandler.cpp
index 17b1f117..e2185524 100644
--- a/src/net/skillhandler.cpp
+++ b/src/net/skillhandler.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "skillhandler.h"
-
#include "messagein.h"
#include "protocol.h"
+#include "skillhandler.h"
#include "../log.h"
diff --git a/src/net/tradehandler.cpp b/src/net/tradehandler.cpp
index da493302..c5465835 100644
--- a/src/net/tradehandler.cpp
+++ b/src/net/tradehandler.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "tradehandler.h"
-
#include "messagein.h"
#include "protocol.h"
+#include "tradehandler.h"
#include "../inventory.h"
#include "../item.h"
@@ -33,6 +32,8 @@
#include "../gui/confirm_dialog.h"
#include "../gui/trade.h"
+#include "../utils/gettext.h"
+
std::string tradePartnerName;
/**
@@ -87,9 +88,9 @@ void TradeHandler::handleMessage(MessageIn *msg)
player_node->setTrading(true);
ConfirmDialog *dlg;
- dlg = new ConfirmDialog("Request for trade",
+ dlg = new ConfirmDialog(_("Request for trade"),
tradePartnerName +
- " wants to trade with you, do you accept?");
+ _(" wants to trade with you, do you accept?"));
dlg->addActionListener(&listener);
}
else
@@ -103,37 +104,35 @@ void TradeHandler::handleMessage(MessageIn *msg)
switch (msg->readInt8())
{
case 0: // Too far away
- chatWindow->chatLog("Trading isn't possible. "
- "Trade partner is too far away.",
+ chatWindow->chatLog(_("Trading isn't possible. Trade partner is too far away."),
BY_SERVER);
break;
case 1: // Character doesn't exist
- chatWindow->chatLog("Trading isn't possible. "
- "Character doesn't exist.",
+ chatWindow->chatLog(_("Trading isn't possible. Character doesn't exist."),
BY_SERVER);
break;
case 2: // Invite request check failed...
- chatWindow->chatLog("Trade cancelled due to an "
- "unknown reason.", BY_SERVER);
+ chatWindow->chatLog(_("Trade cancelled due to an unknown reason."),
+ BY_SERVER);
break;
case 3: // Trade accepted
tradeWindow->reset();
tradeWindow->setCaption(
- "Trade: You and " + tradePartnerName);
+ _("Trade: You and ") + tradePartnerName);
tradeWindow->setVisible(true);
break;
case 4: // Trade cancelled
if (player_relations.hasPermission(tradePartnerName,
PlayerRelation::SPEECH_LOG))
- chatWindow->chatLog("Trade with " + tradePartnerName +
- " cancelled", BY_SERVER);
+ chatWindow->chatLog(_("Trade with ") + tradePartnerName +
+ _(" cancelled"), BY_SERVER);
// otherwise ignore silently
tradeWindow->setVisible(false);
player_node->setTrading(false);
break;
default: // Shouldn't happen as well, but to be sure
- chatWindow->chatLog("Unhandled trade cancel packet",
+ chatWindow->chatLog(_("Unhandled trade cancel packet"),
BY_SERVER);
break;
}
@@ -183,19 +182,17 @@ void TradeHandler::handleMessage(MessageIn *msg)
break;
case 1:
// Add item failed - player overweighted
- chatWindow->chatLog("Failed adding item. Trade "
- "partner is over weighted.",
+ chatWindow->chatLog(_("Failed adding item. Trade partner is over weighted."),
BY_SERVER);
break;
case 2:
- // Add item failed - player has no free slot
- chatWindow->chatLog("Failed adding item. Trade "
- "partner has no free slot.",
- BY_SERVER);
- break;
+ // Add item failed - player has no free slot
+ chatWindow->chatLog(_("Failed adding item. Trade partner has no free slot."),
+ BY_SERVER);
+ break;
default:
- chatWindow->chatLog("Failed adding item for "
- "unknown reason.", BY_SERVER);
+ chatWindow->chatLog(_("Failed adding item for unknown reason."),
+ BY_SERVER);
break;
}
}
@@ -207,14 +204,14 @@ void TradeHandler::handleMessage(MessageIn *msg)
break;
case SMSG_TRADE_CANCEL:
- chatWindow->chatLog("Trade canceled.", BY_SERVER);
+ chatWindow->chatLog(_("Trade canceled."), BY_SERVER);
tradeWindow->setVisible(false);
tradeWindow->reset();
player_node->setTrading(false);
break;
case SMSG_TRADE_COMPLETE:
- chatWindow->chatLog("Trade completed.", BY_SERVER);
+ chatWindow->chatLog(_("Trade completed."), BY_SERVER);
tradeWindow->setVisible(false);
tradeWindow->reset();
player_node->setTrading(false);
diff --git a/src/npc.cpp b/src/npc.cpp
index aed6d87b..dfbc7d16 100644
--- a/src/npc.cpp
+++ b/src/npc.cpp
@@ -19,15 +19,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "npc.h"
-
#include "animatedsprite.h"
-#include "graphics.h"
+#include "localplayer.h"
+#include "npc.h"
#include "particle.h"
#include "text.h"
#include "net/messageout.h"
#include "net/protocol.h"
+
#include "resources/npcdb.h"
NPC *current_npc = 0;
@@ -36,7 +36,7 @@ static const int NAME_X_OFFSET = 15;
static const int NAME_Y_OFFSET = 30;
NPC::NPC(Uint32 id, Uint16 job, Map *map, Network *network):
- Being(id, job, map), mNetwork(network)
+ Player(id, job, map), mNetwork(network)
{
NPCInfo info = NPCDB::get(job);
@@ -54,28 +54,53 @@ NPC::NPC(Uint32 id, Uint16 job, Map *map, Network *network):
c++;
}
- // Setup particle effects
- for (std::list<std::string>::const_iterator i = info.particles.begin();
- i != info.particles.end();
- i++)
+ if (mParticleEffects)
{
- Particle *p = particleEngine->addEffect(*i, 0, 0);
- this->controlParticle(p);
+ //setup particle effects
+ for (std::list<std::string>::const_iterator i = info.particles.begin();
+ i != info.particles.end();
+ i++)
+ {
+ Particle *p = particleEngine->addEffect(*i, 0, 0);
+ this->controlParticle(p);
+ }
}
mName = 0;
+
+ mNameColor = 0x21bbbb;
}
NPC::~NPC()
{
- delete mName;
+ if (mName)
+ {
+ delete mName;
+ player_node->setTarget(NULL);
+ }
}
void NPC::setName(const std::string &name)
{
- delete mName;
- mName = new Text(name, mPx + NAME_X_OFFSET, mPy + NAME_Y_OFFSET,
- gcn::Graphics::CENTER,
- gcn::Color(200, 200, 255));
+ if (mName)
+ {
+ delete mName;
+ }
+ std::string displayName = name.substr(0, name.find('#', 0));
+
+ mName = new Text(displayName, mPx + NAME_X_OFFSET, mPy + NAME_Y_OFFSET,
+ gcn::Graphics::CENTER, gcn::Color(200, 200, 255));
+ Being::setName(displayName + " (NPC)");
+}
+
+void NPC::setGender(Gender gender)
+{
+ Being::setGender(gender);
+}
+
+void NPC::setSprite(int slot, int id, std::string color)
+{
+ // Fix this later should it not be adequate enough.
+ Being::setSprite(slot, id, color);
}
Being::Type NPC::getType() const
diff --git a/src/npc.h b/src/npc.h
index 7c3baf6d..dd8d7f5d 100644
--- a/src/npc.h
+++ b/src/npc.h
@@ -22,13 +22,13 @@
#ifndef NPC_H
#define NPC_H
-#include "being.h"
+#include "player.h"
class Network;
class Graphics;
class Text;
-class NPC : public Being
+class NPC : public Player
{
public:
NPC(Uint32 id, Uint16 job, Map *map, Network *network);
@@ -36,9 +36,10 @@ class NPC : public Being
~NPC();
void setName(const std::string &name);
+ void setGender(Gender gender);
+ void setSprite(int slot, int id, std::string color);
- virtual Type
- getType() const;
+ virtual Type getType() const;
void talk();
void nextDialog();
diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp
index 01208c36..e7e7b204 100644
--- a/src/openglgraphics.cpp
+++ b/src/openglgraphics.cpp
@@ -19,30 +19,23 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "main.h"
-
-#ifdef USE_OPENGL
-
-#ifndef GL_TEXTURE_RECTANGLE_ARB
-#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
-#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
-#endif
+#include <SDL.h>
+#include "log.h"
#include "openglgraphics.h"
-#include <cstring>
-#include <SDL.h>
+#include "resources/image.h"
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#endif
-#include <guichan/exception.hpp>
-#include <guichan/image.hpp>
-
-#include "log.h"
+#ifdef USE_OPENGL
-#include "resources/image.h"
+#ifndef GL_TEXTURE_RECTANGLE_ARB
+#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#endif
OpenGLGraphics::OpenGLGraphics():
mAlpha(false), mTexture(false), mColorAlpha(false),
diff --git a/src/particle.cpp b/src/particle.cpp
index 99a4dd36..45cbb4c9 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -22,13 +22,14 @@
#include <algorithm>
#include <cmath>
-#include "particle.h"
+#include <guichan/color.hpp>
#include "animationparticle.h"
#include "configuration.h"
#include "imageparticle.h"
#include "log.h"
#include "map.h"
+#include "particle.h"
#include "particleemitter.h"
#include "textparticle.h"
@@ -251,7 +252,7 @@ void Particle::moveTo(float x, float y)
}
Particle *Particle::addEffect(const std::string &particleEffectFile,
- int pixelX, int pixelY)
+ int pixelX, int pixelY, int rotation)
{
Particle *newParticle = NULL;
@@ -313,7 +314,7 @@ Particle *Particle::addEffect(const std::string &particleEffectFile,
continue;
ParticleEmitter *newEmitter;
- newEmitter = new ParticleEmitter(emitterNode, newParticle, mMap);
+ newEmitter = new ParticleEmitter(emitterNode, newParticle, mMap, rotation);
newParticle->addEmitter(newEmitter);
}
diff --git a/src/particle.h b/src/particle.h
index 43fdda01..e79a46dd 100644
--- a/src/particle.h
+++ b/src/particle.h
@@ -25,8 +25,6 @@
#include <list>
#include <string>
-#include <guichan/color.hpp>
-
#include "guichanfwd.h"
#include "sprite.h"
#include "vector.h"
@@ -102,7 +100,7 @@ class Particle : public Sprite
* particleEffectFile.
*/
Particle *addEffect(const std::string &particleEffectFile,
- int pixelX, int pixelY);
+ int pixelX, int pixelY, int rotation = 0);
/**
* Creates a standalone text particle.
diff --git a/src/particlecontainer.cpp b/src/particlecontainer.cpp
index c570d6d3..63f89079 100644
--- a/src/particlecontainer.cpp
+++ b/src/particlecontainer.cpp
@@ -21,6 +21,7 @@
#include <cassert>
+#include "particle.h"
#include "particlecontainer.h"
@@ -44,7 +45,6 @@ void ParticleContainer::clear()
mNext->clear();
}
-
void ParticleContainer::moveTo(float x, float y)
{
if (mNext)
@@ -109,9 +109,6 @@ void ParticleList::moveTo(float x, float y)
}
}
-
-
-
// -- particle vector ----------------------------------------
ParticleVector::ParticleVector(ParticleContainer *parent, bool delParent):
diff --git a/src/particlecontainer.h b/src/particlecontainer.h
index 27e02f8b..26539dd7 100644
--- a/src/particlecontainer.h
+++ b/src/particlecontainer.h
@@ -25,8 +25,7 @@
#include <list>
#include <vector>
-#include "particle.h"
-
+class Particle;
/**
* Set of particle effects. May be stacked with other ParticleContainers. All
@@ -65,8 +64,6 @@ protected:
ParticleContainer *mNext; /**< Contained container, if any */
};
-
-
/**
* Linked list of particle effects.
*/
@@ -94,7 +91,6 @@ protected:
std::list<Particle *> mElements; /**< Contained particle effects */
};
-
/**
* Particle container with indexing facilities
*/
diff --git a/src/particleemitter.cpp b/src/particleemitter.cpp
index 076bd740..25e6ade5 100644
--- a/src/particleemitter.cpp
+++ b/src/particleemitter.cpp
@@ -19,31 +19,29 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "particleemitter.h"
+#include <cmath>
#include "animationparticle.h"
#include "imageparticle.h"
#include "log.h"
#include "particle.h"
+#include "particleemitter.h"
-#include "resources/animation.h"
#include "resources/image.h"
-#include "resources/resourcemanager.h"
#include "resources/imageset.h"
-
-#include <cmath>
+#include "resources/resourcemanager.h"
#define SIN45 0.707106781f
#define DEG_RAD_FACTOR 0.017453293f
-ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *map):
+ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *map, int rotation):
mOutputPauseLeft(0),
mParticleImage(0)
{
mMap = map;
mParticleTarget = target;
- //initializing default values
+ // Initializing default values
mParticlePosX.set(0.0f);
mParticlePosY.set(0.0f);
mParticlePosZ.set(0.0f);
@@ -93,7 +91,7 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *
{
std::string image = XML::getProperty(propertyNode, "value", "");
// Don't leak when multiple images are defined
- if (image != "" && !mParticleImage)
+ if (!image.empty() && !mParticleImage)
{
ResourceManager *resman = ResourceManager::getInstance();
mParticleImage = resman->getImage(image);
@@ -102,7 +100,9 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *
else if (name == "horizontal-angle")
{
mParticleAngleHorizontal = readParticleEmitterProp(propertyNode, 0.0f);
+ mParticleAngleHorizontal.minVal += rotation;
mParticleAngleHorizontal.minVal *= DEG_RAD_FACTOR;
+ mParticleAngleHorizontal.maxVal += rotation;
mParticleAngleHorizontal.maxVal *= DEG_RAD_FACTOR;
mParticleAngleHorizontal.changeAmplitude *= DEG_RAD_FACTOR;
}
@@ -310,26 +310,25 @@ ParticleEmitter::readParticleEmitterProp(xmlNodePtr propertyNode, T def)
retval.set((T) XML::getFloatProperty(propertyNode, "min", (double) def),
(T) XML::getFloatProperty(propertyNode, "max", (double) def));
- std::string change = XML::getProperty(propertyNode, "change-func", "none");
- T amplitude = (T) XML::getFloatProperty(propertyNode, "change-amplitude", 0.0);
- int period = XML::getProperty(propertyNode, "change-period", 0);
- int phase = XML::getProperty(propertyNode, "change-phase", 0);
- if (change == "saw" || change == "sawtooth") {
- retval.setFunction(FUNC_SAW, amplitude, period, phase);
- } else if (change == "sine" || change == "sinewave") {
- retval.setFunction(FUNC_SINE, amplitude, period, phase);
- } else if (change == "triangle") {
- retval.setFunction(FUNC_TRIANGLE, amplitude, period, phase);
- } else if (change == "square"){
- retval.setFunction(FUNC_SQUARE, amplitude, period, phase);
- }
+ std::string change = XML::getProperty(propertyNode, "change-func", "none");
+ T amplitude = (T) XML::getFloatProperty(propertyNode, "change-amplitude", 0.0);
+ int period = XML::getProperty(propertyNode, "change-period", 0);
+ int phase = XML::getProperty(propertyNode, "change-phase", 0);
+ if (change == "saw" || change == "sawtooth") {
+ retval.setFunction(FUNC_SAW, amplitude, period, phase);
+ } else if (change == "sine" || change == "sinewave") {
+ retval.setFunction(FUNC_SINE, amplitude, period, phase);
+ } else if (change == "triangle") {
+ retval.setFunction(FUNC_TRIANGLE, amplitude, period, phase);
+ } else if (change == "square"){
+ retval.setFunction(FUNC_SQUARE, amplitude, period, phase);
+ }
return retval;
}
-std::list<Particle *>
-ParticleEmitter::createParticles(int tick)
+std::list<Particle *> ParticleEmitter::createParticles(int tick)
{
std::list<Particle *> newParticles;
diff --git a/src/particleemitter.h b/src/particleemitter.h
index 593ecb3a..67b35ae2 100644
--- a/src/particleemitter.h
+++ b/src/particleemitter.h
@@ -26,10 +26,10 @@
#include "utils/xml.h"
-#include "resources/animation.h"
-
#include "particleemitterprop.h"
+#include "resources/animation.h"
+
class Image;
class Map;
class Particle;
@@ -44,7 +44,7 @@ class ParticleEmitter
/**
* Constructor.
*/
- ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *map);
+ ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *map, int rotation = 0);
/**
* Copy Constructor (necessary for reference counting of particle images)
@@ -70,8 +70,7 @@ class ParticleEmitter
/**
* Sets the target of the particles that are created
*/
- void
- setTarget(Particle *target)
+ void setTarget(Particle *target)
{ mParticleTarget = target; };
private:
diff --git a/src/particleemitterprop.h b/src/particleemitterprop.h
index d9b6350f..e68ac222 100644
--- a/src/particleemitterprop.h
+++ b/src/particleemitterprop.h
@@ -19,7 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <cstdlib>
#include <cmath>
/**
diff --git a/src/party.cpp b/src/party.cpp
new file mode 100644
index 00000000..589aa9b1
--- /dev/null
+++ b/src/party.cpp
@@ -0,0 +1,217 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "being.h"
+#include "localplayer.h"
+#include "party.h"
+
+#include "gui/chat.h"
+#include "gui/confirm_dialog.h"
+
+#include "net/messageout.h"
+#include "net/protocol.h"
+
+#include "utils/gettext.h"
+#include "utils/strprintf.h"
+
+Party::Party(ChatWindow *chat, Network *network) :
+ mChat(chat),
+ mNetwork(network),
+ mInviteListener(network, &mInParty)
+{
+}
+
+void Party::respond(const std::string &command, const std::string &args)
+{
+ if (command == "new" || command == "create")
+ {
+ create(args);
+ return;
+ }
+ if (command == "leave")
+ {
+ leave(args);
+ return;
+ }
+ if (command == "settings")
+ {
+ mChat->chatLog(_("Not yet implemented!"), BY_SERVER);
+ return;
+ /*
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PARTY_SETTINGS);
+ outMsg.writeInt16(0); // Experience
+ outMsg.writeInt16(0); // Item
+ */
+ }
+ mChat->chatLog(_("Party command not known."), BY_SERVER);
+}
+
+void Party::create(const std::string &party)
+{
+ if (party.empty())
+ {
+ mChat->chatLog(_("Party name is missing."), BY_SERVER);
+ return;
+ }
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PARTY_CREATE);
+ outMsg.writeString(party.substr(0, 23), 24);
+ mCreating = true;
+}
+
+void Party::leave(const std::string &args)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PARTY_LEAVE);
+ mChat->chatLog(_("Left party."), BY_SERVER);
+ mInParty = false;
+}
+
+void Party::createResponse(bool ok)
+{
+ if (ok)
+ {
+ mChat->chatLog(_("Party successfully created."), BY_SERVER);
+ mInParty = true;
+ }
+ else
+ {
+ mChat->chatLog(_("Could not create party."), BY_SERVER);
+ }
+}
+
+void Party::inviteResponse(const std::string &nick, int status)
+{
+ switch (status)
+ {
+ case 0:
+ mChat->chatLog(strprintf(_("%s is already a member of a party."),
+ nick.c_str()), BY_SERVER);
+ break;
+ case 1:
+ mChat->chatLog(strprintf(_("%s refused your invitation."),
+ nick.c_str()), BY_SERVER);
+ break;
+ case 2:
+ mChat->chatLog(strprintf(_("%s is now a member of your party."),
+ nick.c_str()), BY_SERVER);
+ break;
+ }
+}
+
+void Party::invitedAsk(const std::string &nick, int gender,
+ const std::string &partyName)
+{
+ mPartyName = partyName; /* Quick and nasty - needs redoing */
+ if (nick.empty())
+ {
+ mChat->chatLog(_("You can\'t have a blank party name!"), BY_SERVER);
+ return;
+ }
+ mCreating = false;
+ ConfirmDialog *dlg = new ConfirmDialog(_("Invite to party"),
+ strprintf(_("%s invites you to join"
+ " the %s party, do you accept?"),
+ nick.c_str(), partyName.c_str()));
+ dlg->addActionListener(&mInviteListener);
+}
+
+void Party::InviteListener::action(const gcn::ActionEvent &event)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PARTY_INVITED);
+ outMsg.writeInt32(player_node->getId());
+ bool accept = event.getId() == "yes";
+ outMsg.writeInt32(accept ? 1 : 0);
+ *mInParty = *mInParty || accept;
+}
+
+void Party::leftResponse(const std::string &nick)
+{
+ mChat->chatLog(strprintf(_("%s has left your party."), nick.c_str()),
+ BY_SERVER);
+}
+
+void Party::receiveChat(Being *being, const std::string &msg)
+{
+ if (!being)
+ {
+ return;
+ }
+ if (being->getType() != Being::PLAYER)
+ {
+ mChat->chatLog(_("Party chat received, but being is not a player"),
+ BY_SERVER);
+ return;
+ }
+ being->setSpeech(msg, SPEECH_TIME);
+ mChat->chatLog(being->getName() + " : " + msg, BY_PARTY);
+}
+
+void Party::help(const std::string &msg)
+{
+ if (msg.empty())
+ {
+ mChat->chatLog(_("Command: /party <command> <args>"), BY_SERVER);
+ mChat->chatLog(_("where <command> can be one of:"), BY_SERVER);
+ mChat->chatLog(_(" /new"), BY_SERVER);
+ mChat->chatLog(_(" /create"), BY_SERVER);
+ mChat->chatLog(_(" /prefix"), BY_SERVER);
+ mChat->chatLog(_(" /leave"), BY_SERVER);
+ mChat->chatLog(_("This command implements the partying function."),
+ BY_SERVER);
+ mChat->chatLog(_("Type /help party <command> for further help."),
+ BY_SERVER);
+ return;
+ }
+ if (msg == "new" || msg == "create")
+ {
+ mChat->chatLog(_("Command: /party new <party-name>"), BY_SERVER);
+ mChat->chatLog(_("Command: /party create <party-name>"), BY_SERVER);
+ mChat->chatLog(_("These commands create a new party <party-name."),
+ BY_SERVER);
+ return;
+ }
+ if (msg == "prefix")
+ {
+ mChat->chatLog(_("Command: /party prefix <prefix-char>"), BY_SERVER);
+ mChat->chatLog(_("This command sets the party prefix character."),
+ BY_SERVER);
+ mChat->chatLog(_("Any message preceded by <prefix-char> is sent to "
+ "the party instead of everyone."), BY_SERVER);
+ mChat->chatLog(_("Command: /party prefix"), BY_SERVER);
+ mChat->chatLog(_("This command reports the current party prefix "
+ "character."), BY_SERVER);
+ return;
+ }
+ //if (msg == "settings")
+ //if (msg == "info")
+ if (msg == "leave")
+ {
+ mChat->chatLog(_("Command: /party leave"), BY_SERVER);
+ mChat->chatLog(_("This command causes the player to leave the party."),
+ BY_SERVER);
+ return;
+ }
+ mChat->chatLog(_("Unknown /party command."), BY_SERVER);
+ mChat->chatLog(_("Type /help party for a list of options."), BY_SERVER);
+}
diff --git a/src/party.h b/src/party.h
new file mode 100644
index 00000000..98252c37
--- /dev/null
+++ b/src/party.h
@@ -0,0 +1,76 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PARTY_H
+#define PARTY_H
+
+#include <string>
+
+#include <guichan/actionlistener.hpp>
+
+class PartyHandler;
+class Being;
+class ChatWindow;
+class Network;
+
+class Party
+{
+ public:
+ Party(ChatWindow *chat, Network *network);
+ void respond(const std::string &command, const std::string &args);
+
+ void create(const std::string &party);
+ void leave(const std::string &args);
+
+ void createResponse(bool ok);
+ void inviteResponse(const std::string &nick, int status);
+ void invitedAsk(const std::string &nick, int gender,
+ const std::string &partyName);
+ void leftResponse(const std::string &nick);
+ void receiveChat(Being *being, const std::string &msg);
+
+ void help(const std::string &msg);
+
+ private:
+ ChatWindow *mChat;
+ std::string mPartyName;
+ Network *mNetwork;
+ bool mInParty;
+ bool mCreating; /**< Used to give an appropriate response to
+ failure */
+ PartyHandler *handler;
+
+ class InviteListener : public gcn::ActionListener
+ {
+ public:
+ InviteListener(Network *network, bool *inParty) :
+ mNetwork(network),
+ mInParty(inParty)
+ {}
+ void action(const gcn::ActionEvent &event);
+ Network *mNetwork;
+ private:
+ bool *mInParty;
+ };
+ InviteListener mInviteListener;
+};
+
+#endif
diff --git a/src/player.cpp b/src/player.cpp
index 5ab94595..a2a263b3 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -19,20 +19,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "player.h"
-
#include "animatedsprite.h"
#include "game.h"
-#include "graphics.h"
-#include "log.h"
+#include "player.h"
+#include "text.h"
+#include "resources/colordb.h"
#include "resources/itemdb.h"
-#include "resources/iteminfo.h"
#include "utils/strprintf.h"
-#include <iostream>
-
static const int NAME_X_OFFSET = 15;
static const int NAME_Y_OFFSET = 30;
@@ -44,19 +40,25 @@ Player::Player(int id, int job, Map *map):
Player::~Player()
{
- if (mName)
- {
- delete mName;
- }
+ delete mName;
}
void Player::setName(const std::string &name)
{
if (mName == 0)
{
- mName = new FlashText(name, mPx + NAME_X_OFFSET, mPy + NAME_Y_OFFSET,
- gcn::Graphics::CENTER,
- gcn::Color(255, 255, 255));
+ if (mIsGM)
+ {
+ mNameColor = 0x009000;
+ mName = new FlashText("(GM) " + name, mPx + NAME_X_OFFSET, mPy + NAME_Y_OFFSET,
+ gcn::Graphics::CENTER, gcn::Color(0, 255, 0));
+ }
+ else
+ {
+ mNameColor = 0x202020;
+ mName = new FlashText(name, mPx + NAME_X_OFFSET, mPy + NAME_Y_OFFSET,
+ gcn::Graphics::CENTER, gcn::Color(255, 255, 255));
+ }
Being::setName(name);
}
}
@@ -64,6 +66,18 @@ void Player::setName(const std::string &name)
void Player::logic()
{
switch (mAction) {
+ case STAND:
+ break;
+
+ case SIT:
+ break;
+
+ case DEAD:
+ break;
+
+ case HURT:
+ break;
+
case WALK:
mFrame = (get_elapsed_time(mWalkTime) * 6) / mWalkSpeed;
if (mFrame >= 6) {
@@ -126,13 +140,13 @@ void Player::setGender(Gender gender)
void Player::setHairStyle(int style, int color)
{
- style = style < 0 ? mHairStyle : style % getHairStylesNr();
- color = color < 0 ? mHairColor : color % getHairColorsNr();
+ style = style < 0 ? mHairStyle : style % mNumberOfHairstyles;
+ color = color < 0 ? mHairColor : color % ColorDB::size();
if (style == mHairStyle && color == mHairColor) return;
Being::setHairStyle(style, color);
- setSprite(HAIR_SPRITE, style * -1, getHairColor(color));
+ setSprite(HAIR_SPRITE, style * -1, ColorDB::get(color));
setAction(mAction);
}
@@ -155,11 +169,12 @@ void Player::setSprite(int slot, int id, std::string color)
std::string filename = ItemDB::get(id).getSprite(mGender);
AnimatedSprite *equipmentSprite = NULL;
- if (filename != "")
+ if (!filename.empty())
{
- if (color!="") filename += "|" + color;
+ if (!color.empty())
+ filename += "|" + color;
equipmentSprite = AnimatedSprite::load(
- "graphics/sprites/" + filename);
+ "graphics/sprites/" + filename);
}
if (equipmentSprite)
@@ -187,4 +202,3 @@ void Player::updateCoords()
}
}
-
diff --git a/src/player.h b/src/player.h
index 7fe2a09c..f9911bb8 100644
--- a/src/player.h
+++ b/src/player.h
@@ -23,8 +23,8 @@
#define PLAYER_H
#include "being.h"
-#include "text.h"
+class FlashText;
class Graphics;
class Map;
@@ -43,17 +43,13 @@ class Player : public Being
/**
* Set up mName to be the character's name
*/
- virtual void
- setName(const std::string &name);
+ virtual void setName(const std::string &name);
- virtual void
- logic();
+ virtual void logic();
- virtual Type
- getType() const;
+ virtual Type getType() const;
- virtual void
- setGender(Gender gender);
+ virtual void setGender(Gender gender);
/**
* Sets the hair style and color for this player.
@@ -70,8 +66,7 @@ class Player : public Being
/**
* Sets visible equipments for this player.
*/
- virtual void
- setSprite(int slot, int id, std::string color = "");
+ virtual void setSprite(int slot, int id, std::string color = "");
/**
* Flash the player's name
@@ -79,9 +74,8 @@ class Player : public Being
void flash(int time);
protected:
- void updateCoords();
+ virtual void updateCoords();
- private:
FlashText *mName;
};
diff --git a/src/player_relations.cpp b/src/player_relations.cpp
index 09859c59..c82876e1 100644
--- a/src/player_relations.cpp
+++ b/src/player_relations.cpp
@@ -19,12 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <algorithm>
+
+#include "being.h"
#include "beingmanager.h"
-#include "player_relations.h"
+#include "configuration.h"
#include "graphics.h"
-#include "gui/gui.h"
-
-#include <algorithm>
+#include "player.h"
+#include "player_relations.h"
#define PLAYER_IGNORE_STRATEGY_NOP "nop"
#define PLAYER_IGNORE_STRATEGY_EMOTE0 "emote0"
@@ -56,7 +58,7 @@ class PlayerConfSerialiser : public ConfigurationListManager<std::pair<std::stri
std::map<std::string, PlayerRelation *> *container)
{
std::string name = cobj->getValue(NAME, "");
- if (name == "")
+ if (name.empty())
return container;
if (!(*container)[name]) {
@@ -90,8 +92,7 @@ PlayerRelationsManager::PlayerRelationsManager() :
{
}
-void
-PlayerRelationsManager::clear()
+void PlayerRelationsManager::clear()
{
std::vector<std::string> *names = getPlayers();
for (std::vector<std::string>::const_iterator
@@ -104,8 +105,7 @@ PlayerRelationsManager::clear()
#define PLAYER_IGNORE_STRATEGY "player-ignore-strategy"
#define DEFAULT_PERMISSIONS "default-player-permissions"
-int
-PlayerRelationsManager::getPlayerIgnoreStrategyIndex(const std::string &name)
+int PlayerRelationsManager::getPlayerIgnoreStrategyIndex(const std::string &name)
{
std::vector<PlayerIgnoreStrategy *> *strategies = getPlayerIgnoreStrategies();
for (unsigned int i = 0; i < strategies->size(); i++)
@@ -115,8 +115,7 @@ PlayerRelationsManager::getPlayerIgnoreStrategyIndex(const std::string &name)
return -1;
}
-void
-PlayerRelationsManager::load()
+void PlayerRelationsManager::load()
{
clear();
@@ -133,8 +132,7 @@ PlayerRelationsManager::load()
}
-void
-PlayerRelationsManager::init()
+void PlayerRelationsManager::init()
{
load();
@@ -142,8 +140,7 @@ PlayerRelationsManager::init()
clear(); // Yes, we still keep them around in the config file until the next update.
}
-void
-PlayerRelationsManager::store()
+void PlayerRelationsManager::store()
{
config.setList<std::map<std::string, PlayerRelation *>::const_iterator,
std::pair<std::string, PlayerRelation *>,
@@ -160,8 +157,7 @@ PlayerRelationsManager::store()
config.write();
}
-void
-PlayerRelationsManager::signalUpdate(const std::string &name)
+void PlayerRelationsManager::signalUpdate(const std::string &name)
{
store();
@@ -169,8 +165,7 @@ PlayerRelationsManager::signalUpdate(const std::string &name)
(*it)->updatedPlayer(name);
}
-unsigned int
-PlayerRelationsManager::checkPermissionSilently(const std::string &player_name, unsigned int flags)
+unsigned int PlayerRelationsManager::checkPermissionSilently(const std::string &player_name, unsigned int flags)
{
PlayerRelation *r = mRelations[player_name];
if (!r)
@@ -195,16 +190,14 @@ PlayerRelationsManager::checkPermissionSilently(const std::string &player_name,
}
}
-bool
-PlayerRelationsManager::hasPermission(Being *being, unsigned int flags)
+bool PlayerRelationsManager::hasPermission(Being *being, unsigned int flags)
{
if (being->getType() == Being::PLAYER)
return hasPermission(being->getName(), flags) == flags;
return true;
}
-bool
-PlayerRelationsManager::hasPermission(const std::string &name, unsigned int flags)
+bool PlayerRelationsManager::hasPermission(const std::string &name, unsigned int flags)
{
unsigned int rejections = flags & ~checkPermissionSilently(name, flags);
bool permitted = rejections == 0;
@@ -223,8 +216,7 @@ PlayerRelationsManager::hasPermission(const std::string &name, unsigned int flag
return permitted;
}
-void
-PlayerRelationsManager::setRelation(const std::string &player_name, PlayerRelation::relation relation)
+void PlayerRelationsManager::setRelation(const std::string &player_name, PlayerRelation::relation relation)
{
PlayerRelation *r = mRelations[player_name];
if (r == NULL)
@@ -235,8 +227,7 @@ PlayerRelationsManager::setRelation(const std::string &player_name, PlayerRelati
signalUpdate(player_name);
}
-std::vector<std::string> *
-PlayerRelationsManager::getPlayers()
+std::vector<std::string> * PlayerRelationsManager::getPlayers()
{
std::vector<std::string> *retval = new std::vector<std::string>();
@@ -249,8 +240,7 @@ PlayerRelationsManager::getPlayers()
return retval;
}
-void
-PlayerRelationsManager::removePlayer(const std::string &name)
+void PlayerRelationsManager::removePlayer(const std::string &name)
{
if (mRelations[name])
delete mRelations[name];
@@ -261,8 +251,7 @@ PlayerRelationsManager::removePlayer(const std::string &name)
}
-PlayerRelation::relation
-PlayerRelationsManager::getRelation(const std::string &name)
+PlayerRelation::relation PlayerRelationsManager::getRelation(const std::string &name)
{
if (mRelations[name])
return mRelations[name]->mRelation;
@@ -273,14 +262,12 @@ PlayerRelationsManager::getRelation(const std::string &name)
////////////////////////////////////////
// defaults
-unsigned int
-PlayerRelationsManager::getDefault() const
+unsigned int PlayerRelationsManager::getDefault() const
{
return mDefaultPermissions;
}
-void
-PlayerRelationsManager::setDefault(unsigned int permissions)
+void PlayerRelationsManager::setDefault(unsigned int permissions)
{
mDefaultPermissions = permissions;
@@ -302,8 +289,7 @@ public:
mShortName = PLAYER_IGNORE_STRATEGY_NOP;
}
- virtual void
- ignore(Player *player, unsigned int flags)
+ virtual void ignore(Player *player, unsigned int flags)
{
}
};
@@ -317,10 +303,9 @@ public:
mShortName = "dotdotdot";
}
- virtual void
- ignore(Player *player, unsigned int flags)
+ virtual void ignore(Player *player, unsigned int flags)
{
- player->setSpeech("...", 5);
+ player->setSpeech("...", 500);
}
};
@@ -334,8 +319,7 @@ public:
mShortName = "blinkname";
}
- virtual void
- ignore(Player *player, unsigned int flags)
+ virtual void ignore(Player *player, unsigned int flags)
{
player->flash(200);
}
@@ -351,8 +335,7 @@ public:
mShortName = shortname;
}
- virtual void
- ignore(Player *player, unsigned int flags)
+ virtual void ignore(Player *player, unsigned int flags)
{
player->setEmote(mEmotion, IGNORE_EMOTE_TIME);
}
diff --git a/src/player_relations.h b/src/player_relations.h
index 6cbaf6b3..1eb4ede6 100644
--- a/src/player_relations.h
+++ b/src/player_relations.h
@@ -22,13 +22,13 @@
#ifndef PLAYER_RELATIONS_H
#define PLAYER_RELATIONS_H
-#include "being.h"
-#include "player.h"
-#include "configuration.h"
-#include <string>
+#include <list>
#include <map>
+#include <string>
#include <vector>
-#include <list>
+
+class Being;
+class Player;
struct PlayerRelation
{
diff --git a/src/properties.h b/src/properties.h
index 016d607a..a2ce5b88 100644
--- a/src/properties.h
+++ b/src/properties.h
@@ -23,8 +23,8 @@
#define PROPERTIES_H
#include <map>
-#include <string>
#include <sstream>
+#include <string>
/**
* A class holding a set of properties.
diff --git a/src/resources/action.cpp b/src/resources/action.cpp
index 3fd3237e..e2cb11f2 100644
--- a/src/resources/action.cpp
+++ b/src/resources/action.cpp
@@ -20,12 +20,10 @@
*/
#include "action.h"
-
#include "animation.h"
#include "../utils/dtor.h"
-
Action::Action()
{
}
diff --git a/src/resources/action.h b/src/resources/action.h
index c557e6da..649d3828 100644
--- a/src/resources/action.h
+++ b/src/resources/action.h
@@ -44,11 +44,9 @@ class Action
*/
~Action();
- void
- setAnimation(int direction, Animation *animation);
+ void setAnimation(int direction, Animation *animation);
- Animation*
- getAnimation(int direction) const;
+ Animation* getAnimation(int direction) const;
protected:
typedef std::map<int, Animation*> Animations;
diff --git a/src/resources/ambientoverlay.cpp b/src/resources/ambientoverlay.cpp
index ef034acf..32ed47d1 100644
--- a/src/resources/ambientoverlay.cpp
+++ b/src/resources/ambientoverlay.cpp
@@ -20,7 +20,6 @@
*/
#include "ambientoverlay.h"
-
#include "image.h"
#include "../graphics.h"
diff --git a/src/resources/animation.cpp b/src/resources/animation.cpp
index 62e5ac16..54c319de 100644
--- a/src/resources/animation.cpp
+++ b/src/resources/animation.cpp
@@ -21,8 +21,6 @@
#include "animation.h"
-#include <algorithm>
-
#include "../utils/dtor.h"
Animation::Animation():
@@ -30,22 +28,19 @@ Animation::Animation():
{
}
-void
-Animation::addFrame(Image *image, unsigned int delay, int offsetX, int offsetY)
+void Animation::addFrame(Image *image, unsigned int delay, int offsetX, int offsetY)
{
Frame frame = { image, delay, offsetX, offsetY };
mFrames.push_back(frame);
mDuration += delay;
}
-void
-Animation::addTerminator()
+void Animation::addTerminator()
{
addFrame(NULL, 0, 0, 0);
}
-bool
-Animation::isTerminator(const Frame &candidate)
+bool Animation::isTerminator(const Frame &candidate)
{
return (candidate.image == NULL);
}
diff --git a/src/resources/animation.h b/src/resources/animation.h
index 29c99209..0c461ebe 100644
--- a/src/resources/animation.h
+++ b/src/resources/animation.h
@@ -54,39 +54,33 @@ class Animation
/**
* Appends a new animation at the end of the sequence.
*/
- void
- addFrame(Image *image, unsigned int delay, int offsetX, int offsetY);
+ void addFrame(Image *image, unsigned int delay, int offsetX, int offsetY);
/**
* Appends an animation terminator that states that the animation
* should not loop.
*/
- void
- addTerminator();
+ void addTerminator();
/**
* Returns the frame at the specified index.
*/
- Frame*
- getFrame(int index) { return &(mFrames[index]); }
+ Frame* getFrame(int index) { return &(mFrames[index]); }
/**
* Returns the length of this animation in frames.
*/
- unsigned int
- getLength() const { return mFrames.size(); }
+ unsigned int getLength() const { return mFrames.size(); }
/**
* Returns the duration of this animation.
*/
- int
- getDuration() const { return mDuration; }
+ int getDuration() const { return mDuration; }
/**
* Determines whether the given animation frame is a terminator.
*/
- static bool
- isTerminator(const Frame &phase);
+ static bool isTerminator(const Frame &phase);
protected:
std::vector<Frame> mFrames;
diff --git a/src/resources/buddylist.cpp b/src/resources/buddylist.cpp
index 24198f59..719ecab1 100644
--- a/src/resources/buddylist.cpp
+++ b/src/resources/buddylist.cpp
@@ -21,13 +21,13 @@
#include <algorithm>
#include <cstring>
-#include <iostream>
#include <fstream>
+#include <iostream>
#include "buddylist.h"
-#include "../main.h"
#include "../configuration.h"
+#include "../main.h"
BuddyList::BuddyList()
{
@@ -55,9 +55,9 @@ void BuddyList::loadFile()
char *buddy = new char[LEN_MAX_USERNAME];
inputStream.getline(buddy, LEN_MAX_USERNAME);
// Ugly ?
- if(strcmp(buddy,"")) mBuddylist.push_back(buddy);
+ if (strcmp(buddy, "")) mBuddylist.push_back(buddy);
delete [] buddy;
- } while(!inputStream.eof());
+ } while (!inputStream.eof());
// Read buddy and close file
inputStream.close();
@@ -111,7 +111,7 @@ bool BuddyList::removeBuddy(const std::string buddy)
return false;
}
-int BuddyList::getNumberOfElements()
+int BuddyList::getNumberOfElements()
{
return mBuddylist.size();
}
diff --git a/src/resources/buddylist.h b/src/resources/buddylist.h
index 33fcde4d..f0758c25 100644
--- a/src/resources/buddylist.h
+++ b/src/resources/buddylist.h
@@ -27,7 +27,8 @@
#include <guichan/listmodel.hpp>
-class BuddyList : public gcn::ListModel {
+class BuddyList : public gcn::ListModel
+{
public:
/**
* Constructor
@@ -52,7 +53,7 @@ class BuddyList : public gcn::ListModel {
/**
* Returns the number of buddy on the list
*/
- int getNumberOfElements();
+ int getNumberOfElements();
/**
* Returns the buddy of the number or null
diff --git a/src/resources/colordb.cpp b/src/resources/colordb.cpp
new file mode 100644
index 00000000..3a8754ea
--- /dev/null
+++ b/src/resources/colordb.cpp
@@ -0,0 +1,122 @@
+/*
+ * Color database
+ * Copyright (C) 2008 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <libxml/tree.h>
+
+#include "colordb.h"
+
+#include "../log.h"
+
+#include "../utils/xml.h"
+
+#define HAIR_COLOR_FILE "colors.xml"
+#define TMW_COLOR_FILE "hair.xml"
+
+namespace
+{
+ ColorDB::Colors mColors;
+ bool mLoaded = false;
+ std::string mFail = "#ffffff";
+}
+
+void ColorDB::load()
+{
+ if (mLoaded)
+ {
+ return;
+ }
+
+ XML::Document *doc = new XML::Document(HAIR_COLOR_FILE);
+ xmlNodePtr root = doc->rootNode();
+ bool TMWHair = false;
+
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "colors"))
+ {
+ logger->log("Trying TMW's color file, %s.", TMW_COLOR_FILE);
+
+ TMWHair = true;
+
+ delete doc;
+
+ doc = new XML::Document(TMW_COLOR_FILE);
+ root = doc->rootNode();
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "colors"))
+ {
+ logger->log("ColorDB: Failed");
+ mColors[0] = mFail;
+ mLoaded = true;
+
+ delete doc;
+
+ return;
+ }
+ }
+ for_each_xml_child_node(node, root)
+ {
+ if (xmlStrEqual(node->name, BAD_CAST "color"))
+ {
+ int id = XML::getProperty(node, "id", 0);
+
+ if (mColors.find(id) != mColors.end())
+ {
+ logger->log("ColorDB: Redefinition of dye ID %d", id);
+ }
+
+ TMWHair ? mColors[id] = XML::getProperty(node, "value", "#FFFFFF") :
+ mColors[id] = XML::getProperty(node, "dye", "#FFFFFF");
+ }
+ }
+
+ delete doc;
+
+ mLoaded = true;
+}
+
+void ColorDB::unload()
+{
+ logger->log("Unloading color database...");
+
+ mColors.clear();
+ mLoaded = false;
+}
+
+std::string& ColorDB::get(int id)
+{
+ if (!mLoaded)
+ load();
+
+ ColorIterator i = mColors.find(id);
+
+ if (i == mColors.end())
+ {
+ logger->log("ColorDB: Error, unknown dye ID# %d", id);
+ return mFail;
+ }
+ else
+ {
+ return i->second;
+ }
+}
+
+int ColorDB::size()
+{
+ return mColors.size();
+}
diff --git a/src/resources/colordb.h b/src/resources/colordb.h
new file mode 100644
index 00000000..c581f653
--- /dev/null
+++ b/src/resources/colordb.h
@@ -0,0 +1,52 @@
+/*
+ * Color database
+ * Copyright (C) 2008 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef COLOR_MANAGER_H
+#define COLOR_MANAGER_H
+
+#include <map>
+#include <string>
+
+/**
+ * The class that holds the color information.
+ */
+namespace ColorDB
+{
+ /**
+ * Loads the color data from <code>colors.xml</code>.
+ */
+ void load();
+
+ /**
+ * Clear the color data
+ */
+ void unload();
+
+ std::string& get(int id);
+
+ int size();
+
+ // Color DB
+ typedef std::map<int, std::string> Colors;
+ typedef Colors::iterator ColorIterator;
+}
+
+#endif
diff --git a/src/resources/dye.cpp b/src/resources/dye.cpp
index 1b34a403..22bd2411 100644
--- a/src/resources/dye.cpp
+++ b/src/resources/dye.cpp
@@ -19,7 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <algorithm>
#include <sstream>
#include "dye.h"
diff --git a/src/resources/dye.h b/src/resources/dye.h
index d32c3f22..3cef334a 100644
--- a/src/resources/dye.h
+++ b/src/resources/dye.h
@@ -22,6 +22,7 @@
#ifndef DYE_H
#define DYE_H
+#include <string>
#include <vector>
/**
@@ -36,7 +37,7 @@ class Palette
* The string is either a file name or a sequence of hexadecimal RGB
* values separated by ',' and starting with '#'.
*/
- Palette(const std::string &);
+ Palette(const std::string &pallete);
/**
* Gets a pixel color depending on its intensity.
@@ -63,7 +64,7 @@ class Dye
* The parts of string are separated by semi-colons. Each part starts
* by an uppercase letter, followed by a colon and then a palette name.
*/
- Dye(const std::string &);
+ Dye(const std::string &dye);
/**
* Destroys the associated palettes.
diff --git a/src/resources/emotedb.cpp b/src/resources/emotedb.cpp
new file mode 100644
index 00000000..77c3c2fb
--- /dev/null
+++ b/src/resources/emotedb.cpp
@@ -0,0 +1,140 @@
+/*
+ * Emote database
+ * Copyright (C) 2008 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "emotedb.h"
+
+#include "../log.h"
+
+#include "../utils/xml.h"
+
+namespace
+{
+ EmoteInfos mEmoteInfos;
+ EmoteInfo mUnknown;
+ bool mLoaded = false;
+ int mLastEmote = 0;
+}
+
+void EmoteDB::load()
+{
+ if (mLoaded)
+ return;
+
+ mLastEmote = 0;
+
+ EmoteSprite *unknownSprite = new EmoteSprite;
+ unknownSprite->sprite = "error.xml";
+ unknownSprite->name = "unknown";
+ unknownSprite->variant = 0;
+ mUnknown.sprites.push_back(unknownSprite);
+
+ logger->log("Initializing emote database...");
+
+ XML::Document doc("emotes.xml");
+ xmlNodePtr rootNode = doc.rootNode();
+
+ if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "emotes"))
+ {
+ logger->log("Emote Database: Error while loading emotes.xml!");
+ return;
+ }
+
+ //iterate <emote>s
+ for_each_xml_child_node(emoteNode, rootNode)
+ {
+ if (!xmlStrEqual(emoteNode->name, BAD_CAST "emote"))
+ continue;
+
+ int id = XML::getProperty(emoteNode, "id", -1);
+ if (id == -1)
+ {
+ logger->log("Emote Database: Emote with missing ID in emotes.xml!");
+ continue;
+ }
+
+ EmoteInfo *currentInfo = new EmoteInfo;
+
+ for_each_xml_child_node(spriteNode, emoteNode)
+ {
+ if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
+ {
+ EmoteSprite *currentSprite = new EmoteSprite;
+ currentSprite->sprite = (const char*) spriteNode->xmlChildrenNode->content;
+ currentSprite->variant = XML::getProperty(spriteNode, "variant", 0);
+ currentInfo->sprites.push_back(currentSprite);
+ }
+ else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
+ {
+ std::string particlefx = (const char*) spriteNode->xmlChildrenNode->content;
+ currentInfo->particles.push_back(particlefx);
+ }
+ }
+ mEmoteInfos[id] = currentInfo;
+ if (id > mLastEmote) mLastEmote = id;
+ }
+
+ mLoaded = true;
+}
+
+void EmoteDB::unload()
+{
+ for ( EmoteInfosIterator i = mEmoteInfos.begin();
+ i != mEmoteInfos.end();
+ i++)
+ {
+ while (!i->second->sprites.empty())
+ {
+ delete i->second->sprites.front();
+ i->second->sprites.pop_front();
+ }
+ delete i->second;
+ }
+
+ mEmoteInfos.clear();
+
+ while (!mUnknown.sprites.empty())
+ {
+ delete mUnknown.sprites.front();
+ mUnknown.sprites.pop_front();
+ }
+
+ mLoaded = false;
+}
+
+const EmoteInfo& EmoteDB::get(int id)
+{
+ EmoteInfosIterator i = mEmoteInfos.find(id);
+
+ if (i == mEmoteInfos.end())
+ {
+ logger->log("EmoteDB: Warning, unknown emote ID %d requested", id);
+ return mUnknown;
+ }
+ else
+ {
+ return *(i->second);
+ }
+}
+
+const int& EmoteDB::getLast()
+{
+ return mLastEmote;
+}
diff --git a/src/resources/emotedb.h b/src/resources/emotedb.h
new file mode 100644
index 00000000..2cf3af62
--- /dev/null
+++ b/src/resources/emotedb.h
@@ -0,0 +1,60 @@
+/*
+ * Emote database
+ * Copyright (C) 2008 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EMOTE_DB_H
+#define EMOTE_DB_H
+
+#include <list>
+#include <map>
+#include <string>
+
+struct EmoteSprite
+{
+ std::string sprite;
+ std::string name;
+ int variant;
+};
+
+struct EmoteInfo
+{
+ std::list<EmoteSprite*> sprites;
+ std::list<std::string> particles;
+};
+
+typedef std::map<int, EmoteInfo*> EmoteInfos;
+
+/**
+ * Emote information database.
+ */
+namespace EmoteDB
+{
+ void load();
+
+ void unload();
+
+ const EmoteInfo& get(int id);
+
+ const int& getLast();
+
+ typedef EmoteInfos::iterator EmoteInfosIterator;
+}
+
+#endif
diff --git a/src/resources/image.cpp b/src/resources/image.cpp
index cc986c81..7a7e6ac8 100644
--- a/src/resources/image.cpp
+++ b/src/resources/image.cpp
@@ -21,9 +21,8 @@
#include <SDL_image.h>
-#include "image.h"
-
#include "dye.h"
+#include "image.h"
#include "../log.h"
@@ -168,7 +167,8 @@ Image *Image::load(SDL_Surface *tmpImage)
tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight,
32, rmask, gmask, bmask, amask);
- if (!tmpImage) {
+ if (!tmpImage)
+ {
logger->log("Error, image convert failed: out of memory");
return NULL;
}
@@ -179,9 +179,8 @@ Image *Image::load(SDL_Surface *tmpImage)
glGenTextures(1, &texture);
glBindTexture(mTextureType, texture);
- if (SDL_MUSTLOCK(tmpImage)) {
+ if (SDL_MUSTLOCK(tmpImage))
SDL_LockSurface(tmpImage);
- }
glTexImage2D(
mTextureType, 0, 4,
@@ -256,14 +255,13 @@ Image *Image::load(SDL_Surface *tmpImage)
SDL_Surface *image;
// Convert the surface to the current display format
- if (hasAlpha) {
+ if (hasAlpha)
image = SDL_DisplayFormatAlpha(tmpImage);
- }
- else {
+ else
image = SDL_DisplayFormat(tmpImage);
- }
- if (!image) {
+ if (!image)
+ {
logger->log("Error: Image convert failed.");
return NULL;
}
@@ -275,14 +273,16 @@ void Image::unload()
{
mLoaded = false;
- if (mImage) {
+ if (mImage)
+ {
// Free the image surface.
SDL_FreeSurface(mImage);
mImage = NULL;
}
#ifdef USE_OPENGL
- if (mGLImage) {
+ if (mGLImage)
+ {
glDeleteTextures(1, &mGLImage);
mGLImage = 0;
}
@@ -293,10 +293,9 @@ Image *Image::getSubImage(int x, int y, int width, int height)
{
// Create a new clipped sub-image
#ifdef USE_OPENGL
- if (mUseOpenGL) {
+ if (mUseOpenGL)
return new SubImage(this, mGLImage, x, y, width, height,
mTexWidth, mTexHeight);
- }
#endif
return new SubImage(this, mImage, x, y, width, height);
@@ -304,13 +303,13 @@ Image *Image::getSubImage(int x, int y, int width, int height)
void Image::setAlpha(float a)
{
- if (mAlpha == a) {
+ if (mAlpha == a)
return;
- }
mAlpha = a;
- if (mImage) {
+ if (mImage)
+ {
// Set the alpha value this image is drawn at
SDL_SetAlpha(mImage, SDL_SRCALPHA, (int) (255 * mAlpha));
}
@@ -322,14 +321,12 @@ float Image::getAlpha()
}
#ifdef USE_OPENGL
-void
-Image::setLoadAsOpenGL(bool useOpenGL)
+void Image::setLoadAsOpenGL(bool useOpenGL)
{
Image::mUseOpenGL = useOpenGL;
}
-int
-Image::powerOfTwo(int input)
+int Image::powerOfTwo(int input)
{
int value;
if (mTextureType == GL_TEXTURE_2D)
@@ -354,7 +351,8 @@ Image::powerOfTwo(int input)
SubImage::SubImage(Image *parent, SDL_Surface *image,
int x, int y, int width, int height):
- Image(image), mParent(parent)
+ Image(image),
+ mParent(parent)
{
mParent->incRef();
@@ -369,7 +367,8 @@ SubImage::SubImage(Image *parent, SDL_Surface *image,
SubImage::SubImage(Image *parent, GLuint image,
int x, int y, int width, int height,
int texWidth, int texHeight):
- Image(image, width, height, texWidth, texHeight), mParent(parent)
+ Image(image, width, height, texWidth, texHeight),
+ mParent(parent)
{
mParent->incRef();
@@ -395,3 +394,4 @@ Image *SubImage::getSubImage(int x, int y, int w, int h)
{
return mParent->getSubImage(mBounds.x + x, mBounds.y + y, w, h);
}
+
diff --git a/src/resources/image.h b/src/resources/image.h
index 963fbb24..fe3081ac 100644
--- a/src/resources/image.h
+++ b/src/resources/image.h
@@ -22,9 +22,10 @@
#ifndef IMAGE_H
#define IMAGE_H
+#include <SDL.h>
+
#include "../main.h"
-#include <SDL.h>
#ifdef USE_OPENGL
/* The definition of OpenGL extensions by SDL is giving problems with recent
@@ -39,6 +40,8 @@
#include "resource.h"
class Dye;
+class SDL_Rect;
+class SDL_Surface;
/**
* Defines a class for loading and storing images.
@@ -96,7 +99,6 @@ class Image : public Resource
virtual int getWidth() const
{ return mBounds.w; }
-
/**
* Returns the height of the image.
*/
@@ -114,7 +116,7 @@ class Image : public Resource
/**
* Sets the alpha value of this image.
*/
- void setAlpha(float alpha);
+ virtual void setAlpha(float alpha);
/**
* Returns the alpha value of this image.
@@ -129,7 +131,6 @@ class Image : public Resource
static void setLoadAsOpenGL(bool useOpenGL);
#endif
-
protected:
/**
* Constructor.
diff --git a/src/resources/imageloader.cpp b/src/resources/imageloader.cpp
index 5aad7c52..40d62797 100644
--- a/src/resources/imageloader.cpp
+++ b/src/resources/imageloader.cpp
@@ -20,13 +20,12 @@
*/
#include <cassert>
-#include <string>
+
#include <guichan/color.hpp>
#include <guichan/sdl/sdlpixel.hpp>
-#include "imageloader.h"
-
#include "image.h"
+#include "imageloader.h"
#include "resourcemanager.h"
ProxyImage::ProxyImage(SDL_Surface *s):
diff --git a/src/resources/imageset.cpp b/src/resources/imageset.cpp
index 458b0405..92bb3242 100644
--- a/src/resources/imageset.cpp
+++ b/src/resources/imageset.cpp
@@ -19,12 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "image.h"
#include "imageset.h"
#include "../log.h"
-#include "image.h"
-
#include "../utils/dtor.h"
ImageSet::ImageSet(Image *img, int width, int height)
@@ -45,8 +44,7 @@ ImageSet::~ImageSet()
delete_all(mImages);
}
-Image*
-ImageSet::get(size_type i) const
+Image* ImageSet::get(size_type i) const
{
if (i >= mImages.size())
{
diff --git a/src/resources/imageset.h b/src/resources/imageset.h
index 00a36754..f59c76bb 100644
--- a/src/resources/imageset.h
+++ b/src/resources/imageset.h
@@ -28,7 +28,6 @@
class Image;
-
/**
* Stores a set of subimages originating from a single image.
*/
diff --git a/src/resources/imagewriter.cpp b/src/resources/imagewriter.cpp
index d6bb4659..c350ac07 100644
--- a/src/resources/imagewriter.cpp
+++ b/src/resources/imagewriter.cpp
@@ -19,11 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "imagewriter.h"
-
#include <png.h>
-#include <string>
#include <SDL.h>
+#include <string>
+
+#include "imagewriter.h"
#include "../log.h"
diff --git a/src/resources/imagewriter.h b/src/resources/imagewriter.h
index 8eb6cead..039d3afb 100644
--- a/src/resources/imagewriter.h
+++ b/src/resources/imagewriter.h
@@ -19,13 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <iosfwd>
-
struct SDL_Surface;
class ImageWriter
{
public:
static bool writePNG(SDL_Surface *surface,
- const std::string &filename);
+ const std::string &filename);
};
diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp
index 1678eda8..6fa010d4 100644
--- a/src/resources/itemdb.cpp
+++ b/src/resources/itemdb.cpp
@@ -20,22 +20,22 @@
*/
#include <cassert>
+
#include <libxml/tree.h>
#include "itemdb.h"
-#include "iteminfo.h"
-#include "resourcemanager.h"
-
#include "../log.h"
#include "../utils/dtor.h"
#include "../utils/gettext.h"
+#include "../utils/trim.h"
#include "../utils/xml.h"
namespace
{
ItemDB::ItemInfos mItemInfos;
+ ItemDB::NamedItemInfos mNamedItemInfos;
ItemInfo *mUnknown;
bool mLoaded = false;
}
@@ -52,17 +52,17 @@ void ItemDB::load()
logger->log("Initializing item database...");
mUnknown = new ItemInfo();
- mUnknown->setName("Unknown item");
+ mUnknown->setName(_("Unknown item"));
mUnknown->setImageName("");
mUnknown->setSprite("error.xml", GENDER_MALE);
mUnknown->setSprite("error.xml", GENDER_FEMALE);
- XML::Document doc("items.xml");
+ XML::Document doc(_("items.xml"));
xmlNodePtr rootNode = doc.rootNode();
if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "items"))
{
- logger->error("ItemDB: Error while loading items.xml!");
+ logger->error(_("ItemDB: Error while loading items.xml!"));
}
for_each_xml_child_node(node, rootNode)
@@ -82,7 +82,7 @@ void ItemDB::load()
logger->log("ItemDB: Redefinition of item ID %d", id);
}
- int type = XML::getProperty(node, "type", 0);
+ std::string type = XML::getProperty(node, "type", "other");
int weight = XML::getProperty(node, "weight", 0);
int view = XML::getProperty(node, "view", 0);
@@ -95,6 +95,7 @@ void ItemDB::load()
if (id)
{
ItemInfo *itemInfo = new ItemInfo;
+ itemInfo->setId(id);
itemInfo->setImageName(image);
itemInfo->setName(name.empty() ? _("Unnamed") : name);
itemInfo->setDescription(description);
@@ -117,6 +118,27 @@ void ItemDB::load()
}
mItemInfos[id] = itemInfo;
+ if (!name.empty())
+ {
+ NamedItemInfoIterator itr = mNamedItemInfos.find(name);
+ if (itr == mNamedItemInfos.end())
+ {
+ std::string temp = name;
+ trim(temp);
+
+ for (unsigned int i = 0; i < temp.size(); i++)
+ {
+ temp[i] = (char) tolower(temp[i]);
+ }
+
+ mNamedItemInfos[temp] = itemInfo;
+ }
+ else
+ {
+ logger->log("ItemDB: Duplicate name of item found item %d",
+ id);
+ }
+ }
}
#define CHECK_PARAM(param, error_value) \
@@ -126,7 +148,7 @@ void ItemDB::load()
CHECK_PARAM(name, "");
CHECK_PARAM(image, "");
CHECK_PARAM(description, "");
- CHECK_PARAM(effect, "");
+ // CHECK_PARAM(effect, "");
// CHECK_PARAM(type, 0);
// CHECK_PARAM(weight, 0);
// CHECK_PARAM(slot, 0);
@@ -166,6 +188,23 @@ const ItemInfo& ItemDB::get(int id)
}
}
+const ItemInfo& ItemDB::get(const std::string &name)
+{
+ assert(mLoaded && !name.empty());
+
+ NamedItemInfoIterator i = mNamedItemInfos.find(name);
+
+ if (i == mNamedItemInfos.end())
+ {
+ logger->log("ItemDB: Error, unknown item name %s", name.c_str());
+ return *mUnknown;
+ }
+ else
+ {
+ return *(i->second);
+ }
+}
+
void loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node)
{
std::string gender = XML::getProperty(node, "gender", "unisex");
@@ -175,7 +214,6 @@ void loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node)
{
itemInfo->setSprite(filename, GENDER_MALE);
}
-
if (gender == "female" || gender == "unisex")
{
itemInfo->setSprite(filename, GENDER_FEMALE);
diff --git a/src/resources/itemdb.h b/src/resources/itemdb.h
index 03fb1eed..08a7acd0 100644
--- a/src/resources/itemdb.h
+++ b/src/resources/itemdb.h
@@ -22,9 +22,11 @@
#ifndef ITEM_MANAGER_H
#define ITEM_MANAGER_H
+#include <map>
+
#include "iteminfo.h"
-#include <map>
+class ItemInfo;
/**
* The namespace that holds the item information.
@@ -42,10 +44,13 @@ namespace ItemDB
void unload();
const ItemInfo& get(int id);
+ const ItemInfo& get(const std::string &name);
// Items database
typedef std::map<int, ItemInfo*> ItemInfos;
+ typedef std::map<std::string, ItemInfo*> NamedItemInfos;
typedef ItemInfos::iterator ItemInfoIterator;
+ typedef NamedItemInfos::iterator NamedItemInfoIterator;
}
#endif
diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp
index b924c591..2f118284 100644
--- a/src/resources/iteminfo.cpp
+++ b/src/resources/iteminfo.cpp
@@ -19,12 +19,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "iteminfo.h"
-
#include "itemdb.h"
+#include "iteminfo.h"
-const std::string&
-ItemInfo::getSprite(Gender gender) const
+const std::string& ItemInfo::getSprite(Gender gender) const
{
if (mView)
{
@@ -67,15 +65,12 @@ void ItemInfo::setWeaponType(int type)
}
}
-void
-ItemInfo::addSound(EquipmentSoundEvent event, const std::string &filename)
+void ItemInfo::addSound(EquipmentSoundEvent event, const std::string &filename)
{
mSounds[event].push_back("sfx/" + filename);
}
-
-const std::string&
-ItemInfo::getSound(EquipmentSoundEvent event) const
+const std::string& ItemInfo::getSound(EquipmentSoundEvent event) const
{
static const std::string empty;
std::map< EquipmentSoundEvent, std::vector<std::string> >::const_iterator i;
diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h
index a04213ff..c03dec28 100644
--- a/src/resources/iteminfo.h
+++ b/src/resources/iteminfo.h
@@ -47,13 +47,19 @@ class ItemInfo
* Constructor.
*/
ItemInfo():
- mType(0),
+ mType(""),
mWeight(0),
mView(0),
mAttackType(ACTION_DEFAULT)
{
}
+ void setId(int id)
+ { mId = id; }
+
+ int getId() const
+ { return mId; }
+
void setName(const std::string &name)
{ mName = name; }
@@ -75,14 +81,12 @@ class ItemInfo
void setEffect(const std::string &effect)
{ mEffect = effect; }
- const std::string&
- getEffect() const { return mEffect; }
+ const std::string& getEffect() const { return mEffect; }
- void setType(short type)
+ void setType(const std::string& type)
{ mType = type; }
- short getType() const
- { return mType; }
+ const std::string& getType() const { return mType; }
void setWeight(short weight)
{ mWeight = weight; }
@@ -112,9 +116,10 @@ class ItemInfo
std::string mName;
std::string mDescription; /**< Short description. */
std::string mEffect; /**< Description of effects. */
- char mType; /**< Item type. */
+ std::string mType; /**< Item type. */
short mWeight; /**< Weight in grams. */
int mView; /**< Item ID of how this item looks. */
+ int mId; /**< Item ID */
// Equipment related members
SpriteAction mAttackType; /**< Attack type, in case of weapon. */
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index 21125c2a..3270c665 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -19,14 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "mapreader.h"
-
#include <cassert>
#include <iostream>
#include <zlib.h>
-#include "resourcemanager.h"
+#include "animation.h"
#include "image.h"
+#include "mapreader.h"
+#include "resourcemanager.h"
#include "../log.h"
#include "../map.h"
@@ -205,14 +205,11 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path)
// Take the filename off the path
const std::string pathDir = path.substr(0, path.rfind("/") + 1);
- //xmlChar *prop = xmlGetProp(node, BAD_CAST "version");
- //xmlFree(prop);
-
const int w = XML::getProperty(node, "width", 0);
const int h = XML::getProperty(node, "height", 0);
- const int tw = XML::getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH);
- const int th = XML::getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT);
- Map *map = new Map(w, h, tw, th);
+ const int tilew = XML::getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH);
+ const int tileh = XML::getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT);
+ Map *map = new Map(w, h, tilew, tileh);
for_each_xml_child_node(childNode, node)
{
@@ -236,8 +233,8 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path)
// The object group offset is applied to each object individually
const int tileOffsetX = XML::getProperty(childNode, "x", 0);
const int tileOffsetY = XML::getProperty(childNode, "y", 0);
- const int offsetX = tileOffsetX * tw;
- const int offsetY = tileOffsetY * th;
+ const int offsetX = tileOffsetX * tilew;
+ const int offsetY = tileOffsetY * tileh;
for_each_xml_child_node(objectNode, childNode)
{
@@ -326,8 +323,8 @@ void MapReader::readLayer(xmlNodePtr node, Map *map)
const int offsetY = XML::getProperty(node, "y", 0);
const std::string name = XML::getProperty(node, "name", "");
- const bool isFringeLayer = (name == "Fringe");
- const bool isCollisionLayer = (name == "Collision");
+ const bool isFringeLayer = (name.substr(0,6) == "Fringe");
+ const bool isCollisionLayer = (name.substr(0,9) == "Collision");
MapLayer *layer = 0;
@@ -370,7 +367,7 @@ void MapReader::readLayer(xmlNodePtr node, Map *map)
while (*charStart) {
if (*charStart != ' ' && *charStart != '\t' &&
- *charStart != '\n')
+ *charStart != '\n')
{
*charIndex = *charStart;
charIndex++;
@@ -461,15 +458,20 @@ Tileset *MapReader::readTileset(xmlNodePtr node,
const std::string &path,
Map *map)
{
+ int firstGid = XML::getProperty(node, "firstgid", 0);
+ XML::Document* doc = NULL;
Tileset *set = NULL;
if (xmlHasProp(node, BAD_CAST "source"))
{
- logger->log("Warning: External tilesets not supported yet.");
- return set;
+ std::string filename = XML::getProperty(node, "source", "");
+ while (filename.substr(0, 3) == "../")
+ filename.erase(0, 3); // Remove "../"
+ doc = new XML::Document(filename);
+ node = doc->rootNode();
+ firstGid += XML::getProperty(node, "firstgid", 0);
}
- const int firstGid = XML::getProperty(node, "firstgid", 0);
const int tw = XML::getProperty(node, "tilewidth", map->getTileWidth());
const int th = XML::getProperty(node, "tileheight", map->getTileHeight());
@@ -545,5 +547,7 @@ Tileset *MapReader::readTileset(xmlNodePtr node,
}
}
+ delete doc;
+
return set;
}
diff --git a/src/resources/mapreader.h b/src/resources/mapreader.h
index 8cb2749d..0ed553c3 100644
--- a/src/resources/mapreader.h
+++ b/src/resources/mapreader.h
@@ -22,12 +22,10 @@
#ifndef MAPREADER_H
#define MAPREADER_H
-#include <iosfwd>
-
#include <libxml/tree.h>
-class Properties;
class Map;
+class Properties;
class Tileset;
/**
diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp
index 5d452db2..15451c95 100644
--- a/src/resources/monsterdb.cpp
+++ b/src/resources/monsterdb.cpp
@@ -20,12 +20,12 @@
*/
#include "monsterdb.h"
-
-#include "resourcemanager.h"
+#include "monsterinfo.h"
#include "../log.h"
#include "../utils/dtor.h"
+#include "../utils/gettext.h"
#include "../utils/xml.h"
namespace
@@ -35,23 +35,22 @@ namespace
bool mLoaded = false;
}
-void
-MonsterDB::load()
+void MonsterDB::load()
{
if (mLoaded)
return;
mUnknown.addSprite("error.xml");
- mUnknown.setName("unnamed");
+ mUnknown.setName(_("unnamed"));
logger->log("Initializing monster database...");
- XML::Document doc("monsters.xml");
+ XML::Document doc(_("monsters.xml"));
xmlNodePtr rootNode = doc.rootNode();
if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "monsters"))
{
- logger->error("Monster Database: Error while loading monster.xml!");
+ logger->error(_("Monster Database: Error while loading monster.xml!"));
}
//iterate <monster>s
@@ -82,7 +81,8 @@ MonsterDB::load()
}
else
{
- logger->log("MonsterDB: Unknown target cursor type \"%s\" for %s - using medium sized one",
+ logger->log("MonsterDB: Unknown target cursor type \"%s\" for %s -"
+ "using medium sized one",
targetCursor.c_str(), currentInfo->getName().c_str());
currentInfo->setTargetCursorSize(Being::TC_MEDIUM);
}
@@ -92,7 +92,8 @@ MonsterDB::load()
{
if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
{
- currentInfo->addSprite((const char*) spriteNode->xmlChildrenNode->content);
+ currentInfo->addSprite(
+ (const char*) spriteNode->xmlChildrenNode->content);
}
if (xmlStrEqual(spriteNode->name, BAD_CAST "sound"))
@@ -119,11 +120,20 @@ MonsterDB::load()
}
else
{
- logger->log("MonsterDB: Warning, sound effect %s for unknown event %s of monster %s",
- filename, event.c_str(), currentInfo->getName().c_str());
+ logger->log("MonsterDB: Warning, sound effect %s for "
+ "unknown event %s of monster %s",
+ filename, event.c_str(),
+ currentInfo->getName().c_str());
}
}
+ if (xmlStrEqual(spriteNode->name, BAD_CAST "attack"))
+ {
+ std::string event = XML::getProperty(
+ spriteNode, "particle-effect", "");
+ currentInfo->addAttackParticleEffect(event);
+ }
+
if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
{
currentInfo->addParticleEffect(
diff --git a/src/resources/monsterdb.h b/src/resources/monsterdb.h
index 8555670b..0a218661 100644
--- a/src/resources/monsterdb.h
+++ b/src/resources/monsterdb.h
@@ -24,18 +24,16 @@
#include <map>
-#include "monsterinfo.h"
+class MonsterInfo;
/**
* Monster information database.
*/
namespace MonsterDB
{
- void
- load();
+ void load();
- void
- unload();
+ void unload();
const MonsterInfo& get(int id);
diff --git a/src/resources/monsterinfo.cpp b/src/resources/monsterinfo.cpp
index d8ff8be3..503990e7 100644
--- a/src/resources/monsterinfo.cpp
+++ b/src/resources/monsterinfo.cpp
@@ -36,8 +36,7 @@ MonsterInfo::~MonsterInfo()
}
-void
-MonsterInfo::addSound(MonsterSoundEvent event, std::string filename)
+void MonsterInfo::addSound(MonsterSoundEvent event, std::string filename)
{
if (mSounds.find(event) == mSounds.end())
{
@@ -48,8 +47,7 @@ MonsterInfo::addSound(MonsterSoundEvent event, std::string filename)
}
-std::string
-MonsterInfo::getSound(MonsterSoundEvent event) const
+std::string MonsterInfo::getSound(MonsterSoundEvent event) const
{
std::map<MonsterSoundEvent, std::vector<std::string>* >::const_iterator i;
diff --git a/src/resources/monsterinfo.h b/src/resources/monsterinfo.h
index b37ac1a9..359791fd 100644
--- a/src/resources/monsterinfo.h
+++ b/src/resources/monsterinfo.h
@@ -22,14 +22,13 @@
#ifndef MONSTERINFO_H
#define MONSTERINFO_H
+#include <list>
#include <map>
#include <string>
#include <vector>
-#include <list>
#include "../being.h"
-
enum MonsterSoundEvent
{
MONSTER_EVENT_HIT,
@@ -57,39 +56,39 @@ class MonsterInfo
*/
~MonsterInfo();
- void
- setName(std::string name) { mName = name; }
+ void setName(std::string name) { mName = name; }
- void
- addSprite(std::string filename) { mSprites.push_back(filename); }
+ void addSprite(std::string filename) { mSprites.push_back(filename); }
- void
- setTargetCursorSize(Being::TargetCursorSize targetCursorSize)
+ void setTargetCursorSize(Being::TargetCursorSize targetCursorSize)
{ mTargetCursorSize = targetCursorSize; }
- void
- addSound(MonsterSoundEvent event, std::string filename);
+ void addSound(MonsterSoundEvent event, std::string filename);
+
+ void addParticleEffect(std::string filename);
+
+ const std::string& getName() const
+ { return mName; }
- void
- addParticleEffect(std::string filename);
+ const std::list<std::string>& getSprites() const
+ { return mSprites; }
- const std::string&
- getName() const { return mName; }
+ Being::TargetCursorSize getTargetCursorSize() const
+ { return mTargetCursorSize; }
- const std::list<std::string>&
- getSprites() const { return mSprites; }
+ std::string getSound(MonsterSoundEvent event) const;
- Being::TargetCursorSize
- getTargetCursorSize() const { return mTargetCursorSize; }
+ std::string getAttackParticleEffect() const { return mAttackParticle; }
- std::string
- getSound(MonsterSoundEvent event) const;
+ void addAttackParticleEffect(const std::string &particleEffect)
+ { mAttackParticle = particleEffect; }
- const std::list<std::string>&
- getParticleEffects() const { return mParticleEffects; }
+ const std::list<std::string>& getParticleEffects() const
+ { return mParticleEffects; }
private:
std::string mName;
+ std::string mAttackParticle;
std::list<std::string> mSprites;
Being::TargetCursorSize mTargetCursorSize;
std::map<MonsterSoundEvent, std::vector<std::string>* > mSounds;
diff --git a/src/resources/music.cpp b/src/resources/music.cpp
index 3b81d05b..ed78a541 100644
--- a/src/resources/music.cpp
+++ b/src/resources/music.cpp
@@ -55,8 +55,7 @@ Resource *Music::load(void *buffer, unsigned bufferSize)
}
}
-bool
-Music::play(int loops)
+bool Music::play(int loops)
{
/*
* Warning: loops should be always set to -1 (infinite) with current
@@ -71,8 +70,7 @@ Music::play(int loops)
return mChannel != -1;
}
-void
-Music::stop()
+void Music::stop()
{
/*
* Warning: very dungerous trick, it could try to stop channels occupied
diff --git a/src/resources/music.h b/src/resources/music.h
index cff18338..65f1ee88 100644
--- a/src/resources/music.h
+++ b/src/resources/music.h
@@ -56,14 +56,12 @@ class Music : public Resource
* @return <code>true</code> if the playback started properly
* <code>false</code> otherwise.
*/
- virtual bool
- play(int loops);
+ virtual bool play(int loops);
/**
* Stops the music.
*/
- virtual void
- stop();
+ virtual void stop();
protected:
/**
diff --git a/src/resources/npcdb.cpp b/src/resources/npcdb.cpp
index 9faef60d..ee65136a 100644
--- a/src/resources/npcdb.cpp
+++ b/src/resources/npcdb.cpp
@@ -21,11 +21,9 @@
#include "npcdb.h"
-#include "resourcemanager.h"
-
#include "../log.h"
-#include "../utils/dtor.h"
+#include "../utils/gettext.h"
#include "../utils/xml.h"
namespace
@@ -52,10 +50,10 @@ void NPCDB::load()
if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "npcs"))
{
- logger->error("NPC Database: Error while loading items.xml!");
+ logger->error(_("NPC Database: Error while loading npcs.xml!"));
}
- //iterate <monster>s
+ //iterate <npc>s
for_each_xml_child_node(npcNode, rootNode)
{
if (!xmlStrEqual(npcNode->name, BAD_CAST "npc"))
@@ -91,8 +89,7 @@ void NPCDB::load()
mLoaded = true;
}
-void
-NPCDB::unload()
+void NPCDB::unload()
{
for ( NPCInfosIterator i = mNPCInfos.begin();
i != mNPCInfos.end();
@@ -117,8 +114,7 @@ NPCDB::unload()
mLoaded = false;
}
-const NPCInfo&
-NPCDB::get(int id)
+const NPCInfo& NPCDB::get(int id)
{
NPCInfosIterator i = mNPCInfos.find(id);
diff --git a/src/resources/npcdb.h b/src/resources/npcdb.h
index a7f28c50..af6764bf 100644
--- a/src/resources/npcdb.h
+++ b/src/resources/npcdb.h
@@ -22,8 +22,8 @@
#ifndef NPC_DB_H
#define NPC_DB_H
-#include <map>
#include <list>
+#include <map>
#include <string>
struct NPCsprite
@@ -45,11 +45,9 @@ typedef std::map<int, NPCInfo*> NPCInfos;
*/
namespace NPCDB
{
- void
- load();
+ void load();
- void
- unload();
+ void unload();
const NPCInfo& get(int id);
diff --git a/src/resources/resource.cpp b/src/resources/resource.cpp
index 4c173962..d1c3ada4 100644
--- a/src/resources/resource.cpp
+++ b/src/resources/resource.cpp
@@ -22,21 +22,18 @@
#include <cassert>
#include "resource.h"
-
#include "resourcemanager.h"
Resource::~Resource()
{
}
-void
-Resource::incRef()
+void Resource::incRef()
{
mRefCount++;
}
-void
-Resource::decRef()
+void Resource::decRef()
{
// Reference may not already have reached zero
assert(mRefCount != 0);
diff --git a/src/resources/resource.h b/src/resources/resource.h
index 0dc50c03..7c5f989e 100644
--- a/src/resources/resource.h
+++ b/src/resources/resource.h
@@ -41,8 +41,7 @@ class Resource
/**
* Increments the internal reference count.
*/
- void
- incRef();
+ void incRef();
/**
* Decrements the reference count and deletes the object
@@ -51,8 +50,7 @@ class Resource
* @return <code>true</code> if the object was deleted
* <code>false</code> otherwise.
*/
- void
- decRef();
+ void decRef();
/**
* Return the path identifying this resource.
@@ -64,8 +62,7 @@ class Resource
/**
* Destructor.
*/
- virtual
- ~Resource();
+ virtual ~Resource();
private:
std::string mIdPath; /**< Path identifying this resource. */
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index febcf0d0..fa8f4654 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -20,24 +20,22 @@
*/
#include <cassert>
-#include <sstream>
-#include <sys/time.h>
-
#include <physfs.h>
#include <SDL_image.h>
+#include <sstream>
-#include "resourcemanager.h"
+#include <sys/time.h>
#include "dye.h"
#include "image.h"
+#include "imageset.h"
#include "music.h"
+#include "resourcemanager.h"
#include "soundeffect.h"
-#include "imageset.h"
#include "spritedef.h"
#include "../log.h"
-
ResourceManager *ResourceManager::instance = NULL;
ResourceManager::ResourceManager()
@@ -155,13 +153,13 @@ bool ResourceManager::addToSearchPath(const std::string &path, bool append)
}
void ResourceManager::searchAndAddArchives(const std::string &path,
- const std::string &ext,
- bool append)
+ const std::string &ext,
+ bool append)
{
const char *dirSep = PHYSFS_getDirSeparator();
char **list = PHYSFS_enumerateFiles(path.c_str());
- for (char **i = list; *i != NULL; i++)
+ for (char **i = list; *i; i++)
{
size_t len = strlen(*i);
@@ -209,7 +207,7 @@ std::string ResourceManager::getPath(const std::string &file)
else
{
// if not found in search path return the default path
- path = std::string(TMW_DATADIR) + std::string("data") + "/" + file;
+ path = std::string(PKG_DATADIR) + std::string("data") + "/" + file;
}
return path;
@@ -420,8 +418,7 @@ void *ResourceManager::loadFile(const std::string &fileName, int &fileSize)
return buffer;
}
-std::vector<std::string>
-ResourceManager::loadTextFile(const std::string &fileName)
+std::vector<std::string> ResourceManager::loadTextFile(const std::string &fileName)
{
int contentsLength;
char *fileContents = (char*)loadFile(fileName, contentsLength);
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index 6a7a2ed6..c3c68d88 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -27,11 +27,11 @@
#include <string>
#include <vector>
-class Resource;
class Image;
+class ImageSet;
class Music;
+class Resource;
class SoundEffect;
-class ImageSet;
class SpriteDef;
struct SDL_Surface;
@@ -100,7 +100,7 @@ class ResourceManager
/**
* Returns the real path to a file. Note that this method will always
* return a path, it does not check whether the file exists.
- *
+ *
* @param file The file to get the real path to.
* @return The real path.
*/
diff --git a/src/resources/soundeffect.cpp b/src/resources/soundeffect.cpp
index 21488511..3a285730 100644
--- a/src/resources/soundeffect.cpp
+++ b/src/resources/soundeffect.cpp
@@ -47,8 +47,7 @@ Resource *SoundEffect::load(void *buffer, unsigned bufferSize)
}
}
-bool
-SoundEffect::play(int loops, int volume)
+bool SoundEffect::play(int loops, int volume)
{
Mix_VolumeChunk(mChunk, volume);
diff --git a/src/resources/soundeffect.h b/src/resources/soundeffect.h
index 5f511b29..116df930 100644
--- a/src/resources/soundeffect.h
+++ b/src/resources/soundeffect.h
@@ -35,8 +35,7 @@ class SoundEffect : public Resource
/**
* Destructor.
*/
- virtual
- ~SoundEffect();
+ virtual ~SoundEffect();
/**
* Loads a sample from a buffer in memory.
@@ -58,8 +57,7 @@ class SoundEffect : public Resource
* @return <code>true</code> if the playback started properly
* <code>false</code> otherwise.
*/
- virtual bool
- play(int loops, int volume);
+ virtual bool play(int loops, int volume);
protected:
/**
diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp
index 64ce8b0a..20c79e73 100644
--- a/src/resources/spritedef.cpp
+++ b/src/resources/spritedef.cpp
@@ -21,14 +21,13 @@
#include <set>
-#include "spritedef.h"
-
#include "action.h"
#include "animation.h"
#include "dye.h"
#include "image.h"
#include "imageset.h"
#include "resourcemanager.h"
+#include "spritedef.h"
#include "../log.h"
#include "../utils/xml.h"
@@ -322,7 +321,7 @@ SpriteDef::~SpriteDef()
SpriteAction SpriteDef::makeSpriteAction(const std::string &action)
{
- if (action == "" || action == "default") {
+ if (action.empty() || action == "default") {
return ACTION_DEFAULT;
}
if (action == "stand") {
@@ -374,7 +373,7 @@ SpriteAction SpriteDef::makeSpriteAction(const std::string &action)
SpriteDirection SpriteDef::makeSpriteDirection(const std::string& direction)
{
- if (direction == "" || direction == "default") {
+ if (direction.empty() || direction == "default") {
return DIRECTION_DEFAULT;
}
else if (direction == "up") {
diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h
index b86a4c4d..b9d7b85d 100644
--- a/src/resources/spritedef.h
+++ b/src/resources/spritedef.h
@@ -25,10 +25,10 @@
#include <map>
#include <string>
-#include "resource.h"
-
#include <libxml/tree.h>
+#include "resource.h"
+
class Action;
class ImageSet;
@@ -89,7 +89,6 @@ class SpriteDef : public Resource
static SpriteDirection
makeSpriteDirection(const std::string &direction);
-
private:
/**
* Constructor.
@@ -140,7 +139,6 @@ class SpriteDef : public Resource
*/
void substituteAction(SpriteAction complete, SpriteAction with);
-
typedef std::map<std::string, ImageSet*> ImageSets;
typedef ImageSets::iterator ImageSetIterator;
diff --git a/src/simpleanimation.cpp b/src/simpleanimation.cpp
index 8abb4a67..48f2f6a5 100644
--- a/src/simpleanimation.cpp
+++ b/src/simpleanimation.cpp
@@ -19,15 +19,21 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "simpleanimation.h"
-
-#include "graphics.h"
#include "log.h"
+#include "simpleanimation.h"
+#include "resources/animation.h"
#include "resources/image.h"
-#include "resources/resourcemanager.h"
#include "resources/imageset.h"
+#include "resources/resourcemanager.h"
+SimpleAnimation::SimpleAnimation(Animation *animation):
+ mAnimation(animation),
+ mAnimationTime(0),
+ mAnimationPhase(0),
+ mCurrentFrame(mAnimation->getFrame(0))
+{
+}
SimpleAnimation::SimpleAnimation(xmlNodePtr animationNode):
mAnimationTime(0),
@@ -43,7 +49,7 @@ SimpleAnimation::SimpleAnimation(xmlNodePtr animationNode):
// Get animation frames
for ( xmlNodePtr frameNode = animationNode->xmlChildrenNode;
- frameNode != NULL;
+ frameNode;
frameNode = frameNode->next)
{
int delay = XML::getProperty(frameNode, "delay", 0);
diff --git a/src/simpleanimation.h b/src/simpleanimation.h
index a7178145..16ac2906 100644
--- a/src/simpleanimation.h
+++ b/src/simpleanimation.h
@@ -22,12 +22,12 @@
#ifndef SIMPLEANIMAION_H
#define SIMPLEANIMAION_H
-#include "resources/animation.h"
-
#include "utils/xml.h"
+class Animation;
class Frame;
class Graphics;
+class Image;
/**
* This class is a leightweight alternative to the AnimatedSprite class.
@@ -39,12 +39,7 @@ class SimpleAnimation
/**
* Creates a simple animation with an already created animation.
*/
- SimpleAnimation(Animation *animation):
- mAnimation(animation),
- mAnimationTime(0),
- mAnimationPhase(0),
- mCurrentFrame(mAnimation->getFrame(0))
- {};
+ SimpleAnimation(Animation *animation);
/**
* Creates a simple animation that creates its animation from XML Data.
diff --git a/src/sound.cpp b/src/sound.cpp
index c69dc023..6e0b0da0 100644
--- a/src/sound.cpp
+++ b/src/sound.cpp
@@ -19,11 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "sound.h"
-
#include <SDL.h>
#include "log.h"
+#include "sound.h"
+
#include "resources/resourcemanager.h"
#include "resources/soundeffect.h"
@@ -128,7 +128,7 @@ void Sound::playMusic(const std::string &filename, int loop)
{
if (!mInstalled) return;
- if (mMusic != NULL) {
+ if (mMusic) {
stopMusic();
}
@@ -154,7 +154,7 @@ void Sound::stopMusic()
logger->log("Sound::stopMusic()");
- if (mMusic != NULL) {
+ if (mMusic) {
Mix_HaltMusic();
Mix_FreeMusic(mMusic);
mMusic = NULL;
@@ -165,7 +165,7 @@ void Sound::fadeInMusic(const std::string &path, int loop, int ms)
{
if (!mInstalled) return;
- if (mMusic != NULL) {
+ if (mMusic) {
stopMusic();
}
@@ -188,7 +188,7 @@ void Sound::fadeOutMusic(int ms)
logger->log("Sound::fadeOutMusic() Fading-out (%i ms)", ms);
- if (mMusic != NULL) {
+ if (mMusic) {
Mix_FadeOutMusic(ms);
Mix_FreeMusic(mMusic);
mMusic = NULL;
diff --git a/src/sound.h b/src/sound.h
index 88336572..05b2def3 100644
--- a/src/sound.h
+++ b/src/sound.h
@@ -23,7 +23,6 @@
#define SOUND_H
#include <SDL_mixer.h>
-
#include <string>
/** Sound engine
diff --git a/src/sprite.h b/src/sprite.h
index 624e4e8b..a6384e94 100644
--- a/src/sprite.h
+++ b/src/sprite.h
@@ -44,30 +44,26 @@ class Sprite
* would support setting a translation offset. It already does this
* partly with the clipping rectangle support.
*/
- virtual void
- draw(Graphics *graphics, int offsetX, int offsetY) const = 0;
+ virtual void draw(Graphics *graphics, int offsetX, int offsetY) const = 0;
/**
* Returns the horizontal size of the sprites graphical representation
* in pixels or 0 when it is undefined.
*/
- virtual int
- getWidth() const
+ virtual int getWidth() const
{ return 0; }
/**
* Returns the vertical size of the sprites graphical representation
* in pixels or 0 when it is undefined.
*/
- virtual int
- getHeight() const
+ virtual int getHeight() const
{ return 0; }
/**
* Returns the pixel Y coordinate of the sprite.
*/
- virtual int
- getPixelY() const = 0;
+ virtual int getPixelY() const = 0;
};
#endif
diff --git a/src/statuseffect.cpp b/src/statuseffect.cpp
index 8872fd7b..7a50e794 100644
--- a/src/statuseffect.cpp
+++ b/src/statuseffect.cpp
@@ -39,19 +39,19 @@ StatusEffect::~StatusEffect()
void StatusEffect::playSFX()
{
- if (mSFXEffect != "")
+ if (!mSFXEffect.empty())
sound.playSfx(mSFXEffect);
}
void StatusEffect::deliverMessage()
{
- if (mMessage != "")
+ if (!mMessage.empty())
chatWindow->chatLog(mMessage, BY_SERVER);
}
Particle *StatusEffect::getParticle()
{
- if (mParticleEffect == "")
+ if (mParticleEffect.empty())
return NULL;
else
return particleEngine->addEffect(mParticleEffect, 0, 0);
@@ -59,7 +59,7 @@ Particle *StatusEffect::getParticle()
AnimatedSprite *StatusEffect::getIcon()
{
- if (mIcon == "")
+ if (mIcon.empty())
return NULL;
else {
AnimatedSprite *sprite = AnimatedSprite::load(
@@ -74,7 +74,7 @@ AnimatedSprite *StatusEffect::getIcon()
SpriteAction StatusEffect::getAction()
{
- if (mAction == "")
+ if (mAction.empty())
return ACTION_INVALID;
else
return SpriteDef::makeSpriteAction(mAction);
diff --git a/src/text.cpp b/src/text.cpp
index 0e458c9f..c4559879 100644
--- a/src/text.cpp
+++ b/src/text.cpp
@@ -1,5 +1,6 @@
/*
- * The Mana World
+ * Support for non-overlapping floating text
+ * Copyright (C) 2008 Douglas Boffey <DougABoffey@netscape.net>
* Copyright (C) 2008 The Mana World Development Team
*
* This file is part of The Mana World.
@@ -21,8 +22,6 @@
#include "text.h"
-#include <cstring>
-
#include <guichan/font.hpp>
#include "configuration.h"
@@ -38,9 +37,9 @@ Image *Text::mBubbleArrow;
Text::Text(const std::string &text, int x, int y,
gcn::Graphics::Alignment alignment,
- gcn::Color colour, bool isSpeech) :
+ gcn::Color color, bool isSpeech) :
mText(text),
- mColour(colour),
+ mColor(color),
mIsSpeech(isSpeech)
{
if (textManager == 0)
@@ -48,7 +47,7 @@ Text::Text(const std::string &text, int x, int y,
textManager = new TextManager;
ResourceManager *resman = ResourceManager::getInstance();
Image *sbImage = resman->getImage("graphics/gui/bubble.png|W:#"
- + config.getValue("speechBubbleColour", "000000"));
+ + config.getValue("speechBubblecolor", "000000"));
mBubble.grid[0] = sbImage->getSubImage(0, 0, 5, 5);
mBubble.grid[1] = sbImage->getSubImage(5, 0, 5, 5);
mBubble.grid[2] = sbImage->getSubImage(10, 0, 5, 5);
@@ -68,8 +67,8 @@ Text::Text(const std::string &text, int x, int y,
sbImage->decRef();
}
++mInstances;
- mHeight = gui->getFont()->getHeight();
- mWidth = gui->getFont()->getWidth(text);
+ mHeight = boldFont->getHeight();
+ mWidth = boldFont->getWidth(text);
switch (alignment)
{
@@ -113,9 +112,9 @@ void Text::adviseXY(int x, int y)
textManager->moveText(this, x - mXOffset, y);
}
-void Text::draw(Graphics *graphics, int xOff, int yOff)
+void Text::draw(gcn::Graphics *graphics, int xOff, int yOff)
{
- graphics->setFont(gui->getFont());
+ graphics->setFont(boldFont);
if (mIsSpeech) {
static_cast<Graphics*>(graphics)->drawImageRect(
@@ -162,20 +161,20 @@ void Text::draw(Graphics *graphics, int xOff, int yOff)
gcn::Graphics::LEFT);
}
- graphics->setColor(mColour);
+ graphics->setColor(mColor);
graphics->drawText(mText, mX - xOff, mY - yOff,
gcn::Graphics::LEFT);
}
FlashText::FlashText(const std::string &text, int x, int y,
gcn::Graphics::Alignment alignment,
- gcn::Color colour) :
- Text(text, x, y, alignment, colour),
+ gcn::Color color) :
+ Text(text, x, y, alignment, color),
mTime(0)
{
}
-void FlashText::draw(Graphics *graphics, int xOff, int yOff)
+void FlashText::draw(gcn::Graphics *graphics, int xOff, int yOff)
{
if (mTime)
{
diff --git a/src/text.h b/src/text.h
index a7eae152..6e121da7 100644
--- a/src/text.h
+++ b/src/text.h
@@ -1,5 +1,6 @@
/*
- * The Mana World
+ * Support for non-overlapping floating text
+ * Copyright (C) 2008 Douglas Boffey <DougABoffey@netscape.net>
* Copyright (C) 2008 The Mana World Development Team
*
* This file is part of The Mana World.
@@ -22,9 +23,10 @@
#ifndef TEXT_H
#define TEXT_H
-#include "graphics.h"
+#include <guichan/color.hpp>
-#include <list>
+#include "graphics.h"
+#include "guichanfwd.h"
class TextManager;
@@ -38,7 +40,7 @@ class Text
*/
Text(const std::string &text, int x, int y,
gcn::Graphics::Alignment alignment,
- gcn::Color colour, bool isSpeech = false);
+ gcn::Color color, bool isSpeech = false);
/**
* Destructor. The text is removed from the screen.
@@ -53,7 +55,7 @@ class Text
/**
* Draws the text.
*/
- virtual void draw(Graphics *graphics, int xOff, int yOff);
+ virtual void draw(gcn::Graphics *graphics, int xOff, int yOff);
private:
int mX; /**< Actual x-value of left of text written. */
@@ -63,7 +65,7 @@ class Text
int mXOffset; /**< The offset of mX from the desired x. */
static int mInstances; /**< Instances of text. */
std::string mText; /**< The text to display. */
- gcn::Color mColour; /**< The colour of the text. */
+ gcn::Color mColor; /**< The color of the text. */
bool mIsSpeech; /**< Is this text a speech bubble? */
protected:
@@ -76,7 +78,12 @@ class FlashText : public Text
public:
FlashText(const std::string &text, int x, int y,
gcn::Graphics::Alignment alignment,
- gcn::Color colour);
+ gcn::Color color);
+
+ /**
+ * Remove the text from the screen
+ */
+ virtual ~FlashText() {}
/**
* Flash the text for so many refreshes.
@@ -86,10 +93,10 @@ class FlashText : public Text
/**
* Draws the text.
*/
- virtual void draw(Graphics *graphics, int xOff, int yOff);
+ virtual void draw(gcn::Graphics *graphics, int xOff, int yOff);
private:
- int mTime; /**< Time left for flashing. */
+ int mTime; /**< Time left for flashing */
};
#endif // TEXT_H
diff --git a/src/textmanager.cpp b/src/textmanager.cpp
index bbcc271a..6bc8f8b6 100644
--- a/src/textmanager.cpp
+++ b/src/textmanager.cpp
@@ -1,6 +1,6 @@
/*
- * The Mana World
- * Copyright (C) 2008 The Mana World Development Team
+ * Support for non-overlapping floating text
+ * Copyright (C) 2008 Douglas Boffey <DougABoffey@netscape.net>
*
* This file is part of The Mana World.
*
@@ -61,7 +61,7 @@ TextManager::~TextManager()
{
}
-void TextManager::draw(Graphics *graphics, int xOff, int yOff)
+void TextManager::draw(gcn::Graphics *graphics, int xOff, int yOff)
{
for (TextList::iterator bPtr = mTextList.begin(), ePtr = mTextList.end();
bPtr != ePtr; ++bPtr)
@@ -91,21 +91,13 @@ void TextManager::place(const Text *textObj, const Text *omit,
int from = (*ptr)->mY - occupiedTop;
int to = from + (*ptr)->mHeight - 1;
if (to < 0 || from >= TEST) // out of range considered
- {
continue;
- }
if (from < 0)
- {
from = 0;
- }
if (to >= TEST)
- {
to = TEST - 1;
- }
for (int i = from; i <= to; ++i)
- {
occupied[i] = true;
- }
}
}
bool ok = true;
@@ -113,10 +105,10 @@ void TextManager::place(const Text *textObj, const Text *omit,
{
ok = ok && !occupied[i];
}
+
if (ok)
- {
return;
- }
+
// Have to move it up or down, so find nearest spaces either side
int consec = 0;
int upSlot = -1; // means not found
diff --git a/src/textmanager.h b/src/textmanager.h
index fd0006c9..ee8e1209 100644
--- a/src/textmanager.h
+++ b/src/textmanager.h
@@ -1,6 +1,6 @@
/*
- * The Mana World
- * Copyright (C) 2008 The Mana World Development Team
+ * Support for non-overlapping floating text
+ * Copyright (C) 2008 Douglas Boffey <DougABoffey@netscape.net>
*
* This file is part of The Mana World.
*
@@ -24,8 +24,9 @@
#include <list>
+#include "guichanfwd.h"
+
class Text;
-class Graphics;
class TextManager
{
@@ -58,7 +59,7 @@ class TextManager
/**
* Draw the text
*/
- void draw(Graphics *graphics, int xOff, int yOff);
+ void draw(gcn::Graphics *graphics, int xOff, int yOff);
private:
/**
diff --git a/src/textparticle.cpp b/src/textparticle.cpp
index 0367f109..f38c32ce 100644
--- a/src/textparticle.cpp
+++ b/src/textparticle.cpp
@@ -19,9 +19,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "textparticle.h"
+#include <guichan/color.hpp>
#include "graphics.h"
+#include "textparticle.h"
TextParticle::TextParticle(Map *map, const std::string &text,
int colorR, int colorG, int colorB,
diff --git a/src/textparticle.h b/src/textparticle.h
index acf1e6a5..cdf99d8f 100644
--- a/src/textparticle.h
+++ b/src/textparticle.h
@@ -22,11 +22,8 @@
#ifndef _TEXTPARTICLE_H
#define _TEXTPARTICLE_H
-#include "particle.h"
-
-#include <guichan/color.hpp>
-
#include "guichanfwd.h"
+#include "particle.h"
class TextParticle : public Particle
{
diff --git a/src/utils/base64.cpp b/src/utils/base64.cpp
index 8cea60f9..9d8ba836 100644
--- a/src/utils/base64.cpp
+++ b/src/utils/base64.cpp
@@ -27,8 +27,8 @@
+----------------------------------------------------------------------+
*/
-#include <string.h>
#include <stdlib.h>
+#include <string.h>
#include "base64.h"
diff --git a/src/utils/strprintf.cpp b/src/utils/strprintf.cpp
index bed4a7c4..07fb3508 100644
--- a/src/utils/strprintf.cpp
+++ b/src/utils/strprintf.cpp
@@ -45,3 +45,4 @@ std::string strprintf(char const *format, ...)
delete [] buf2;
return res;
}
+
diff --git a/src/utils/tostring.h b/src/utils/tostring.h
index 5ac1d3aa..62eb44e4 100644
--- a/src/utils/tostring.h
+++ b/src/utils/tostring.h
@@ -32,4 +32,19 @@ std::string toString(const T &arg)
return ss.str();
}
+// TODO: Is there a good way to suppress warnings from classes which don't use
+// this function?
+inline char *iptostring(int address)
+{
+ static char asciiIP[16];
+
+ sprintf(asciiIP, "%i.%i.%i.%i",
+ (unsigned char)(address),
+ (unsigned char)(address >> 8),
+ (unsigned char)(address >> 16),
+ (unsigned char)(address >> 24));
+
+ return asciiIP;
+}
+
#endif
diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp
index f6498c9f..d5dd54be 100644
--- a/src/utils/xml.cpp
+++ b/src/utils/xml.cpp
@@ -20,7 +20,9 @@
*/
#include "xml.h"
+
#include "../log.h"
+
#include "../resources/resourcemanager.h"
namespace XML
diff --git a/tmw.cbp b/tmw.cbp
index db698175..7fcfdd92 100644
--- a/tmw.cbp
+++ b/tmw.cbp
@@ -16,6 +16,7 @@
<Add option="-Wall" />
<Add option="-DUSE_OPENGL" />
<Add option="-DNOGDI" />
+ <Add option="-DENABLE_NLS" />
</Compiler>
<Linker>
<Add library="guichan" />
@@ -35,6 +36,7 @@
<Add library="z.dll" />
<Add library="physfs" />
<Add library="curl.dll" />
+ <Add library="intl" />
</Linker>
</Target>
<Target title="unix">
@@ -77,6 +79,7 @@
<Linker>
<Add directory="lib" />
</Linker>
+ <Unit filename="src\SDLMain.h" />
<Unit filename="src\animatedsprite.cpp" />
<Unit filename="src\animatedsprite.h" />
<Unit filename="src\animationparticle.cpp" />
@@ -88,6 +91,10 @@
<Unit filename="src\configlistener.h" />
<Unit filename="src\configuration.cpp" />
<Unit filename="src\configuration.h" />
+ <Unit filename="src\effectmanager.cpp" />
+ <Unit filename="src\effectmanager.h" />
+ <Unit filename="src\emoteshortcut.cpp" />
+ <Unit filename="src\emoteshortcut.h" />
<Unit filename="src\engine.cpp" />
<Unit filename="src\engine.h" />
<Unit filename="src\equipment.cpp" />
@@ -102,8 +109,6 @@
<Unit filename="src\graphics.h" />
<Unit filename="src\gui\browserbox.cpp" />
<Unit filename="src\gui\browserbox.h" />
- <Unit filename="src\gui\buddywindow.cpp" />
- <Unit filename="src\gui\buddywindow.h" />
<Unit filename="src\gui\button.cpp" />
<Unit filename="src\gui\button.h" />
<Unit filename="src\gui\buy.cpp" />
@@ -120,12 +125,20 @@
<Unit filename="src\gui\chatinput.h" />
<Unit filename="src\gui\checkbox.cpp" />
<Unit filename="src\gui\checkbox.h" />
+ <Unit filename="src\gui\color.cpp" />
+ <Unit filename="src\gui\color.h" />
<Unit filename="src\gui\confirm_dialog.cpp" />
<Unit filename="src\gui\confirm_dialog.h" />
<Unit filename="src\gui\connection.cpp" />
<Unit filename="src\gui\connection.h" />
<Unit filename="src\gui\debugwindow.cpp" />
<Unit filename="src\gui\debugwindow.h" />
+ <Unit filename="src\gui\emotecontainer.cpp" />
+ <Unit filename="src\gui\emotecontainer.h" />
+ <Unit filename="src\gui\emoteshortcutcontainer.cpp" />
+ <Unit filename="src\gui\emoteshortcutcontainer.h" />
+ <Unit filename="src\gui\emotewindow.cpp" />
+ <Unit filename="src\gui\emotewindow.h" />
<Unit filename="src\gui\equipmentwindow.cpp" />
<Unit filename="src\gui\equipmentwindow.h" />
<Unit filename="src\gui\focushandler.cpp" />
@@ -144,10 +157,12 @@
<Unit filename="src\gui\item_amount.h" />
<Unit filename="src\gui\itemcontainer.cpp" />
<Unit filename="src\gui\itemcontainer.h" />
+ <Unit filename="src\gui\itemlinkhandler.cpp" />
+ <Unit filename="src\gui\itemlinkhandler.h" />
+ <Unit filename="src\gui\itempopup.cpp" />
+ <Unit filename="src\gui\itempopup.h" />
<Unit filename="src\gui\itemshortcutcontainer.cpp" />
<Unit filename="src\gui\itemshortcutcontainer.h" />
- <Unit filename="src\gui\itemshortcutwindow.cpp" />
- <Unit filename="src\gui\itemshortcutwindow.h" />
<Unit filename="src\gui\linkhandler.h" />
<Unit filename="src\gui\listbox.cpp" />
<Unit filename="src\gui\listbox.h" />
@@ -179,6 +194,8 @@
<Unit filename="src\gui\progressbar.h" />
<Unit filename="src\gui\radiobutton.cpp" />
<Unit filename="src\gui\radiobutton.h" />
+ <Unit filename="src\gui\recorder.cpp" />
+ <Unit filename="src\gui\recorder.h" />
<Unit filename="src\gui\register.cpp" />
<Unit filename="src\gui\register.h" />
<Unit filename="src\gui\scrollarea.cpp" />
@@ -191,6 +208,8 @@
<Unit filename="src\gui\setup.h" />
<Unit filename="src\gui\setup_audio.cpp" />
<Unit filename="src\gui\setup_audio.h" />
+ <Unit filename="src\gui\setup_colors.cpp" />
+ <Unit filename="src\gui\setup_colors.h" />
<Unit filename="src\gui\setup_joystick.cpp" />
<Unit filename="src\gui\setup_joystick.h" />
<Unit filename="src\gui\setup_keyboard.cpp" />
@@ -204,10 +223,16 @@
<Unit filename="src\gui\shop.h" />
<Unit filename="src\gui\shoplistbox.cpp" />
<Unit filename="src\gui\shoplistbox.h" />
+ <Unit filename="src\gui\shortcutcontainer.cpp" />
+ <Unit filename="src\gui\shortcutcontainer.h" />
+ <Unit filename="src\gui\shortcutwindow.cpp" />
+ <Unit filename="src\gui\shortcutwindow.h" />
<Unit filename="src\gui\skill.cpp" />
<Unit filename="src\gui\skill.h" />
<Unit filename="src\gui\slider.cpp" />
<Unit filename="src\gui\slider.h" />
+ <Unit filename="src\gui\speechbubble.cpp" />
+ <Unit filename="src\gui\speechbubble.h" />
<Unit filename="src\gui\status.cpp" />
<Unit filename="src\gui\status.h" />
<Unit filename="src\gui\table.cpp" />
@@ -226,6 +251,8 @@
<Unit filename="src\gui\updatewindow.h" />
<Unit filename="src\gui\viewport.cpp" />
<Unit filename="src\gui\viewport.h" />
+ <Unit filename="src\gui\widgets\dropdown.cpp" />
+ <Unit filename="src\gui\widgets\dropdown.h" />
<Unit filename="src\gui\widgets\layout.cpp" />
<Unit filename="src\gui\widgets\layout.h" />
<Unit filename="src\gui\widgets\layouthelper.cpp" />
@@ -294,6 +321,8 @@
<Unit filename="src\net\npchandler.cpp" />
<Unit filename="src\net\npchandler.h" />
<Unit filename="src\net\packet.h" />
+ <Unit filename="src\net\partyhandler.cpp" />
+ <Unit filename="src\net\partyhandler.h" />
<Unit filename="src\net\playerhandler.cpp" />
<Unit filename="src\net\playerhandler.h" />
<Unit filename="src\net\protocol.cpp" />
@@ -313,10 +342,14 @@
<Unit filename="src\particleemitter.cpp" />
<Unit filename="src\particleemitter.h" />
<Unit filename="src\particleemitterprop.h" />
+ <Unit filename="src\party.cpp" />
+ <Unit filename="src\party.h" />
<Unit filename="src\player.cpp" />
<Unit filename="src\player.h" />
<Unit filename="src\player_relations.cpp" />
<Unit filename="src\player_relations.h" />
+ <Unit filename="src\position.cpp" />
+ <Unit filename="src\position.h" />
<Unit filename="src\properties.h" />
<Unit filename="src\resources\action.cpp" />
<Unit filename="src\resources\action.h" />
@@ -326,8 +359,12 @@
<Unit filename="src\resources\animation.h" />
<Unit filename="src\resources\buddylist.cpp" />
<Unit filename="src\resources\buddylist.h" />
+ <Unit filename="src\resources\colordb.cpp" />
+ <Unit filename="src\resources\colordb.h" />
<Unit filename="src\resources\dye.cpp" />
<Unit filename="src\resources\dye.h" />
+ <Unit filename="src\resources\emotedb.cpp" />
+ <Unit filename="src\resources\emotedb.h" />
<Unit filename="src\resources\image.cpp" />
<Unit filename="src\resources\image.h" />
<Unit filename="src\resources\imageloader.cpp" />
@@ -382,12 +419,15 @@
<Unit filename="src\utils\base64.h" />
<Unit filename="src\utils\dtor.h" />
<Unit filename="src\utils\fastsqrt.h" />
+ <Unit filename="src\utils\gettext.h" />
+ <Unit filename="src\utils\mutex.h" />
<Unit filename="src\utils\strprintf.cpp" />
<Unit filename="src\utils\strprintf.h" />
<Unit filename="src\utils\tostring.h" />
<Unit filename="src\utils\trim.h" />
<Unit filename="src\utils\xml.cpp" />
<Unit filename="src\utils\xml.h" />
+ <Unit filename="src\vector.cpp" />
<Unit filename="src\vector.h" />
<Unit filename="src\winver.h" />
<Extensions>