summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt88
-rw-r--r--src/Makefile.am323
-rw-r--r--src/SDLMain.h11
-rw-r--r--src/SDLMain.m383
-rw-r--r--src/animatedsprite.cpp9
-rw-r--r--src/animatedsprite.h12
-rw-r--r--src/animationparticle.cpp9
-rw-r--r--src/animationparticle.h8
-rw-r--r--src/being.cpp696
-rw-r--r--src/being.h323
-rw-r--r--src/beingmanager.cpp130
-rw-r--r--src/beingmanager.h33
-rw-r--r--src/configlistener.h15
-rw-r--r--src/configuration.cpp198
-rw-r--r--src/configuration.h163
-rw-r--r--src/effectmanager.cpp46
-rw-r--r--src/effectmanager.h37
-rw-r--r--src/emoteshortcut.cpp77
-rw-r--r--src/emoteshortcut.h125
-rw-r--r--src/engine.cpp87
-rw-r--r--src/engine.h20
-rw-r--r--src/equipment.cpp37
-rw-r--r--src/equipment.h60
-rw-r--r--src/floor_item.cpp25
-rw-r--r--src/floor_item.h48
-rw-r--r--src/flooritemmanager.cpp11
-rw-r--r--src/flooritemmanager.h12
-rw-r--r--src/game.cpp654
-rw-r--r--src/game.h38
-rw-r--r--src/graphics.cpp30
-rw-r--r--src/graphics.h36
-rw-r--r--src/gui/box.h58
-rw-r--r--src/gui/browserbox.cpp123
-rw-r--r--src/gui/browserbox.h21
-rw-r--r--src/gui/button.cpp58
-rw-r--r--src/gui/button.h22
-rw-r--r--src/gui/buy.cpp43
-rw-r--r--src/gui/buy.h24
-rw-r--r--src/gui/buysell.cpp23
-rw-r--r--src/gui/buysell.h12
-rw-r--r--src/gui/char_select.cpp347
-rw-r--r--src/gui/char_select.h67
-rw-r--r--src/gui/char_server.cpp122
-rw-r--r--src/gui/char_server.h65
-rw-r--r--src/gui/chat.cpp847
-rw-r--r--src/gui/chat.h203
-rw-r--r--src/gui/chatinput.cpp8
-rw-r--r--src/gui/chatinput.h14
-rw-r--r--src/gui/checkbox.cpp35
-rw-r--r--src/gui/checkbox.h18
-rw-r--r--src/gui/color.cpp146
-rw-r--r--src/gui/color.h136
-rw-r--r--src/gui/confirm_dialog.cpp67
-rw-r--r--src/gui/confirm_dialog.h23
-rw-r--r--src/gui/connection.cpp15
-rw-r--r--src/gui/connection.h12
-rw-r--r--src/gui/debugwindow.cpp75
-rw-r--r--src/gui/debugwindow.h16
-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.h66
-rw-r--r--src/gui/equipmentwindow.cpp199
-rw-r--r--src/gui/equipmentwindow.h64
-rw-r--r--src/gui/focushandler.cpp11
-rw-r--r--src/gui/focushandler.h14
-rw-r--r--src/gui/gccontainer.cpp8
-rw-r--r--src/gui/gccontainer.h12
-rw-r--r--src/gui/gui.cpp91
-rw-r--r--src/gui/gui.h20
-rw-r--r--src/gui/hbox.cpp39
-rw-r--r--src/gui/help.cpp31
-rw-r--r--src/gui/help.h16
-rw-r--r--src/gui/inttextbox.cpp74
-rw-r--r--src/gui/inttextfield.cpp104
-rw-r--r--src/gui/inttextfield.h (renamed from src/gui/inttextbox.h)36
-rw-r--r--src/gui/inventorywindow.cpp218
-rw-r--r--src/gui/inventorywindow.h59
-rw-r--r--src/gui/item_amount.cpp42
-rw-r--r--src/gui/item_amount.h22
-rw-r--r--src/gui/itemcontainer.cpp58
-rw-r--r--src/gui/itemcontainer.h42
-rw-r--r--src/gui/itemlinkhandler.cpp27
-rw-r--r--src/gui/itemlinkhandler.h12
-rw-r--r--src/gui/itempopup.cpp183
-rw-r--r--src/gui/itempopup.h24
-rw-r--r--src/gui/itemshortcutcontainer.cpp187
-rw-r--r--src/gui/itemshortcutcontainer.h55
-rw-r--r--src/gui/linkhandler.h14
-rw-r--r--src/gui/listbox.cpp48
-rw-r--r--src/gui/listbox.h16
-rw-r--r--src/gui/login.cpp266
-rw-r--r--src/gui/login.h87
-rw-r--r--src/gui/magic.cpp1
-rw-r--r--src/gui/menuwindow.cpp42
-rw-r--r--src/gui/menuwindow.h14
-rw-r--r--src/gui/minimap.cpp120
-rw-r--r--src/gui/minimap.h24
-rw-r--r--src/gui/ministatus.cpp122
-rw-r--r--src/gui/ministatus.h37
-rw-r--r--src/gui/npc_text.cpp95
-rw-r--r--src/gui/npc_text.h49
-rw-r--r--src/gui/npcintegerdialog.cpp125
-rw-r--r--src/gui/npcintegerdialog.h87
-rw-r--r--src/gui/npclistdialog.cpp78
-rw-r--r--src/gui/npclistdialog.h38
-rw-r--r--src/gui/npcstringdialog.cpp89
-rw-r--r--src/gui/npcstringdialog.h76
-rw-r--r--src/gui/ok_dialog.cpp62
-rw-r--r--src/gui/ok_dialog.h23
-rw-r--r--src/gui/passwordfield.cpp10
-rw-r--r--src/gui/passwordfield.h15
-rw-r--r--src/gui/playerbox.cpp36
-rw-r--r--src/gui/playerbox.h16
-rw-r--r--src/gui/popupmenu.cpp181
-rw-r--r--src/gui/popupmenu.h19
-rw-r--r--src/gui/progressbar.cpp65
-rw-r--r--src/gui/progressbar.h75
-rw-r--r--src/gui/radiobutton.cpp47
-rw-r--r--src/gui/radiobutton.h19
-rw-r--r--src/gui/recorder.cpp116
-rw-r--r--src/gui/recorder.h76
-rw-r--r--src/gui/register.cpp179
-rw-r--r--src/gui/register.h48
-rw-r--r--src/gui/scrollarea.cpp62
-rw-r--r--src/gui/scrollarea.h22
-rw-r--r--src/gui/sdlinput.cpp4
-rw-r--r--src/gui/sdlinput.h6
-rw-r--r--src/gui/sell.cpp71
-rw-r--r--src/gui/sell.h30
-rw-r--r--src/gui/serverdialog.cpp2
-rw-r--r--src/gui/setup.cpp65
-rw-r--r--src/gui/setup.h17
-rw-r--r--src/gui/setup_audio.cpp40
-rw-r--r--src/gui/setup_audio.h16
-rw-r--r--src/gui/setup_colors.cpp249
-rw-r--r--src/gui/setup_colors.h75
-rw-r--r--src/gui/setup_joystick.cpp45
-rw-r--r--src/gui/setup_joystick.h16
-rw-r--r--src/gui/setup_keyboard.cpp49
-rw-r--r--src/gui/setup_keyboard.h21
-rw-r--r--src/gui/setup_players.cpp388
-rw-r--r--src/gui/setup_players.h67
-rw-r--r--src/gui/setup_video.cpp311
-rw-r--r--src/gui/setup_video.h48
-rw-r--r--src/gui/setuptab.h16
-rw-r--r--src/gui/shop.cpp19
-rw-r--r--src/gui/shop.h23
-rw-r--r--src/gui/shoplistbox.cpp36
-rw-r--r--src/gui/shoplistbox.h17
-rw-r--r--src/gui/shortcutcontainer.cpp71
-rw-r--r--src/gui/shortcutcontainer.h107
-rw-r--r--src/gui/shortcutwindow.cpp83
-rw-r--r--src/gui/shortcutwindow.h65
-rw-r--r--src/gui/skill.cpp372
-rw-r--r--src/gui/skill.h108
-rw-r--r--src/gui/skilldialog.cpp263
-rw-r--r--src/gui/skilldialog.h139
-rw-r--r--src/gui/slider.cpp24
-rw-r--r--src/gui/slider.h14
-rw-r--r--src/gui/speechbubble.cpp76
-rw-r--r--src/gui/speechbubble.h24
-rw-r--r--src/gui/status.cpp402
-rw-r--r--src/gui/status.h35
-rw-r--r--src/gui/statuswindow.cpp370
-rw-r--r--src/gui/statuswindow.h105
-rw-r--r--src/gui/table.cpp561
-rw-r--r--src/gui/table.h187
-rw-r--r--src/gui/table_model.cpp161
-rw-r--r--src/gui/table_model.h144
-rw-r--r--src/gui/textbox.cpp68
-rw-r--r--src/gui/textbox.h25
-rw-r--r--src/gui/textfield.cpp68
-rw-r--r--src/gui/textfield.h54
-rw-r--r--src/gui/trade.cpp234
-rw-r--r--src/gui/trade.h70
-rw-r--r--src/gui/truetypefont.cpp48
-rw-r--r--src/gui/truetypefont.h31
-rw-r--r--src/gui/unregisterdialog.h12
-rw-r--r--src/gui/updatewindow.cpp88
-rw-r--r--src/gui/updatewindow.h11
-rw-r--r--src/gui/vbox.cpp43
-rw-r--r--src/gui/viewport.cpp345
-rw-r--r--src/gui/viewport.h102
-rw-r--r--src/gui/widgets/dropdown.cpp70
-rw-r--r--src/gui/widgets/dropdown.h34
-rw-r--r--src/gui/widgets/layout.cpp8
-rw-r--r--src/gui/widgets/layout.h14
-rw-r--r--src/gui/widgets/layouthelper.cpp63
-rw-r--r--src/gui/widgets/layouthelper.h84
-rw-r--r--src/gui/widgets/resizegrip.cpp28
-rw-r--r--src/gui/widgets/resizegrip.h15
-rw-r--r--src/gui/widgets/tab.cpp32
-rw-r--r--src/gui/widgets/tab.h13
-rw-r--r--src/gui/widgets/tabbedarea.cpp12
-rw-r--r--src/gui/widgets/tabbedarea.h12
-rw-r--r--src/gui/window.cpp209
-rw-r--r--src/gui/window.h58
-rw-r--r--src/gui/windowcontainer.cpp8
-rw-r--r--src/gui/windowcontainer.h15
-rw-r--r--src/guichanfwd.h15
-rw-r--r--src/imageparticle.cpp11
-rw-r--r--src/imageparticle.h8
-rw-r--r--src/inventory.cpp106
-rw-r--r--src/inventory.h34
-rw-r--r--src/item.cpp23
-rw-r--r--src/item.h62
-rw-r--r--src/itemshortcut.cpp44
-rw-r--r--src/itemshortcut.h14
-rw-r--r--src/joystick.cpp11
-rw-r--r--src/joystick.h22
-rw-r--r--src/keyboardconfig.cpp140
-rw-r--r--src/keyboardconfig.h61
-rw-r--r--src/localplayer.cpp700
-rw-r--r--src/localplayer.h257
-rw-r--r--src/lockedarray.h12
-rw-r--r--src/log.cpp10
-rw-r--r--src/log.h9
-rw-r--r--src/logindata.h34
-rw-r--r--src/main.cpp1574
-rw-r--r--src/main.h48
-rw-r--r--src/map.cpp143
-rw-r--r--src/map.h86
-rw-r--r--src/monster.cpp144
-rw-r--r--src/monster.h49
-rw-r--r--src/net/accountserver/internal.h8
-rw-r--r--src/net/buysellhandler.cpp11
-rw-r--r--src/net/buysellhandler.h12
-rw-r--r--src/net/charserverhandler.cpp2
-rw-r--r--src/net/chathandler.cpp2
-rw-r--r--src/net/chathandler.h12
-rw-r--r--src/net/ea/beinghandler.cpp542
-rw-r--r--src/net/ea/beinghandler.h39
-rw-r--r--src/net/ea/buysellhandler.cpp133
-rw-r--r--src/net/ea/buysellhandler.h35
-rw-r--r--src/net/ea/charserverhandler.cpp235
-rw-r--r--src/net/ea/charserverhandler.h65
-rw-r--r--src/net/ea/chathandler.cpp175
-rw-r--r--src/net/ea/chathandler.h (renamed from src/gui/hbox.h)22
-rw-r--r--src/net/ea/equipmenthandler.cpp190
-rw-r--r--src/net/ea/equipmenthandler.h35
-rw-r--r--src/net/ea/inventoryhandler.cpp227
-rw-r--r--src/net/ea/inventoryhandler.h35
-rw-r--r--src/net/ea/loginhandler.cpp158
-rw-r--r--src/net/ea/loginhandler.h45
-rw-r--r--src/net/ea/maploginhandler.cpp76
-rw-r--r--src/net/ea/maploginhandler.h35
-rw-r--r--src/net/ea/network.cpp436
-rw-r--r--src/net/ea/network.h118
-rw-r--r--src/net/ea/npchandler.cpp111
-rw-r--r--src/net/ea/npchandler.h (renamed from src/gui/vbox.h)20
-rw-r--r--src/net/ea/partyhandler.cpp122
-rw-r--r--src/net/ea/partyhandler.h39
-rw-r--r--src/net/ea/playerhandler.cpp417
-rw-r--r--src/net/ea/playerhandler.h (renamed from src/gui/box.cpp)33
-rw-r--r--src/net/ea/protocol.cpp77
-rw-r--r--src/net/ea/protocol.h162
-rw-r--r--src/net/ea/skillhandler.cpp93
-rw-r--r--src/net/ea/skillhandler.h (renamed from src/utils/tostring.h)26
-rw-r--r--src/net/ea/tradehandler.cpp220
-rw-r--r--src/net/ea/tradehandler.h37
-rw-r--r--src/net/effecthandler.cpp8
-rw-r--r--src/net/inventoryhandler.h12
-rw-r--r--src/net/itemhandler.cpp9
-rw-r--r--src/net/itemhandler.h12
-rw-r--r--src/net/messagehandler.cpp35
-rw-r--r--src/net/messagehandler.h23
-rw-r--r--src/net/messagein.cpp125
-rw-r--r--src/net/messagein.h63
-rw-r--r--src/net/messageout.cpp83
-rw-r--r--src/net/messageout.h39
-rw-r--r--src/net/npchandler.h12
-rw-r--r--src/net/playerhandler.cpp4
-rw-r--r--src/net/playerhandler.h18
-rw-r--r--src/net/tradehandler.h12
-rw-r--r--src/npc.cpp193
-rw-r--r--src/npc.h51
-rw-r--r--src/openglgraphics.cpp31
-rw-r--r--src/openglgraphics.h12
-rw-r--r--src/particle.cpp54
-rw-r--r--src/particle.h29
-rw-r--r--src/particlecontainer.cpp174
-rw-r--r--src/particlecontainer.h121
-rw-r--r--src/particleemitter.cpp133
-rw-r--r--src/particleemitter.h48
-rw-r--r--src/particleemitterprop.h109
-rw-r--r--src/party.cpp217
-rw-r--r--src/party.h76
-rw-r--r--src/player.cpp132
-rw-r--r--src/player.h66
-rw-r--r--src/player_relations.cpp369
-rw-r--r--src/player_relations.h241
-rw-r--r--src/position.cpp8
-rw-r--r--src/position.h14
-rw-r--r--src/properties.h14
-rw-r--r--src/resources/action.cpp10
-rw-r--r--src/resources/action.h18
-rw-r--r--src/resources/ambientoverlay.cpp9
-rw-r--r--src/resources/ambientoverlay.h12
-rw-r--r--src/resources/animation.cpp19
-rw-r--r--src/resources/animation.h30
-rw-r--r--src/resources/colordb.cpp122
-rw-r--r--src/resources/colordb.h52
-rw-r--r--src/resources/dye.cpp9
-rw-r--r--src/resources/dye.h17
-rw-r--r--src/resources/emotedb.cpp140
-rw-r--r--src/resources/emotedb.h60
-rw-r--r--src/resources/image.cpp54
-rw-r--r--src/resources/image.h49
-rw-r--r--src/resources/imageloader.cpp13
-rw-r--r--src/resources/imageloader.h12
-rw-r--r--src/resources/imageset.cpp14
-rw-r--r--src/resources/imageset.h13
-rw-r--r--src/resources/imagewriter.cpp14
-rw-r--r--src/resources/imagewriter.h12
-rw-r--r--src/resources/itemdb.cpp45
-rw-r--r--src/resources/itemdb.h16
-rw-r--r--src/resources/iteminfo.cpp43
-rw-r--r--src/resources/iteminfo.h32
-rw-r--r--src/resources/mapreader.cpp155
-rw-r--r--src/resources/mapreader.h16
-rw-r--r--src/resources/monsterdb.cpp33
-rw-r--r--src/resources/monsterdb.h20
-rw-r--r--src/resources/monsterinfo.cpp27
-rw-r--r--src/resources/monsterinfo.h55
-rw-r--r--src/resources/music.cpp14
-rw-r--r--src/resources/music.h23
-rw-r--r--src/resources/npcdb.cpp22
-rw-r--r--src/resources/npcdb.h20
-rw-r--r--src/resources/resource.cpp15
-rw-r--r--src/resources/resource.h21
-rw-r--r--src/resources/resourcemanager.cpp31
-rw-r--r--src/resources/resourcemanager.h18
-rw-r--r--src/resources/soundeffect.cpp11
-rw-r--r--src/resources/soundeffect.h22
-rw-r--r--src/resources/spritedef.cpp21
-rw-r--r--src/resources/spritedef.h31
-rw-r--r--src/serverinfo.h12
-rw-r--r--src/shopitem.cpp13
-rw-r--r--src/shopitem.h12
-rw-r--r--src/simpleanimation.cpp48
-rw-r--r--src/simpleanimation.h30
-rw-r--r--src/sound.cpp20
-rw-r--r--src/sound.h17
-rw-r--r--src/sprite.h24
-rw-r--r--src/statuseffect.cpp170
-rw-r--r--src/statuseffect.h108
-rw-r--r--src/text.cpp183
-rw-r--r--src/text.h102
-rw-r--r--src/textmanager.cpp169
-rw-r--r--src/textmanager.h77
-rw-r--r--src/textparticle.cpp11
-rw-r--r--src/textparticle.h17
-rw-r--r--src/tileset.h12
-rw-r--r--src/tmw.rc2
-rw-r--r--src/units.cpp232
-rw-r--r--src/units.h46
-rw-r--r--src/utils/base64.cpp2
-rw-r--r--src/utils/base64.h6
-rw-r--r--src/utils/dtor.h12
-rw-r--r--src/utils/gettext.h12
-rw-r--r--src/utils/minmax.h69
-rw-r--r--src/utils/mutex.h14
-rw-r--r--src/utils/sha256.h14
-rw-r--r--src/utils/stringutils.cpp (renamed from src/utils/trim.h)40
-rw-r--r--src/utils/stringutils.h68
-rw-r--r--src/utils/strprintf.cpp8
-rw-r--r--src/utils/strprintf.h12
-rw-r--r--src/utils/xml.cpp10
-rw-r--r--src/utils/xml.h12
-rw-r--r--src/vector.cpp8
-rw-r--r--src/vector.h14
374 files changed, 24967 insertions, 6217 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9b1dd0e9..94688e66 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,6 +1,7 @@
FIND_PACKAGE(SDL REQUIRED)
FIND_PACKAGE(SDL_image REQUIRED)
FIND_PACKAGE(SDL_mixer REQUIRED)
+FIND_PACKAGE(SDL_net REQUIRED)
FIND_PACKAGE(SDL_ttf REQUIRED)
FIND_PACKAGE(ENet REQUIRED)
FIND_PACKAGE(CURL REQUIRED)
@@ -28,6 +29,7 @@ INCLUDE_DIRECTORIES(
${SDL_INCLUDE_DIR}
${SDLIMAGE_INCLUDE_DIR}
${SDLMIXER_INCLUDE_DIR}
+ ${SDLNET_INCLUDE_DIR}
${SDLTTF_INCLUDE_DIR}
${ENET_INCLUDE_DIR}
${PNG_INCLUDE_DIR}
@@ -45,6 +47,8 @@ MARK_AS_ADVANCED(SDLIMAGE_LIBRARY)
MARK_AS_ADVANCED(SDLMAIN_LIBRARY)
MARK_AS_ADVANCED(SDLMIXER_INCLUDE_DIR)
MARK_AS_ADVANCED(SDLMIXER_LIBRARY)
+MARK_AS_ADVANCED(SDLNET_INCLUDE_DIR)
+MARK_AS_ADVANCED(SDLNET_LIBRARY)
MARK_AS_ADVANCED(SDL_INCLUDE_DIR)
MARK_AS_ADVANCED(SDL_LIBRARY)
@@ -57,12 +61,12 @@ SET(SRCS
gui/widgets/resizegrip.h
gui/widgets/layout.cpp
gui/widgets/layout.h
+ gui/widgets/layouthelper.cpp
+ gui/widgets/layouthelper.h
gui/widgets/tab.cpp
gui/widgets/tab.h
gui/widgets/tabbedarea.cpp
gui/widgets/tabbedarea.h
- gui/box.cpp
- gui/box.h
gui/browserbox.cpp
gui/browserbox.h
gui/buddywindow.cpp
@@ -77,6 +81,8 @@ SET(SRCS
gui/changeemaildialog.h
gui/changepassworddialog.cpp
gui/changepassworddialog.h
+ gui/char_server.cpp
+ gui/char_server.h
gui/char_select.cpp
gui/char_select.h
gui/chat.cpp
@@ -85,12 +91,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
@@ -103,18 +117,14 @@ SET(SRCS
gui/guildlistbox.h
gui/guildwindow.cpp
gui/guildwindow.h
- gui/hbox.cpp
- gui/hbox.h
gui/help.cpp
gui/help.h
gui/icon.cpp
gui/icon.h
- gui/inttextbox.cpp
- gui/inttextbox.h
+ gui/inttextfield.cpp
+ gui/inttextfield.h
gui/inventorywindow.cpp
gui/inventorywindow.h
- gui/item_amount.cpp
- gui/item_amount.h
gui/itemcontainer.cpp
gui/itemcontainer.h
gui/itemlinkhandler.cpp
@@ -122,9 +132,9 @@ SET(SRCS
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
gui/listbox.cpp
gui/listbox.h
@@ -138,8 +148,12 @@ SET(SRCS
gui/minimap.h
gui/ministatus.cpp
gui/ministatus.h
+ gui/npcintegerdialog.cpp
+ gui/npcintegerdialog.h
gui/npclistdialog.cpp
gui/npclistdialog.h
+ gui/npcstringdialog.cpp
+ gui/npcstringdialog.h
gui/npcpostdialog.cpp
gui/npcpostdialog.h
gui/npc_text.cpp
@@ -160,6 +174,8 @@ SET(SRCS
gui/quitdialog.h
gui/radiobutton.cpp
gui/radiobutton.h
+ gui/recorder.cpp
+ gui/recorder.h
gui/register.cpp
gui/register.h
gui/scrollarea.cpp
@@ -170,14 +186,18 @@ SET(SRCS
gui/sell.h
gui/serverdialog.cpp
gui/serverdialog.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
gui/setup_keyboard.h
+ gui/setup_players.cpp
+ gui/setup_players.h
gui/setuptab.h
gui/setup_video.cpp
gui/setup_video.h
@@ -185,6 +205,10 @@ 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
@@ -193,6 +217,10 @@ SET(SRCS
gui/speechbubble.h
gui/status.cpp
gui/status.h
+ gui/table.cpp
+ gui/table.h
+ gui/table_model.cpp
+ gui/table_model.h
gui/textbox.cpp
gui/textbox.h
gui/textdialog.cpp
@@ -207,8 +235,6 @@ SET(SRCS
gui/unregisterdialog.h
gui/updatewindow.cpp
gui/updatewindow.h
- gui/vbox.cpp
- gui/vbox.h
gui/viewport.cpp
gui/viewport.h
gui/window.cpp
@@ -225,6 +251,8 @@ SET(SRCS
net/chathandler.h
net/connection.cpp
net/connection.h
+ net/equipmenthandler.cpp
+ net/equipmenthandler.h
net/guildhandler.cpp
net/guildhandler.h
net/internal.cpp
@@ -237,6 +265,8 @@ SET(SRCS
net/loginhandler.h
net/logouthandler.cpp
net/logouthandler.h
+ net/maploginhandler.cpp
+ net/maploginhandler.h
net/messagehandler.cpp
net/messagehandler.h
net/messagein.cpp
@@ -251,7 +281,10 @@ SET(SRCS
net/partyhandler.h
net/playerhandler.cpp
net/playerhandler.h
+ net/protocol.cpp
net/protocol.h
+ net/skillhandler.cpp
+ net/skillhandler.h
net/tradehandler.cpp
net/tradehandler.h
net/effecthandler.cpp
@@ -284,8 +317,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
@@ -321,13 +358,12 @@ SET(SRCS
utils/dtor.h
utils/fastsqrt.h
utils/gettext.h
- utils/minmax.h
utils/sha256.h
utils/sha256.cpp
+ utils/stringutils.cpp
+ utils/stringutils.h
utils/strprintf.cpp
utils/strprintf.h
- utils/tostring.h
- utils/trim.h
utils/xml.cpp
utils/xml.h
animatedsprite.cpp
@@ -347,6 +383,10 @@ SET(SRCS
configlistener.h
configuration.cpp
configuration.h
+ effectmanager.cpp
+ effectmanager.h
+ emoteshortcut.cpp
+ emoteshortcut.h
engine.cpp
engine.h
equipment.cpp
@@ -392,10 +432,17 @@ 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
+ player_relations.h
position.cpp
position.h
properties.h
@@ -407,6 +454,10 @@ SET(SRCS
sound.cpp
sound.h
sprite.h
+ text.cpp
+ text.h
+ textmanager.cpp
+ textmanager.h
textparticle.cpp
textparticle.h
tileset.h
@@ -422,6 +473,7 @@ TARGET_LINK_LIBRARIES(tmw
${SDL_LIBRARY}
${SDLIMAGE_LIBRARY}
${SDLMIXER_LIBRARY}
+ ${SDLNET_LIBRARY}
${SDLTTF_LIBRARY}
${ENET_LIBRARIES}
${PNG_LIBRARIES}
diff --git a/src/Makefile.am b/src/Makefile.am
index d3926a70..ce51b12d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,34 +1,32 @@
AUTOMAKE_OPTIONS = subdir-objects
bin_PROGRAMS = tmw
+
+tmw_CXXFLAGS = -DPKG_DATADIR=\""$(pkgdatadir)/"\" \
+ -DLOCALEDIR=\""$(localedir)"\"
+
tmw_SOURCES = gui/widgets/avatar.cpp \
- gui/widgets/avatar.h \
- gui/widgets/dropdown.cpp \
+ gui/widgets/avatar.h \
+ gui/widgets/dropdown.cpp \
gui/widgets/dropdown.h \
gui/widgets/layout.cpp \
gui/widgets/layout.h \
+ gui/widgets/layouthelper.cpp \
+ gui/widgets/layouthelper.h \
gui/widgets/resizegrip.cpp \
gui/widgets/resizegrip.h \
gui/widgets/tab.cpp \
gui/widgets/tab.h \
gui/widgets/tabbedarea.cpp \
gui/widgets/tabbedarea.h \
- gui/box.h \
- gui/box.cpp \
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/changeemaildialog.cpp \
- gui/changeemaildialog.h \
- gui/changepassworddialog.cpp \
- gui/changepassworddialog.h \
gui/char_select.cpp \
gui/char_select.h \
gui/chat.cpp \
@@ -37,12 +35,18 @@ tmw_SOURCES = gui/widgets/avatar.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 \
@@ -51,30 +55,22 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
gui/gccontainer.h \
gui/gui.cpp \
gui/gui.h \
- gui/guildwindow.cpp \
- gui/guildwindow.h \
- gui/guildlistbox.cpp \
- gui/guildlistbox.h \
- gui/hbox.h \
- gui/hbox.cpp \
gui/help.cpp \
gui/help.h \
- gui/icon.h \
gui/icon.cpp \
- gui/inttextbox.h \
- gui/inttextbox.cpp \
+ gui/icon.h \
+ gui/inttextfield.cpp \
+ gui/inttextfield.h \
gui/inventorywindow.cpp \
gui/inventorywindow.h \
gui/itemcontainer.cpp \
gui/itemcontainer.h \
- gui/itemlinkhandler.cpp \
- gui/itemlinkhandler.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 \
@@ -82,26 +78,22 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
gui/listbox.h \
gui/login.cpp \
gui/login.h \
- gui/magic.cpp \
- gui/magic.h \
gui/menuwindow.cpp \
gui/menuwindow.h \
gui/minimap.cpp \
gui/minimap.h \
gui/ministatus.cpp \
gui/ministatus.h \
+ gui/npcintegerdialog.cpp \
+ gui/npcintegerdialog.h \
gui/npclistdialog.cpp \
gui/npclistdialog.h \
- gui/npcpostdialog.cpp \
- gui/npcpostdialog.h \
+ gui/npcstringdialog.cpp \
+ gui/npcstringdialog.h \
gui/npc_text.cpp \
gui/npc_text.h \
gui/ok_dialog.cpp \
gui/ok_dialog.h \
- gui/truetypefont.cpp \
- gui/truetypefont.h \
- gui/partywindow.h \
- gui/partywindow.cpp \
gui/passwordfield.cpp \
gui/passwordfield.h \
gui/playerbox.cpp \
@@ -110,10 +102,10 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
gui/popupmenu.h \
gui/progressbar.cpp \
gui/progressbar.h \
- gui/quitdialog.cpp \
- gui/quitdialog.h \
gui/radiobutton.cpp \
gui/radiobutton.h \
+ gui/recorder.cpp \
+ gui/recorder.h \
gui/register.cpp \
gui/register.h \
gui/scrollarea.cpp \
@@ -122,16 +114,18 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
gui/sdlinput.h \
gui/sell.cpp \
gui/sell.h \
- gui/serverdialog.cpp \
- gui/serverdialog.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 \
gui/setup_keyboard.h \
+ gui/setup_players.cpp \
+ gui/setup_players.h \
gui/setuptab.h \
gui/setup_video.cpp \
gui/setup_video.h \
@@ -139,14 +133,18 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
gui/shop.h \
gui/shoplistbox.cpp \
gui/shoplistbox.h \
- gui/skill.cpp \
- gui/skill.h \
+ gui/shortcutwindow.cpp \
+ gui/shortcutwindow.h \
+ gui/shortcutcontainer.cpp \
+ gui/shortcutcontainer.h \
gui/slider.cpp \
gui/slider.h \
gui/speechbubble.cpp \
gui/speechbubble.h \
- gui/status.cpp \
- gui/status.h \
+ gui/table.cpp \
+ gui/table.h \
+ gui/table_model.cpp \
+ gui/table_model.h \
gui/textbox.cpp \
gui/textbox.h \
gui/textdialog.cpp \
@@ -155,87 +153,36 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
gui/textfield.h \
gui/trade.cpp \
gui/trade.h \
- gui/unregisterdialog.cpp \
- gui/unregisterdialog.h \
- gui/updatewindow.h \
+ gui/truetypefont.cpp \
+ gui/truetypefont.h \
gui/updatewindow.cpp \
- gui/vbox.h \
- gui/vbox.cpp \
+ gui/updatewindow.h \
gui/viewport.cpp \
gui/viewport.h \
gui/window.cpp \
gui/window.h \
gui/windowcontainer.cpp \
gui/windowcontainer.h \
- net/beinghandler.h \
- net/beinghandler.cpp \
- net/buysellhandler.h \
- net/buysellhandler.cpp \
- net/charserverhandler.h \
- net/charserverhandler.cpp \
- net/chathandler.h \
- net/chathandler.cpp \
- net/connection.h \
- net/connection.cpp \
- net/guildhandler.cpp \
- net/guildhandler.h \
- net/internal.h \
- net/internal.cpp \
- net/inventoryhandler.h \
- net/inventoryhandler.cpp \
net/itemhandler.h \
net/itemhandler.cpp \
- net/loginhandler.h \
- net/loginhandler.cpp \
- net/logouthandler.cpp \
- net/logouthandler.h \
net/messagehandler.cpp \
net/messagehandler.h \
net/messagein.cpp \
net/messagein.h \
net/messageout.cpp \
net/messageout.h \
- net/network.cpp \
- net/network.h \
- net/npchandler.cpp \
- net/npchandler.h \
- net/partyhandler.cpp \
- net/partyhandler.h \
- net/playerhandler.cpp \
- net/playerhandler.h \
- net/protocol.h \
- net/tradehandler.cpp \
- net/tradehandler.h \
- net/effecthandler.h \
- net/effecthandler.cpp \
- net/accountserver/account.cpp \
- net/accountserver/account.h \
- net/accountserver/accountserver.cpp \
- net/accountserver/accountserver.h \
- net/accountserver/internal.cpp \
- net/accountserver/internal.h \
- net/chatserver/chatserver.cpp \
- net/chatserver/chatserver.h \
- net/chatserver/internal.cpp \
- net/chatserver/internal.h \
- net/chatserver/guild.cpp \
- net/chatserver/guild.h \
- net/chatserver/party.cpp \
- net/chatserver/party.h \
- net/gameserver/gameserver.cpp \
- net/gameserver/gameserver.h \
- net/gameserver/internal.cpp \
- net/gameserver/internal.h \
- net/gameserver/player.cpp \
- net/gameserver/player.h \
resources/action.cpp \
resources/action.h \
resources/ambientoverlay.cpp \
resources/ambientoverlay.h \
resources/animation.cpp \
resources/animation.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 \
@@ -266,20 +213,17 @@ tmw_SOURCES = gui/widgets/avatar.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 \
utils/fastsqrt.h \
utils/gettext.h \
- utils/minmax.h \
- utils/sha256.h \
utils/sha256.cpp \
+ utils/sha256.h \
+ utils/stringutils.cpp \
+ utils/stringutils.h \
utils/strprintf.cpp \
utils/strprintf.h \
- utils/tostring.h \
- utils/trim.h \
utils/mutex.h \
utils/xml.cpp \
utils/xml.h \
@@ -295,11 +239,13 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
channel.h \
channelmanager.cpp \
channelmanager.h \
- commandhandler.cpp \
- commandhandler.h \
configlistener.h \
configuration.cpp \
configuration.h \
+ effectmanager.cpp \
+ effectmanager.h \
+ emoteshortcut.cpp \
+ emoteshortcut.h \
engine.cpp \
engine.h \
equipment.cpp \
@@ -312,8 +258,6 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
game.h \
graphics.cpp \
graphics.h \
- guild.cpp \
- guild.h \
guichanfwd.h \
imageparticle.cpp \
imageparticle.h \
@@ -345,10 +289,15 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
openglgraphics.h \
particle.cpp \
particle.h \
+ particlecontainer.cpp \
+ particlecontainer.h \
particleemitter.cpp \
particleemitter.h \
+ particleemitterprop.h \
player.cpp \
player.h \
+ player_relations.cpp \
+ player_relations.h \
position.cpp \
position.h \
properties.h \
@@ -360,16 +309,154 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
sound.cpp \
sound.h \
sprite.h \
+ statuseffect.cpp \
+ statuseffect.h \
+ text.cpp \
+ text.h \
+ textmanager.cpp \
+ textmanager.h \
textparticle.cpp \
textparticle.h \
tileset.h \
+ units.cpp \
+ units.h \
vector.cpp \
- vector.h \
- effectmanager.cpp \
- effectmanager.h
+ vector.h
+
+if SERVER_TMWSERV
+tmw_CXXFLAGS += -DTMWSERV_SUPPORT
+tmw_SOURCES += \
+ gui/buddywindow.cpp \
+ gui/buddywindow.h \
+ gui/changeemaildialog.cpp \
+ gui/changeemaildialog.h \
+ gui/changepassworddialog.cpp \
+ gui/changepassworddialog.h \
+ gui/connection.cpp \
+ gui/connection.h \
+ gui/guildlistbox.cpp \
+ gui/guildlistbox.h \
+ gui/guildwindow.cpp \
+ gui/guildwindow.h \
+ gui/magic.cpp \
+ gui/magic.h \
+ gui/npcpostdialog.cpp \
+ gui/npcpostdialog.h \
+ gui/partywindow.cpp \
+ gui/partywindow.h \
+ gui/quitdialog.cpp \
+ gui/quitdialog.h \
+ gui/serverdialog.cpp \
+ gui/serverdialog.h \
+ gui/skilldialog.cpp \
+ gui/skilldialog.h \
+ gui/statuswindow.cpp \
+ gui/statuswindow.h \
+ gui/unregisterdialog.cpp \
+ gui/unregisterdialog.h \
+ net/accountserver/account.cpp \
+ net/accountserver/account.h \
+ net/accountserver/accountserver.cpp \
+ net/accountserver/accountserver.h \
+ net/accountserver/internal.cpp \
+ net/accountserver/internal.h \
+ net/chatserver/chatserver.cpp \
+ net/chatserver/chatserver.h \
+ net/chatserver/guild.cpp \
+ net/chatserver/guild.h \
+ net/chatserver/internal.cpp \
+ net/chatserver/internal.h \
+ net/chatserver/party.cpp \
+ net/chatserver/party.h \
+ net/gameserver/gameserver.cpp \
+ net/gameserver/gameserver.h \
+ net/gameserver/internal.cpp \
+ net/gameserver/internal.h \
+ net/gameserver/player.cpp \
+ net/gameserver/player.h \
+ net/beinghandler.cpp \
+ net/beinghandler.h \
+ net/buysellhandler.cpp \
+ net/buysellhandler.h \
+ net/charserverhandler.cpp \
+ net/charserverhandler.h \
+ net/chathandler.cpp \
+ net/chathandler.h \
+ net/connection.cpp \
+ net/connection.h \
+ net/effecthandler.cpp \
+ net/effecthandler.h \
+ net/guildhandler.cpp \
+ net/guildhandler.h \
+ net/internal.cpp \
+ net/internal.h \
+ net/inventoryhandler.cpp \
+ net/inventoryhandler.h \
+ net/loginhandler.cpp \
+ net/loginhandler.h \
+ net/logouthandler.cpp \
+ net/logouthandler.h \
+ net/network.cpp \
+ net/network.h \
+ net/npchandler.cpp \
+ net/npchandler.h \
+ net/partyhandler.cpp \
+ net/partyhandler.h \
+ net/playerhandler.cpp \
+ net/playerhandler.h \
+ net/protocol.h \
+ net/tradehandler.cpp \
+ net/tradehandler.h \
+ resources/buddylist.cpp \
+ resources/buddylist.h \
+ commandhandler.cpp \
+ commandhandler.h \
+ guild.cpp \
+ guild.h
+endif
+
+if SERVER_EATHENA
+tmw_CXXFLAGS += -DEATHENA_SUPPORT
+tmw_SOURCES += \
+ gui/char_server.cpp \
+ gui/char_server.h \
+ gui/skill.cpp \
+ gui/skill.h \
+ gui/status.cpp \
+ gui/status.h \
+ net/ea/beinghandler.cpp \
+ net/ea/beinghandler.h \
+ net/ea/buysellhandler.cpp \
+ net/ea/buysellhandler.h \
+ net/ea/charserverhandler.cpp \
+ net/ea/charserverhandler.h \
+ net/ea/chathandler.cpp \
+ net/ea/chathandler.h \
+ net/ea/equipmenthandler.cpp \
+ net/ea/equipmenthandler.h \
+ net/ea/inventoryhandler.cpp \
+ net/ea/inventoryhandler.h \
+ net/ea/loginhandler.cpp \
+ net/ea/loginhandler.h \
+ net/ea/maploginhandler.cpp \
+ net/ea/maploginhandler.h \
+ net/ea/network.cpp \
+ net/ea/network.h \
+ net/ea/npchandler.cpp \
+ net/ea/npchandler.h \
+ net/ea/partyhandler.cpp \
+ net/ea/partyhandler.h \
+ net/ea/playerhandler.cpp \
+ net/ea/playerhandler.h \
+ net/ea/protocol.cpp \
+ net/ea/protocol.h \
+ net/ea/skillhandler.cpp \
+ net/ea/skillhandler.h \
+ net/ea/tradehandler.cpp \
+ net/ea/tradehandler.h \
+ party.cpp \
+ party.h
+endif
# set the include path found by configure
-INCLUDES = \
- $(all_includes) \
- -DTMW_DATADIR=\""$(pkgdatadir)/"\" \
- -DLOCALEDIR=\""$(localedir)"\"
+INCLUDES = $(all_includes)
diff --git a/src/SDLMain.h b/src/SDLMain.h
new file mode 100644
index 00000000..4683df57
--- /dev/null
+++ b/src/SDLMain.h
@@ -0,0 +1,11 @@
+/* SDLMain.m - main entry point for our Cocoa-ized SDL app
+ Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
+ Non-NIB-Code & other changes: Max Horn <max@quendi.de>
+
+ Feel free to customize this file to suit your needs
+*/
+
+#import <Cocoa/Cocoa.h>
+
+@interface SDLMain : NSObject
+@end
diff --git a/src/SDLMain.m b/src/SDLMain.m
new file mode 100644
index 00000000..3d02719c
--- /dev/null
+++ b/src/SDLMain.m
@@ -0,0 +1,383 @@
+/* SDLMain.m - main entry point for our Cocoa-ized SDL app
+ Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
+ Non-NIB-Code & other changes: Max Horn <max@quendi.de>
+
+ Feel free to customize this file to suit your needs
+ */
+
+#import "SDL.h"
+#import "SDLMain.h"
+#import <sys/param.h> /* for MAXPATHLEN */
+#import <unistd.h>
+
+/* For some reaon, Apple removed setAppleMenu from the headers in 10.4,
+ but the method still is there and works. To avoid warnings, we declare
+ it ourselves here. */
+@interface NSApplication(SDL_Missing_Methods)
+- (void)setAppleMenu:(NSMenu *)menu;
+@end
+
+/* Use this flag to determine whether we use SDLMain.nib or not */
+#define SDL_USE_NIB_FILE 0
+
+/* Use this flag to determine whether we use CPS (docking) or not */
+#define SDL_USE_CPS 1
+#ifdef SDL_USE_CPS
+/* Portions of CPS.h */
+typedef struct CPSProcessSerNum
+ {
+ UInt32 lo;
+ UInt32 hi;
+ } CPSProcessSerNum;
+
+extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
+extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
+extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
+
+#endif /* SDL_USE_CPS */
+
+static int gArgc;
+static char **gArgv;
+static BOOL gFinderLaunch;
+static BOOL gCalledAppMainline = FALSE;
+
+static NSString *getApplicationName(void)
+{
+ NSDictionary *dict;
+ NSString *appName = 0;
+
+ /* Determine the application name */
+ dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
+ if (dict)
+ appName = [dict objectForKey: @"CFBundleName"];
+
+ if (![appName length])
+ appName = [[NSProcessInfo processInfo] processName];
+
+ return appName;
+}
+
+#if SDL_USE_NIB_FILE
+/* A helper category for NSString */
+@interface NSString (ReplaceSubString)
+- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;
+@end
+#endif
+
+@interface SDLApplication : NSApplication
+@end
+
+@implementation SDLApplication
+/* Invoked from the Quit menu item */
+- (void)terminate:(id)sender
+{
+ /* Post a SDL_QUIT event */
+ SDL_Event event;
+ event.type = SDL_QUIT;
+ SDL_PushEvent(&event);
+}
+@end
+
+/* The main class of the application, the application's delegate */
+@implementation SDLMain
+
+/* Set the working directory to the .app's parent directory */
+- (void) setupWorkingDirectory:(BOOL)shouldChdir
+{
+ if (shouldChdir)
+ {
+ char parentdir[MAXPATHLEN];
+ CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
+ CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
+ if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) {
+ assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */
+ }
+ CFRelease(url);
+ CFRelease(url2);
+ }
+
+}
+
+#if SDL_USE_NIB_FILE
+
+/* Fix menu to contain the real app name instead of "SDL App" */
+- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName
+{
+ NSRange aRange;
+ NSEnumerator *enumerator;
+ NSMenuItem *menuItem;
+
+ aRange = [[aMenu title] rangeOfString:@"SDL App"];
+ if (aRange.length != 0)
+ [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];
+
+ enumerator = [[aMenu itemArray] objectEnumerator];
+ while ((menuItem = [enumerator nextObject]))
+ {
+ aRange = [[menuItem title] rangeOfString:@"SDL App"];
+ if (aRange.length != 0)
+ [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]];
+ if ([menuItem hasSubmenu])
+ [self fixMenu:[menuItem submenu] withAppName:appName];
+ }
+ [ aMenu sizeToFit ];
+}
+
+#else
+
+static void setApplicationMenu(void)
+{
+ /* warning: this code is very odd */
+ NSMenu *appleMenu;
+ NSMenuItem *menuItem;
+ NSString *title;
+ NSString *appName;
+
+ appName = getApplicationName();
+ appleMenu = [[NSMenu alloc] initWithTitle:@""];
+
+ /* Add menu items */
+ title = [@"About " stringByAppendingString:appName];
+ [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
+
+ [appleMenu addItem:[NSMenuItem separatorItem]];
+
+ title = [@"Hide " stringByAppendingString:appName];
+ [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
+
+ menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
+ [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
+
+ [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
+
+ [appleMenu addItem:[NSMenuItem separatorItem]];
+
+ title = [@"Quit " stringByAppendingString:appName];
+ [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
+
+
+ /* Put menu into the menubar */
+ menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
+ [menuItem setSubmenu:appleMenu];
+ [[NSApp mainMenu] addItem:menuItem];
+
+ /* Tell the application object that this is now the application menu */
+ [NSApp setAppleMenu:appleMenu];
+
+ /* Finally give up our references to the objects */
+ [appleMenu release];
+ [menuItem release];
+}
+
+/* Create a window menu */
+static void setupWindowMenu(void)
+{
+ NSMenu *windowMenu;
+ NSMenuItem *windowMenuItem;
+ NSMenuItem *menuItem;
+
+ windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+
+ /* "Minimize" item */
+ menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
+ [windowMenu addItem:menuItem];
+ [menuItem release];
+
+ /* Put menu into the menubar */
+ windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
+ [windowMenuItem setSubmenu:windowMenu];
+ [[NSApp mainMenu] addItem:windowMenuItem];
+
+ /* Tell the application object that this is now the window menu */
+ [NSApp setWindowsMenu:windowMenu];
+
+ /* Finally give up our references to the objects */
+ [windowMenu release];
+ [windowMenuItem release];
+}
+
+/* Replacement for NSApplicationMain */
+static void CustomApplicationMain (int argc, char **argv)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ SDLMain *sdlMain;
+
+ /* Ensure the application object is initialised */
+ [SDLApplication sharedApplication];
+
+#ifdef SDL_USE_CPS
+ {
+ CPSProcessSerNum PSN;
+ /* Tell the dock about us */
+ if (!CPSGetCurrentProcess(&PSN))
+ if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
+ if (!CPSSetFrontProcess(&PSN))
+ [SDLApplication sharedApplication];
+ }
+#endif /* SDL_USE_CPS */
+
+ /* Set up the menubar */
+ [NSApp setMainMenu:[[NSMenu alloc] init]];
+ setApplicationMenu();
+ setupWindowMenu();
+
+ /* Create SDLMain and make it the app delegate */
+ sdlMain = [[SDLMain alloc] init];
+ [NSApp setDelegate:sdlMain];
+
+ /* Start the main event loop */
+ [NSApp run];
+
+ [sdlMain release];
+ [pool release];
+}
+
+#endif
+
+
+/*
+ * Catch document open requests...this lets us notice files when the app
+ * was launched by double-clicking a document, or when a document was
+ * dragged/dropped on the app's icon. You need to have a
+ * CFBundleDocumentsType section in your Info.plist to get this message,
+ * apparently.
+ *
+ * Files are added to gArgv, so to the app, they'll look like command line
+ * arguments. Previously, apps launched from the finder had nothing but
+ * an argv[0].
+ *
+ * This message may be received multiple times to open several docs on launch.
+ *
+ * This message is ignored once the app's mainline has been called.
+ */
+- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
+{
+ const char *temparg;
+ size_t arglen;
+ char *arg;
+ char **newargv;
+
+ if (!gFinderLaunch) /* MacOS is passing command line args. */
+ return FALSE;
+
+ if (gCalledAppMainline) /* app has started, ignore this document. */
+ return FALSE;
+
+ temparg = [filename UTF8String];
+ arglen = SDL_strlen(temparg) + 1;
+ arg = (char *) SDL_malloc(arglen);
+ if (arg == NULL)
+ return FALSE;
+
+ newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2));
+ if (newargv == NULL)
+ {
+ SDL_free(arg);
+ return FALSE;
+ }
+ gArgv = newargv;
+
+ SDL_strlcpy(arg, temparg, arglen);
+ gArgv[gArgc++] = arg;
+ gArgv[gArgc] = NULL;
+ return TRUE;
+}
+
+
+/* Called when the internal event loop has just started running */
+- (void) applicationDidFinishLaunching: (NSNotification *) note
+{
+ int status;
+
+ /* Set the working directory to the .app's parent directory */
+ [self setupWorkingDirectory:gFinderLaunch];
+
+#if SDL_USE_NIB_FILE
+ /* Set the main menu to contain the real app name instead of "SDL App" */
+ [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()];
+#endif
+
+ /* Hand off to main application code */
+ gCalledAppMainline = TRUE;
+ status = SDL_main (gArgc, gArgv);
+
+ /* We're done, thank you for playing */
+ exit(status);
+}
+@end
+
+
+@implementation NSString (ReplaceSubString)
+
+- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
+{
+ unsigned int bufferSize;
+ unsigned int selfLen = [self length];
+ unsigned int aStringLen = [aString length];
+ unichar *buffer;
+ NSRange localRange;
+ NSString *result;
+
+ bufferSize = selfLen + aStringLen - aRange.length;
+ buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
+
+ /* Get first part into buffer */
+ localRange.location = 0;
+ localRange.length = aRange.location;
+ [self getCharacters:buffer range:localRange];
+
+ /* Get middle part into buffer */
+ localRange.location = 0;
+ localRange.length = aStringLen;
+ [aString getCharacters:(buffer+aRange.location) range:localRange];
+
+ /* Get last part into buffer */
+ localRange.location = aRange.location + aRange.length;
+ localRange.length = selfLen - localRange.location;
+ [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
+
+ /* Build output string */
+ result = [NSString stringWithCharacters:buffer length:bufferSize];
+
+ NSDeallocateMemoryPages(buffer, bufferSize);
+
+ return result;
+}
+
+@end
+
+
+
+#ifdef main
+# undef main
+#endif
+
+
+/* Main entry point to executable - should *not* be SDL_main! */
+int main (int argc, char **argv)
+{
+ /* Copy the arguments into a global variable */
+ /* This is passed if we are launched by double-clicking */
+ if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
+ gArgv = (char **) SDL_malloc(sizeof (char *) * 2);
+ gArgv[0] = argv[0];
+ gArgv[1] = NULL;
+ gArgc = 1;
+ gFinderLaunch = YES;
+ } else {
+ int i;
+ gArgc = argc;
+ gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1));
+ for (i = 0; i <= argc; i++)
+ gArgv[i] = argv[i];
+ gFinderLaunch = NO;
+ }
+
+#if SDL_USE_NIB_FILE
+ [SDLApplication poseAsClass:[NSApplication class]];
+ NSApplicationMain (argc, argv);
+#else
+ CustomApplicationMain (argc, argv);
+#endif
+ return 0;
+}
diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp
index 203a82af..aa2fb4ee 100644
--- a/src/animatedsprite.cpp
+++ b/src/animatedsprite.cpp
@@ -1,26 +1,25 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "animatedsprite.h"
-
#include "graphics.h"
#include "log.h"
diff --git a/src/animatedsprite.h b/src/animatedsprite.h
index 41857d8f..43248731 100644
--- a/src/animatedsprite.h
+++ b/src/animatedsprite.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ANIMATEDSPRITE_H
-#define _TMW_ANIMATEDSPRITE_H
+#ifndef ANIMATEDSPRITE_H
+#define ANIMATEDSPRITE_H
#include "resources/spritedef.h"
diff --git a/src/animationparticle.cpp b/src/animationparticle.cpp
index eb260157..9c1f7ccb 100644
--- a/src/animationparticle.cpp
+++ b/src/animationparticle.cpp
@@ -1,26 +1,25 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "animationparticle.h"
-
#include "graphics.h"
#include "simpleanimation.h"
diff --git a/src/animationparticle.h b/src/animationparticle.h
index eabc2742..03065eb7 100644
--- a/src/animationparticle.h
+++ b/src/animationparticle.h
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/being.cpp b/src/being.cpp
index 442c08ef..7f5a7d33 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -1,109 +1,160 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 <cassert>
-#include <cmath>
-
#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 "simpleanimation.h"
#include "sound.h"
-#include "localplayer.h"
+#include "text.h"
+#include "statuseffect.h"
+#include "gui/speechbubble.h"
+
+#include "resources/colordb.h"
+#include "resources/emotedb.h"
+#include "resources/image.h"
#include "resources/itemdb.h"
-#include "resources/resourcemanager.h"
-#include "resources/imageset.h"
#include "resources/iteminfo.h"
+#include "resources/resourcemanager.h"
#include "gui/gui.h"
#include "gui/speechbubble.h"
#include "utils/dtor.h"
-#include "utils/tostring.h"
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
#include "utils/xml.h"
+#include <cassert>
+#include <cmath>
+
namespace {
const bool debug_movement = true;
}
-#define HAIR_FILE "hair.xml"
-
-#include "utils/xml.h"
#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):
+#ifdef EATHENA_SUPPORT
+ mX(0), mY(0),
+ mWalkTime(0),
+#endif
mEmotion(0), mEmotionTime(0),
mAttackSpeed(350),
mAction(STAND),
mJob(job),
mId(id),
- mSpriteDirection(DIRECTION_DOWN), mDirection(DOWN),
+ mDirection(DOWN),
+#ifdef TMWSERV_SUPPORT
+ mSpriteDirection(DIRECTION_DOWN),
+#endif
mMap(NULL),
+ mName(""),
+ mIsGM(false),
+ mParticleEffects(config.getValue("particleeffects", 1)),
mEquippedWeapon(NULL),
+#ifdef TMWSERV_SUPPORT
mHairStyle(0),
+#else
+ mHairStyle(1),
+#endif
mHairColor(0),
mGender(GENDER_UNSPECIFIED),
mSpeechTime(0),
+ mPx(0), mPy(0),
+ mStunMode(0),
mSprites(VECTOREND_SPRITE, NULL),
mSpriteIDs(VECTOREND_SPRITE, 0),
mSpriteColors(VECTOREND_SPRITE, ""),
- mWalkSpeed(100)
+ mStatusParticleEffects(&mStunParticleEffects, false),
+ mChildParticleEffects(&mStatusParticleEffects, false),
+ mMustResetParticles(false),
+#ifdef TMWSERV_SUPPORT
+ mWalkSpeed(100),
+#else
+ mWalkSpeed(150),
+#endif
+ mUsedTargetCursor(NULL)
{
setMap(map);
- mSpeechBubble = new SpeechBubble();
+ mSpeechBubble = new SpeechBubble;
if (instances == 0)
{
- // Load the emotion set
- ResourceManager *rm = ResourceManager::getInstance();
- emotionSet = rm->getImageSet("graphics/sprites/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 = "";
+ mNameColor = 0x202020;
+ mText = 0;
}
Being::~Being()
{
+ mUsedTargetCursor = NULL;
delete_all(mSprites);
clearPath();
- for ( std::list<Particle *>::iterator i = mChildParticleEffects.begin();
- i != mChildParticleEffects.end();
- i++)
- {
- (*i)->kill();
- }
+ if (player_node && player_node->getTarget() == this)
+ player_node->setTarget(NULL);
setMap(NULL);
@@ -111,11 +162,11 @@ Being::~Being()
if (instances == 0)
{
- emotionSet->decRef();
- emotionSet = NULL;
+ delete_all(emotionSet);
}
delete mSpeechBubble;
+ delete mText;
}
void Being::setPosition(const Vector &pos)
@@ -125,6 +176,15 @@ void Being::setPosition(const Vector &pos)
mPath.clear();
}
+#ifdef EATHENA_SUPPORT
+void Being::setDestination(Uint16 destX, Uint16 destY)
+{
+ if (mMap)
+ setPath(mMap->findPath(mX, mY, destX, destY, getWalkMask()));
+}
+#endif
+
+#ifdef TMWSERV_SUPPORT
void Being::adjustCourse(int srcX, int srcY, int dstX, int dstY)
{
if (debug_movement)
@@ -289,6 +349,7 @@ void Being::setDestination(int destX, int destY)
adjustCourse((int) mPos.x, (int) mPos.y, destX, destY);
}
+#endif // TMWSERV_SUPPORT
void Being::clearPath()
{
@@ -297,14 +358,22 @@ void Being::clearPath()
void Being::setPath(const Path &path)
{
- std::cout << this << " New path: " << path << std::endl;
mPath = path;
+#ifdef TMWSERV_SUPPORT
+ std::cout << this << " New path: " << path << std::endl;
+#else
+ if (mAction != WALK && mAction != DEAD)
+ {
+ nextStep();
+ mWalkTime = tick_time;
+ }
+#endif
}
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, const std::string &color)
@@ -317,7 +386,43 @@ void Being::setSprite(int slot, int id, const std::string &color)
void Being::setSpeech(const std::string &text, Uint32 time)
{
mSpeech = text;
- mSpeechTime = 500;
+
+ // 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);
+ }
+
+ 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)
@@ -327,69 +432,71 @@ void Being::takeDamage(int amount)
// Selecting the right color
if (damage == "miss")
- {
font = hitYellowFont;
- }
else
{
- // Hit particle effect
- controlParticle(particleEngine->addEffect(
- "graphics/particles/hit.particle.xml", mPos.x, mPos.y));
-
if (getType() == MONSTER)
- {
font = hitBlueFont;
- }
else
- {
font = hitRedFont;
- }
}
// Show damage number
particleEngine->addTextSplashEffect(damage, 255, 255, 255, font,
+#ifdef TMWSERV_SUPPORT
(int) mPos.x + 16,
(int) mPos.y + 16);
+#else
+ mPx + 16, mPy + 16);
+#endif
+ effectManager->trigger(26, this);
}
+void Being::showCrit()
+{
+ effectManager->trigger(28, this);
+
+}
+
+#ifdef TMWSERV_SUPPORT
void Being::handleAttack()
+#else
+void Being::handleAttack(Being *victim, int damage)
+#endif
{
setAction(Being::ATTACK);
+#ifdef EATHENA_SUPPORT
+ mFrame = 0;
+ mWalkTime = tick_time;
+#endif
}
void Being::setMap(Map *map)
{
// Remove sprite from potential previous map
if (mMap)
- {
mMap->removeSprite(mSpriteIterator);
- }
mMap = map;
// Add sprite to potential new map
if (mMap)
- {
mSpriteIterator = mMap->addSprite(this);
- }
// Clear particle effect list because child particles became invalid
mChildParticleEffects.clear();
+ mMustResetParticles = true; // Reset status particles on next redraw
}
void Being::controlParticle(Particle *particle)
{
- if (particle)
- {
- // The effect may not die without the beings permission or we segfault
- particle->disableAutoDelete();
- mChildParticleEffects.push_back(particle);
- }
+ mChildParticleEffects.addLocally(particle);
}
void Being::setAction(Action action, int attackType)
{
SpriteAction currentAction = ACTION_INVALID;
+
switch (action)
{
case WALK:
@@ -403,15 +510,14 @@ void Being::setAction(Action action, int attackType)
{
currentAction = mEquippedWeapon->getAttackType();
}
- else {
+ else
+ {
currentAction = ACTION_ATTACK;
}
for (int i = 0; i < VECTOREND_SPRITE; i++)
{
if (mSprites[i])
- {
mSprites[i]->reset();
- }
}
break;
case HURT:
@@ -432,20 +538,18 @@ void Being::setAction(Action action, int attackType)
for (int i = 0; i < VECTOREND_SPRITE; i++)
{
if (mSprites[i])
- {
mSprites[i]->play(currentAction);
- }
}
mAction = action;
}
}
-
void Being::setDirection(Uint8 direction)
{
if (mDirection == direction)
return;
+#ifdef TMWSERV_SUPPORT
// if the direction does not change much, keep the common component
int mFaceDirection = mDirection & direction;
if (!mFaceDirection)
@@ -462,16 +566,93 @@ void Being::setDirection(Uint8 direction)
else
dir = DIRECTION_LEFT;
mSpriteDirection = dir;
+#else
+ mDirection = direction;
+ SpriteDirection dir = getSpriteDirection();
+#endif
for (int i = 0; i < VECTOREND_SPRITE; i++)
{
- if (mSprites[i] != NULL)
- mSprites[i]->setDirection(dir);
+ if (mSprites[i])
+ mSprites[i]->setDirection(dir);
+ }
+}
+
+#ifdef EATHENA_SUPPORT
+SpriteDirection Being::getSpriteDirection() const
+{
+ SpriteDirection dir;
+
+ if (mDirection & UP)
+ {
+ dir = DIRECTION_UP;
+ }
+ else if (mDirection & DOWN)
+ {
+ dir = DIRECTION_DOWN;
+ }
+ else if (mDirection & RIGHT)
+ {
+ dir = DIRECTION_RIGHT;
+ }
+ else
+ {
+ dir = DIRECTION_LEFT;
}
+
+ return dir;
}
+void Being::nextStep()
+{
+ if (mPath.empty())
+ {
+ setAction(STAND);
+ return;
+ }
+
+ Position pos = mPath.front();
+ mPath.pop_front();
+
+ int dir = 0;
+ if (pos.x > mX)
+ dir |= RIGHT;
+ else if (pos.x < mX)
+ dir |= LEFT;
+ if (pos.y > mY)
+ dir |= DOWN;
+ else if (pos.y < mY)
+ dir |= UP;
+
+ setDirection(dir);
+
+ if (!mMap->getWalk(pos.x, pos.y, getWalkMask()))
+ {
+ setAction(STAND);
+ return;
+ }
+
+ mX = pos.x;
+ mY = pos.y;
+ setAction(WALK);
+ mWalkTime += mWalkSpeed / 10;
+}
+#endif
+
void Being::logic()
{
+ // Reduce the time that speech is still displayed
+ if (mSpeechTime > 0)
+ mSpeechTime--;
+
+ // Remove text if speech boxes aren't being used
+ if (mSpeechTime == 0 && mText)
+ {
+ delete mText;
+ mText = 0;
+ }
+
+#ifdef TMWSERV_SUPPORT
const Vector dest = (mPath.empty()) ?
mDest : Vector(mPath.front().x * 32 + 16,
mPath.front().y * 32 + 16);
@@ -506,56 +687,83 @@ void Being::logic()
} else if (mAction == WALK) {
setAction(STAND);
}
+#else
+ int oldPx = mPx;
+ int oldPy = mPy;
- // Reduce the time that speech is still displayed
- if (mSpeechTime > 0)
- mSpeechTime--;
+ // Update pixel coordinates
+ mPx = mX * 32 + getXOffset();
+ mPy = mY * 32 + getYOffset();
+
+ if (mPx != oldPx || mPy != oldPy)
+ {
+ updateCoords();
+ }
+#endif
if (mEmotion != 0)
{
mEmotionTime--;
- if (mEmotionTime == 0) {
+ if (mEmotionTime == 0)
mEmotion = 0;
- }
}
// Update sprite animations
+ if (mUsedTargetCursor)
+ mUsedTargetCursor->update(tick_time * 10);
+
for (int i = 0; i < VECTOREND_SPRITE; i++)
{
- if (mSprites[i] != NULL)
- {
+ if (mSprites[i])
mSprites[i]->update(tick_time * 10);
- }
}
- // Update particle effects
- for (std::list<Particle *>::iterator i = mChildParticleEffects.begin();
- i != mChildParticleEffects.end();)
- {
- (*i)->setPosition(mPos.x, mPos.y);
- if ((*i)->isExtinct())
- {
- (*i)->kill();
- i = mChildParticleEffects.erase(i);
- }
- else {
- i++;
+ // Restart status/particle effects, if needed
+ if (mMustResetParticles) {
+ mMustResetParticles = false;
+ for (std::set<int>::iterator it = mStatusEffects.begin();
+ it != mStatusEffects.end(); it++) {
+ const StatusEffect *effect = StatusEffect::getStatusEffect(*it, true);
+ if (effect && effect->particleEffectIsPersistent())
+ updateStatusEffect(*it, true);
}
}
+
+ // Update particle effects
+#ifdef TMWSERV_SUPPORT
+ mChildParticleEffects.moveTo((float) mPx + 16.0f,
+ (float) mPy + 32.0f);
+#else
+ mChildParticleEffects.moveTo(mPos.x, mPos.y);
+#endif
}
void Being::draw(Graphics *graphics, int offsetX, int offsetY) const
{
+#ifdef TMWSERV_SUPPORT
int px = (int) mPos.x + offsetX;
int py = (int) mPos.y + offsetY;
+#else
+ int px = mPx + offsetX;
+ int py = mPy + offsetY;
+#endif
+
+ if (mUsedTargetCursor)
+ {
+ mUsedTargetCursor->draw(graphics, px, py);
+ }
for (int i = 0; i < VECTOREND_SPRITE; i++)
{
- if (mSprites[i] != NULL)
+ if (mSprites[i])
{
+#ifdef TMWSERV_SUPPORT
// TODO: Eventually, we probably should fix all sprite offsets so
// that this translation isn't necessary anymore.
mSprites[i]->draw(graphics, px - 16, py - 32);
+#else
+ mSprites[i]->draw(graphics, px, py);
+#endif
}
}
}
@@ -565,26 +773,69 @@ void Being::drawEmotion(Graphics *graphics, int offsetX, int offsetY)
if (!mEmotion)
return;
+#ifdef TMWSERV_SUPPORT
const int px = (int) mPos.x + offsetX + 3;
const int py = (int) mPos.y + offsetY - 60;
+#else
+ const int px = mPx + offsetX + 3;
+ const int py = mPy + offsetY - 60;
+#endif
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(Graphics *graphics, int offsetX, int offsetY)
+void Being::drawSpeech(int offsetX, int offsetY)
{
+#ifdef TMWSERV_SUPPORT
int px = (int) mPos.x + offsetX;
int py = (int) mPos.y + offsetY;
+#else
+ const int px = mPx + offsetX;
+ const int py = mPy + offsetY;
+#endif
+ const int speech = (int) config.getValue("speech", NAME_IN_BUBBLE);
// Draw speech above this being
- if (mSpeechTime > 0)
+ if (mSpeechTime > 0 && (speech == NAME_IN_BUBBLE ||
+ speech == NO_NAME_IN_BUBBLE))
{
- mSpeechBubble->setPosition(px - 50, py - 80 - (mSpeechBubble->getNumRows()*14) );
- mSpeechBubble->setText( mSpeech );
+ const bool showName = (speech == NAME_IN_BUBBLE);
+
+ if (mText)
+ {
+ delete mText;
+ mText = 0;
+ }
+
+ mSpeechBubble->setCaption(showName ? 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, showName);
+ mSpeechBubble->setPosition(px - (mSpeechBubble->getWidth() * 4 / 11),
+ py - 40 - (mSpeechBubble->getHeight()));
mSpeechBubble->setVisible(true);
}
+ else if (mSpeechTime > 0 && speech == TEXT_OVERHEAD)
+ {
+ 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 (speech == NO_SPEECH)
+ {
+ mSpeechBubble->setVisible(false);
+ if (mText)
+ delete mText;
+ mText = NULL;
+ }
else if (mSpeechTime == 0)
{
mSpeechBubble->setVisible(false);
@@ -596,115 +847,125 @@ Being::Type Being::getType() const
return UNKNOWN;
}
-int Being::getWidth() const
+void Being::setStatusEffectBlock(int offset, Uint16 newEffects)
{
- if (mSprites[BASE_SPRITE])
- {
- return mSprites[BASE_SPRITE]->getWidth();
- }
- else {
- return Being::DEFAULT_WIDTH;
- }
-}
+ for (int i = 0; i < STATUS_EFFECTS; i++) {
+ int index = StatusEffect::blockEffectIndexToEffectIndex(offset + i);
-int Being::getHeight() const
-{
- if (mSprites[BASE_SPRITE])
- {
- return mSprites[BASE_SPRITE]->getHeight();
- }
- else {
- return Being::DEFAULT_HEIGHT;
+ if (index != -1)
+ setStatusEffect(index, (newEffects & (1 << i)) > 0);
}
}
+void Being::handleStatusEffect(StatusEffect *effect, int effectId)
+{
+ if (!effect)
+ return;
+ // 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();
-static int hairStylesNr;
-static int hairColorsNr;
-static std::vector<std::string> hairColors;
-
-static void
-initializeHair(void);
+ if (effectId >= 0)
+ mStatusParticleEffects.setLocally(effectId, particle);
+ else {
+ mStunParticleEffects.clearLocally();
+ if (particle)
+ mStunParticleEffects.addLocally(particle);
+ }
+}
-int
-Being::getHairStylesNr(void)
+void Being::updateStunMode(int oldMode, int newMode)
{
- initializeHair();
- return hairStylesNr;
+ handleStatusEffect(StatusEffect::getStatusEffect(oldMode, false), -1);
+ handleStatusEffect(StatusEffect::getStatusEffect(newMode, true), -1);
}
-int
-Being::getHairColorsNr(void)
+void Being::updateStatusEffect(int index, bool newStatus)
{
- initializeHair();
- return hairColorsNr;
+ handleStatusEffect(StatusEffect::getStatusEffect(index, newStatus), index);
}
-std::string
-Being::getHairColor(int index)
+void Being::setStatusEffect(int index, bool active)
{
- initializeHair();
- if (index < 0 || index >= hairColorsNr)
- return "#000000";
+ const bool wasActive = mStatusEffects.find(index) != mStatusEffects.end();
- return hairColors[index];
+ if (active != wasActive) {
+ updateStatusEffect(index, active);
+ if (active)
+ mStatusEffects.insert(index);
+ else
+ mStatusEffects.erase(index);
+ }
}
-static bool hairInitialized = false;
-
-static void
-initializeHair(void)
+#ifdef EATHENA_SUPPORT
+int Being::getOffset(char pos, char neg) const
{
- if (hairInitialized)
- return;
-
- // Hairstyles are encoded as negative numbers. Count how far negative we can go.
- int hairstylesCtr = -1;
- while (ItemDB::get(hairstylesCtr).getSprite(GENDER_MALE) != "error.xml")
- --hairstylesCtr;
-
- hairStylesNr = -hairstylesCtr; // done.
- if (hairStylesNr == 0)
- hairStylesNr = 1; // No hair style -> no hair
+ // Check whether we're walking in the requested direction
+ if (mAction != WALK || !(mDirection & (pos | neg)))
+ {
+ return 0;
+ }
- hairColorsNr = 0;
+ int offset = (get_elapsed_time(mWalkTime) * 32) / mWalkSpeed;
- XML::Document doc(HAIR_FILE);
- xmlNodePtr root = doc.rootNode();
+ // We calculate the offset _from_ the _target_ location
+ offset -= 32;
+ if (offset > 0)
+ {
+ offset = 0;
+ }
- if (!root || !xmlStrEqual(root->name, BAD_CAST "colors"))
+ // Going into negative direction? Invert the offset.
+ if (mDirection & pos)
{
- logger->log("Error loading being hair configuration file");
- } else {
- for_each_xml_child_node(node, root)
- {
- if (xmlStrEqual(node->name, BAD_CAST "color"))
- {
- int index = atoi(XML::getProperty(node, "id", "-1").c_str());
- std::string value = XML::getProperty(node, "value", "");
+ offset = -offset;
+ }
- if (index >= 0 && value != "") {
- if (index >= hairColorsNr) {
- hairColorsNr = index + 1;
- hairColors.resize(hairColorsNr, "#000000");
- }
- hairColors[index] = value;
- }
- }
- }
- } // done initializing
+ return offset;
+}
+#endif
- if (hairColorsNr == 0) { // No colours -> black only
- hairColorsNr = 1;
- hairColors.resize(hairColorsNr, "#000000");
+int Being::getWidth() const
+{
+ if (mSprites[BASE_SPRITE])
+ {
+ const int width = mSprites[BASE_SPRITE]->getWidth() > DEFAULT_WIDTH ?
+ mSprites[BASE_SPRITE]->getWidth() :
+ DEFAULT_WIDTH;
+ return width;
+ }
+ else
+ {
+ return DEFAULT_WIDTH;
}
-
- hairInitialized = 1;
}
+int Being::getHeight() const
+{
+ if (mSprites[BASE_SPRITE])
+ {
+ const int height = mSprites[BASE_SPRITE]->getHeight() > DEFAULT_HEIGHT ?
+ mSprites[BASE_SPRITE]->getHeight() :
+ DEFAULT_HEIGHT;
+ return height;
+ }
+ else
+ {
+ return DEFAULT_HEIGHT;
+ }
+}
+void Being::setTargetAnimation(SimpleAnimation* animation)
+{
+ mUsedTargetCursor = animation;
+ mUsedTargetCursor->reset();
+}
struct EffectDescription {
std::string mGFXEffect;
@@ -715,8 +976,7 @@ static EffectDescription *default_effect = NULL;
static std::map<int, EffectDescription *> effects;
static bool effects_initialized = false;
-static EffectDescription *
-getEffectDescription(xmlNodePtr node, int *id)
+static EffectDescription *getEffectDescription(xmlNodePtr node, int *id)
{
EffectDescription *ed = new EffectDescription;
@@ -727,8 +987,7 @@ getEffectDescription(xmlNodePtr node, int *id)
return ed;
}
-static EffectDescription *
-getEffectDescription(int effectId)
+static EffectDescription *getEffectDescription(int effectId)
{
if (!effects_initialized)
{
@@ -774,8 +1033,7 @@ getEffectDescription(int effectId)
return ed;
}
-void
-Being::internalTriggerEffect(int effectId, bool sfx, bool gfx)
+void Being::internalTriggerEffect(int effectId, bool sfx, bool gfx)
{
logger->log("Special effect #%d on %s", effectId,
getId() == player_node->getId() ? "self" : "other");
@@ -787,14 +1045,96 @@ 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);
}
}
+
+
+
+
+static int hairStylesNr;
+static int hairColorsNr;
+static std::vector<std::string> hairColors;
+
+static void initializeHair();
+
+int Being::getHairStylesNr()
+{
+ initializeHair();
+ return hairStylesNr;
+}
+
+int Being::getHairColorsNr()
+{
+ initializeHair();
+ return hairColorsNr;
+}
+
+std::string Being::getHairColor(int index)
+{
+ initializeHair();
+ if (index < 0 || index >= hairColorsNr)
+ return "#000000";
+
+ return hairColors[index];
+}
+
+static bool hairInitialized = false;
+
+static void initializeHair()
+{
+ if (hairInitialized)
+ return;
+
+ // Hairstyles are encoded as negative numbers. Count how far negative we
+ // can go.
+ int hairstylesCtr = -1;
+ while (ItemDB::get(hairstylesCtr).getSprite(GENDER_MALE) != "error.xml")
+ --hairstylesCtr;
+
+ hairStylesNr = -hairstylesCtr; // done.
+ if (hairStylesNr == 0)
+ hairStylesNr = 1; // No hair style -> no hair
+
+ hairColorsNr = 0;
+
+ XML::Document doc(HAIR_FILE);
+ xmlNodePtr root = doc.rootNode();
+
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "colors"))
+ {
+ logger->log("Error loading being hair configuration file");
+ } else {
+ for_each_xml_child_node(node, root)
+ {
+ if (xmlStrEqual(node->name, BAD_CAST "color"))
+ {
+ int index = atoi(XML::getProperty(node, "id", "-1").c_str());
+ std::string value = XML::getProperty(node, "value", "");
+
+ if (index >= 0 && !value.empty()) {
+ if (index >= hairColorsNr) {
+ hairColorsNr = index + 1;
+ hairColors.resize(hairColorsNr, "#000000");
+ }
+ hairColors[index] = value;
+ }
+ }
+ }
+ } // done initializing
+
+ if (hairColorsNr == 0) { // No colors -> black only
+ hairColorsNr = 1;
+ hairColors.resize(hairColorsNr, "#000000");
+ }
+
+ hairInitialized = 1;
+}
diff --git a/src/being.h b/src/being.h
index cd317859..a704b3df 100644
--- a/src/being.h
+++ b/src/being.h
@@ -1,49 +1,68 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_BEING_H
-#define _TMW_BEING_H
+#ifndef BEING_H
+#define BEING_H
+
+#include <guichan/color.hpp>
-#include <list>
-#include <string>
#include <SDL_types.h>
+
+#include <set>
+#include <string>
#include <vector>
+#include "map.h"
+#include "particlecontainer.h"
#include "position.h"
#include "sprite.h"
-#include "map.h"
-#include "animatedsprite.h"
#include "vector.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 SimpleAnimation;
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
@@ -52,7 +71,8 @@ enum Gender {
class Being : public Sprite
{
public:
- enum Type {
+ enum Type
+ {
UNKNOWN,
PLAYER,
NPC,
@@ -64,7 +84,8 @@ class Being : public Sprite
* WARNING: Has to be in sync with the same enum in the Being class
* of the server!
*/
- enum Action {
+ enum Action
+ {
STAND,
WALK,
ATTACK,
@@ -73,33 +94,59 @@ class Being : public Sprite
HURT
};
- enum Sprite {
+ enum Sprite
+ {
BASE_SPRITE = 0,
SHOE_SPRITE,
BOTTOMCLOTHES_SPRITE,
TOPCLOTHES_SPRITE,
+#ifdef EATHENA_SUPPORT
+ MISC1_SPRITE,
+ MISC2_SPRITE,
+#endif
HAIR_SPRITE,
HAT_SPRITE,
+#ifdef EATHENA_SUPPORT
+ CAPE_SPRITE,
+ GLOVES_SPRITE,
+#endif
WEAPON_SPRITE,
+#ifdef EATHENA_SUPPORT
+ SHIELD_SPRITE,
+#endif
VECTOREND_SPRITE
};
- enum TargetCursorSize {
+ enum TargetCursorSize
+ {
TC_SMALL = 0,
TC_MEDIUM,
TC_LARGE,
NUM_TC
};
+ enum Speech
+ {
+ NO_SPEECH = 0,
+ TEXT_OVERHEAD,
+ NO_NAME_IN_BUBBLE,
+ NAME_IN_BUBBLE,
+ NUM_SPEECH
+ };
/**
* Directions, to be used as bitmask values
*/
enum { DOWN = 1, LEFT = 2, UP = 4, RIGHT = 8 };
- std::string mName; /**< Name of character */
+#ifdef EATHENA_SUPPORT
+ Uint16 mX, mY; /**< Tile coordinates */
+ Uint16 mFrame;
+ Uint16 mWalkTime;
+#endif
Uint8 mEmotion; /**< Currently showing emotion */
Uint8 mEmotionTime; /**< Time until emotion disappears */
+
Uint16 mAttackSpeed; /**< Attack speed */
Action mAction; /**< Action the being is performing */
Uint16 mJob; /**< Job (player job, npc, monster, creature ) */
@@ -122,6 +169,9 @@ class Being : public Sprite
/**
* Sets a new destination for this being to walk to.
*/
+#ifdef EATHENA_SUPPORT
+ virtual void setDestination(Uint16 destX, Uint16 destY);
+#else
void setDestination(int x, int y);
/**
@@ -138,6 +188,7 @@ class Being : public Sprite
* Adjusts course to expected start and end points.
*/
void adjustCourse(int srcX, int srcY, int destX, int destY);
+#endif
/**
* Puts a "speech balloon" above this being for the specified amount
@@ -146,7 +197,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.
@@ -156,9 +207,21 @@ 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.
+ * @param damage The amount of damage dealt (0 means miss).
*/
+#ifdef TMWSERV_SUPPORT
virtual void handleAttack();
+#else
+ virtual void handleAttack(Being *victim, int damage);
+#endif
/**
* Returns the name of the being.
@@ -171,12 +234,8 @@ class Being : public Sprite
*
* @param name The name that should appear.
*/
- void setName(const std::string &name) { mName = name; }
-
- /**
- * Sets the gender for this being.
- */
- virtual void setGender(Gender gender) { mGender = gender; }
+ virtual void setName(const std::string &name)
+ { mName = name; }
/**
* Gets the hair color for this being.
@@ -191,12 +250,12 @@ 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.
- *
- * NOTE: This method was necessary for convenience in the 0.0 client.
- * It should be removed here since the server can provide the hair ID
- * and coloring the same way it does for other equipment pieces. Then
- * Being::setSprite can be used instead.
*/
virtual void setHairStyle(int style, int color);
@@ -207,6 +266,31 @@ class Being : public Sprite
const std::string &color = "");
/**
+ * Sets the gender of this being.
+ */
+ virtual void setGender(Gender gender) { mGender = gender; }
+
+ /**
+ * Gets the gender of this being.
+ */
+ Gender getGender() const { return mGender; }
+
+#ifdef EATHENA_SUPPORT
+ /**
+ * Makes this being take the next step of his path.
+ */
+ virtual void nextStep();
+#endif
+
+ /**
+ * 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();
@@ -214,7 +298,7 @@ class Being : public Sprite
/**
* Draws the speech text above the being.
*/
- void drawSpeech(Graphics* graphics, int offsetX, int offsetY);
+ void drawSpeech(int offsetX, int offsetY);
/**
* Draws the emotion picture above the being.
@@ -222,11 +306,6 @@ class Being : public Sprite
void drawEmotion(Graphics *graphics, int offsetX, int offsetY);
/**
- * Draws the name text below the being.
- */
- virtual void drawName(Graphics *, int, int) {};
-
- /**
* Returns the type of the being.
*/
virtual Type getType() const;
@@ -245,12 +324,12 @@ class Being : public Sprite
/**
* Gets the being id.
*/
- Uint16 getId() const { return mId; }
+ Uint32 getId() const { return mId; }
/**
* Sets the sprite id.
*/
- void setId(Uint16 id) { mId = id; }
+ void setId(Uint32 id) { mId = id; }
/**
* Sets the map the being is on
@@ -268,16 +347,32 @@ class Being : public Sprite
bool isAlive() { return mAction != DEAD; }
/**
- * Returns the direction the being is facing.
+ * Returns the current direction.
*/
- SpriteDirection getSpriteDirection() const
- { return SpriteDirection(mSpriteDirection); }
+ Uint8 getDirection() const { return mDirection; }
/**
* Sets the current direction.
*/
void setDirection(Uint8 direction);
+#ifdef EATHENA_SUPPORT
+ /**
+ * Gets the current action.
+ */
+ int getWalkTime() { return mWalkTime; }
+#endif
+
+ /**
+ * Returns the direction the being is facing.
+ */
+#ifdef TMWSERV_SUPPORT
+ SpriteDirection getSpriteDirection() const
+ { return SpriteDirection(mSpriteDirection); }
+#else
+ SpriteDirection getSpriteDirection() const;
+#endif
+
/**
* Draws this being to the given graphics context.
*
@@ -288,14 +383,36 @@ class Being : public Sprite
/**
* Returns the pixel X coordinate.
*/
+#ifdef TMWSERV_SUPPORT
int getPixelX() const { return (int) mPos.x; }
+#else
+ int getPixelX() const { return mPx; }
+#endif
/**
* Returns the pixel Y coordinate.
*
* @see Sprite::getPixelY()
*/
+#ifdef TMWSERV_SUPPORT
int getPixelY() const { return (int) mPos.y; }
+#else
+ int getPixelY() const { return mPy; }
+#endif
+
+#ifdef EATHENA_SUPPORT
+ /**
+ * Get the current X pixel offset.
+ */
+ int getXOffset() const
+ { return getOffset(LEFT, RIGHT); }
+
+ /**
+ * Get the current Y pixel offset.
+ */
+ int getYOffset() const
+ { return getOffset(UP, DOWN); }
+#endif
/**
* Sets the position of this being. When the being was walking, it also
@@ -318,6 +435,7 @@ class Being : public Sprite
*/
const Vector &getPosition() const { return mPos; }
+
/**
* Returns the horizontal size of the current base sprite of the being.
*/
@@ -352,21 +470,68 @@ class Being : public Sprite
const Path &getPath() const { return mPath; }
/**
+ * Sets the target animation for this being.
+ */
+ void setTargetAnimation(SimpleAnimation* animation);
+
+ /**
+ * Untargets the being
+ */
+ void untarget() { mUsedTargetCursor = NULL; }
+
+ AnimatedSprite* getEmote(int index) { return emotionSet[index]; }
+
+ void setEmote(Uint8 emotion, Uint8 emote_time)
+ {
+ mEmotion = emotion;
+ mEmotionTime = emote_time;
+ }
+
+ /**
+ * Sets the being's stun mode. If zero, the being is `normal',
+ * otherwise it is `stunned' in some fashion.
+ */
+ void setStunMode(int stunMode)
+ {
+ if (mStunMode != stunMode)
+ updateStunMode(mStunMode, stunMode);
+ mStunMode = stunMode;
+ };
+
+ void setStatusEffect(int index, bool active);
+
+ /**
+ * A status effect block is a 16 bit mask of status effects.
+ * We assign each such flag a block ID of offset + bitnr.
+ *
+ * These are NOT the same as the status effect indices.
+ */
+ void setStatusEffectBlock(int offset, Uint16 flags);
+
+ /**
* Triggers a visual effect, such as `level up'
*
* Only draws the visual effect, does not play sound effects
*
* \param effectId ID of the effect to trigger
*/
- virtual void
- triggerEffect(int effectId) { internalTriggerEffect(effectId, false, true); }
+ virtual void triggerEffect(int effectId)
+ {
+ internalTriggerEffect(effectId, false, true);
+ }
+
+ // Target cursor being used by the being
+ Image *mTargetCursor;
- static int getHairColorsNr(void);
+ static int getHairColorsNr();
- static int getHairStylesNr(void);
+ static int getHairStylesNr();
static std::string getHairColor(int index);
+ virtual AnimatedSprite* getSprite(int index) const
+ { return mSprites[index]; }
+
protected:
/**
* Sets the new path for this being.
@@ -374,6 +539,11 @@ class Being : public Sprite
void setPath(const Path &path);
/**
+ * Let the sub-classes react to a replacement
+ */
+ virtual void updateCoords() {}
+
+ /**
* Gets the way the object blocks pathfinding for other objects
*/
virtual Map::BlockType getBlockType() const
@@ -386,34 +556,80 @@ class Being : public Sprite
* \param sfx Whether to trigger sound effects
* \param gfx Whether to trigger graphical effects
*/
- void
- internalTriggerEffect(int effectId, bool sfx, bool gfx);
+ void internalTriggerEffect(int effectId, bool sfx, bool gfx);
- Uint16 mId; /**< Unique being id */
+ /**
+ * Notify self that the stun mode has been updated. Invoked by
+ * setStunMode if something changed.
+ */
+ virtual void updateStunMode(int oldMode, int newMode);
+
+ /**
+ * Notify self that a status effect has flipped.
+ * The new flag is passed.
+ */
+ virtual void updateStatusEffect(int index, bool newStatus);
+
+ /**
+ * Handle an update to a status or stun effect
+ *
+ * \param The StatusEffect to effect
+ * \param effectId -1 for stun, otherwise the effect index
+ */
+ virtual void handleStatusEffect(StatusEffect *effect, int effectId);
+
+ Uint32 mId; /**< Unique sprite id */
+ Uint8 mDirection; /**< Facing direction */
+#ifdef TMWSERV_SUPPORT
Uint8 mSpriteDirection; /**< Facing direction */
- Uint8 mDirection; /**< Walking direction */
+#endif
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;
std::string mSpeech;
+ Text *mText;
int mHairStyle;
int mHairColor;
Gender mGender;
Uint32 mSpeechTime;
+ Sint32 mPx, mPy; /**< Pixel coordinates */
+ 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;
- std::list<Particle *> mChildParticleEffects;
+ ParticleList mStunParticleEffects;
+ ParticleVector mStatusParticleEffects;
+ ParticleList mChildParticleEffects;
private:
+#ifdef EATHENA_SUPPORT
+ /**
+ * Calculates the offset in the given directions.
+ * If walking in direction 'neg' the value is negated.
+ */
+ int getOffset(char pos, char neg) const;
+#endif
+ /** Reset particle status effects on next redraw? */
+ bool mMustResetParticles;
+
+#ifdef TMWSERV_SUPPORT
static const int DEFAULT_WIDTH = 32;
static const int DEFAULT_HEIGHT = 32;
+#endif
// Speech Bubble components
SpeechBubble *mSpeechBubble;
@@ -423,8 +639,11 @@ class Being : public Sprite
Vector mPos;
Vector mDest;
- static int instances; /**< Number of Being instances */
- static ImageSet *emotionSet; /**< Emoticons used by beings */
+ // Target cursor being used
+ SimpleAnimation* mUsedTargetCursor;
+
+ 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 7f3d8845..e9d598c7 100644
--- a/src/beingmanager.cpp
+++ b/src/beingmanager.cpp
@@ -1,26 +1,24 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 "beingmanager.h"
#include "localplayer.h"
@@ -28,18 +26,31 @@
#include "npc.h"
#include "player.h"
+#ifdef EATHENA_SUPPORT
+#include "net/messageout.h"
+#include "net/ea/protocol.h"
+#else
#include "net/protocol.h"
+#endif
+
#include "utils/dtor.h"
+#include <cassert>
+
class FindBeingFunctor
{
public:
bool operator() (Being *being)
{
Uint16 other_y = y + ((being->getType() == Being::NPC) ? 1 : 0);
+#ifdef TMWSERV_SUPPORT
const Vector &pos = being->getPosition();
return ((int) pos.x / 32 == x &&
((int) pos.y / 32 == y || (int) pos.y / 32 == other_y) &&
+#else
+ return (being->mX == x &&
+ (being->mY == y || being->mY == other_y) &&
+#endif
being->mAction != Being::DEAD &&
(type == Being::UNKNOWN || being->getType() == type));
}
@@ -48,6 +59,13 @@ class FindBeingFunctor
Being::Type type;
} beingFinder;
+#ifdef EATHENA_SUPPORT
+BeingManager::BeingManager(Network *network):
+ mNetwork(network)
+{
+}
+#endif
+
void BeingManager::setMap(Map *map)
{
mMap = map;
@@ -61,10 +79,15 @@ void BeingManager::setPlayer(LocalPlayer *player)
mBeings.push_back(player);
}
+#ifdef TMWSERV_SUPPORT
Being* BeingManager::createBeing(int id, int type, int subtype)
+#else
+Being* BeingManager::createBeing(Uint32 id, Uint16 job)
+#endif
{
Being *being;
+#ifdef TMWSERV_SUPPORT
switch (type)
{
case OBJECT_PLAYER:
@@ -79,6 +102,24 @@ Being* BeingManager::createBeing(int id, int type, int subtype)
default:
assert(false);
}
+#else
+ if (job < 10)
+ being = new Player(id, job, mMap);
+ else if (job >= 50 && job < 1002)
+ being = new NPC(id, job, mMap, mNetwork);
+ else if (job >= 1002 && job < 1500)
+ being = new Monster(id, job, mMap);
+ else
+ being = new Being(id, job, mMap);
+
+ // Player or NPC
+ if (job < 1002)
+ {
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0094);
+ outMsg.writeInt32(id);//readLong(2));
+ }
+#endif
mBeings.push_back(being);
return being;
@@ -87,12 +128,14 @@ Being* BeingManager::createBeing(int id, int type, int subtype)
void BeingManager::destroyBeing(Being *being)
{
mBeings.remove(being);
+#ifdef TMWSERV_SUPPORT
if(being == player_node->getTarget())
player_node->setTarget(NULL);
+#endif
delete being;
}
-Being* BeingManager::findBeing(Uint16 id)
+Being* BeingManager::findBeing(Uint32 id)
{
for (BeingIterator i = mBeings.begin(); i != mBeings.end(); i++)
{
@@ -123,9 +166,12 @@ Being* BeingManager::findBeingByPixel(Uint16 x, Uint16 y)
for (; itr != itr_end; ++itr)
{
Being *being = (*itr);
+
int xtol = being->getWidth() / 2;
int uptol = being->getHeight();
- if ((being != player_node) &&
+
+ if ((being->mAction != Being::DEAD) &&
+ (being != player_node) &&
(being->getPixelX() - xtol <= x) &&
(being->getPixelX() + xtol >= x) &&
(being->getPixelY() - uptol <= y) &&
@@ -138,6 +184,19 @@ Being* BeingManager::findBeingByPixel(Uint16 x, Uint16 y)
return NULL;
}
+Being* BeingManager::findBeingByName(std::string name, Being::Type type)
+{
+ for (BeingIterator i = mBeings.begin(); i != mBeings.end(); i++)
+ {
+ Being *being = (*i);
+ if (being->getName() == name
+ && (type == Being::UNKNOWN
+ || type == being->getType()))
+ return being;
+ }
+ return NULL;
+}
+
Beings& BeingManager::getAll()
{
return mBeings;
@@ -152,13 +211,15 @@ void BeingManager::logic()
being->logic();
- /*
+#ifdef EATHENA_SUPPORT
if (being->mAction == Being::DEAD && being->mFrame >= 20)
{
delete being;
i = mBeings.erase(i);
}
- else*/ {
+ else
+#endif
+ {
i++;
}
}
@@ -186,6 +247,7 @@ Being* BeingManager::findNearestLivingBeing(Uint16 x, Uint16 y, int maxdist,
Being *closestBeing = NULL;
int dist = 0;
+#ifdef TMWSERV_SUPPORT
//Why do we do this:
//For some reason x,y passed to this function is always
//in map coords, while down below its in pixels
@@ -195,12 +257,20 @@ Being* BeingManager::findNearestLivingBeing(Uint16 x, Uint16 y, int maxdist,
x = x * 32;
y = y * 32;
maxdist = maxdist * 32;
+#endif
- 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);
+#ifdef TMWSERV_SUPPORT
const Vector &pos = being->getPosition();
int d = abs(((int) pos.x) - x) + abs(((int) pos.y) - y);
+#else
+ int d = abs(being->mX - x) + abs(being->mY - y);
+#endif
if ((being->getType() == type || type == Being::UNKNOWN)
&& (d < dist || closestBeing == NULL) // it is closer
@@ -218,6 +288,38 @@ Being* BeingManager::findNearestLivingBeing(Uint16 x, Uint16 y, int maxdist,
Being* BeingManager::findNearestLivingBeing(Being *aroundBeing, int maxdist,
Being::Type type)
{
- const Vector &aroundBeingPos = aroundBeing->getPosition();
- return findNearestLivingBeing((int) aroundBeingPos.x,(int) aroundBeingPos.y,maxdist,type);
+ Being *closestBeing = NULL;
+ int dist = 0;
+#ifdef TMWSERV_SUPPORT
+ const Vector &apos = aroundBeing->getPosition();
+ int x = apos.x;
+ int y = apos.y;
+ maxdist = maxdist * 32;
+#else
+ int x = aroundBeing->mX;
+ int y = aroundBeing->mY;
+#endif
+
+ for (BeingIterator i = mBeings.begin(); i != mBeings.end(); i++)
+ {
+ Being *being = (*i);
+#ifdef TMWSERV_SUPPORT
+ const Vector &pos = being->getPosition();
+ int d = abs(((int) pos.x) - x) + abs(((int) pos.y) - y);
+#else
+ int d = abs(being->mX - x) + abs(being->mY - y);
+#endif
+
+ if ((being->getType() == type || type == Being::UNKNOWN)
+ && (d < dist || closestBeing == NULL) // it is closer
+ && being->mAction != Being::DEAD // no dead beings
+ && being != aroundBeing
+ )
+ {
+ dist = d;
+ closestBeing = being;
+ }
+ }
+
+ return (maxdist >= dist) ? closestBeing : NULL;
}
diff --git a/src/beingmanager.h b/src/beingmanager.h
index d3fb9888..726a73ec 100644
--- a/src/beingmanager.h
+++ b/src/beingmanager.h
@@ -1,31 +1,34 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_BEINGMANAGER_H
-#define _TMW_BEINGMANAGER_H
+#ifndef BEINGMANAGER_H
+#define BEINGMANAGER_H
#include "being.h"
class LocalPlayer;
class Map;
+#ifdef EATHENA_SUPPORT
+class Network;
+#endif
typedef std::list<Being*> Beings;
typedef Beings::iterator BeingIterator;
@@ -33,6 +36,10 @@ typedef Beings::iterator BeingIterator;
class BeingManager
{
public:
+#ifdef EATHENA_SUPPORT
+ BeingManager(Network *network);
+#endif
+
/**
* Sets the map on which beings are created
*/
@@ -46,7 +53,11 @@ class BeingManager
/**
* Create a being and add it to the list of beings.
*/
+#ifdef TMWSERV_SUPPORT
Being *createBeing(int id, int type, int subtype);
+#else
+ Being *createBeing(Uint32 id, Uint16 job);
+#endif
/**
* Remove a Being.
@@ -56,7 +67,7 @@ class BeingManager
/**
* Returns a specific id Being.
*/
- Being* findBeing(Uint16 id);
+ Being* findBeing(Uint32 id);
/**
* Returns a being at specific coordinates.
@@ -77,6 +88,11 @@ class BeingManager
Being::Type type = Being::UNKNOWN);
/**
+ * Finds a being by name and (optionally) by type.
+ */
+ Being* findBeingByName(std::string name, Being::Type type = Being::UNKNOWN);
+
+ /**
* Returns a being nearest to another being.
*
* \param maxdist maximal distance. If minimal distance is larger,
@@ -103,6 +119,9 @@ class BeingManager
protected:
Beings mBeings;
Map *mMap;
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+#endif
};
extern BeingManager *beingManager;
diff --git a/src/configlistener.h b/src/configlistener.h
index b740720f..ec7d6a2c 100644
--- a/src/configlistener.h
+++ b/src/configlistener.h
@@ -1,29 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_CONFIGLISTENER_H
-#define _TMW_CONFIGLISTENER_H
-
-#include <iosfwd>
+#ifndef CONFIGLISTENER_H
+#define CONFIGLISTENER_H
+#include <string>
/**
* The listener interface for receiving notifications about changes to
diff --git a/src/configuration.cpp b/src/configuration.cpp
index e801083f..3c3ae1d5 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -1,35 +1,131 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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"
+#include "utils/stringutils.h"
#include "utils/xml.h"
+void ConfigurationObject::setValue(const std::string &key, std::string value)
+{
+ mOptions[key] = value;
+}
+
+void ConfigurationObject::setValue(const std::string &key, float value)
+{
+ setValue(key, toString((value == (int)value) ? (int)value : value));
+}
+
+void Configuration::setValue(const std::string &key, float value)
+{
+ setValue(key, toString((value == (int)value) ? (int)value : value));
+}
+
+void Configuration::setValue(const std::string &key, std::string value)
+{
+ ConfigurationObject::setValue(key, value);
+
+ // Notify listeners
+ ListenerMapIterator list = mListenerMap.find(key);
+ if (list != mListenerMap.end()) {
+ Listeners listeners = list->second;
+ for (ListenerIterator i = listeners.begin(); i != listeners.end(); i++)
+ {
+ (*i)->optionChanged(key);
+ }
+ }
+}
+
+std::string ConfigurationObject::getValue(const std::string &key,
+ std::string deflt)
+{
+ OptionIterator iter = mOptions.find(key);
+ return ((iter != mOptions.end()) ? iter->second : deflt);
+}
+
+float ConfigurationObject::getValue(const std::string &key, float deflt)
+{
+ OptionIterator iter = mOptions.find(key);
+ return (iter != mOptions.end()) ? atof(iter->second.c_str()) : deflt;
+}
+
+void ConfigurationObject::deleteList(const std::string &name)
+{
+ for (ConfigurationList::const_iterator
+ it = mContainerOptions[name].begin(); it != mContainerOptions[name].end(); it++)
+ delete *it;
+
+ mContainerOptions[name].clear();
+}
+
+void ConfigurationObject::clear()
+{
+ for (std::map<std::string, ConfigurationList>::const_iterator
+ it = mContainerOptions.begin(); it != mContainerOptions.end(); it++)
+ deleteList(it->first);
+ mOptions.clear();
+}
+
+ConfigurationObject::~ConfigurationObject()
+{
+ clear();
+}
+
+void ConfigurationObject::initFromXML(xmlNodePtr parent_node)
+{
+ clear();
+
+ for_each_xml_child_node(node, parent_node)
+ {
+ if (xmlStrEqual(node->name, BAD_CAST "list")) {
+ // list option handling
+
+ std::string name = XML::getProperty(node, "name", std::string());
+
+ for_each_xml_child_node(subnode, node)
+ {
+ if (xmlStrEqual(subnode->name, BAD_CAST name.c_str())
+ && subnode->type == XML_ELEMENT_NODE) {
+ ConfigurationObject *cobj = new ConfigurationObject;
+
+ cobj->initFromXML(subnode); // recurse
+
+ mContainerOptions[name].push_back(cobj);
+ }
+ }
+
+ } else if (xmlStrEqual(node->name, BAD_CAST "option")) {
+ // single option handling
+
+ std::string name = XML::getProperty(node, "name", std::string());
+ std::string value = XML::getProperty(node, "value", std::string());
+
+ if (!name.empty() && !value.empty())
+ mOptions[name] = value;
+ } // otherwise ignore
+ }
+}
+
void Configuration::init(const std::string &filename)
{
mConfigPath = filename;
@@ -55,21 +151,41 @@ void Configuration::init(const std::string &filename)
return;
}
- for_each_xml_child_node(node, rootNode)
+ initFromXML(rootNode);
+
+ xmlFreeDoc(doc);
+}
+
+void ConfigurationObject::writeToXML(xmlTextWriterPtr writer)
+{
+ for (OptionIterator i = mOptions.begin(); i != mOptions.end(); i++)
{
- if (!xmlStrEqual(node->name, BAD_CAST "option"))
- continue;
+ xmlTextWriterStartElement(writer, BAD_CAST "option");
+ xmlTextWriterWriteAttribute(writer,
+ BAD_CAST "name", BAD_CAST i->first.c_str());
+ xmlTextWriterWriteAttribute(writer,
+ BAD_CAST "value", BAD_CAST i->second.c_str());
+ xmlTextWriterEndElement(writer);
+ }
- std::string name = XML::getProperty(node, "name", std::string());
- std::string value = XML::getProperty(node, "value", std::string());
+ for (std::map<std::string, ConfigurationList>::const_iterator
+ it = mContainerOptions.begin(); it != mContainerOptions.end(); it++) {
+ const char *name = it->first.c_str();
- if (!name.empty() && !value.empty())
- {
- mOptions[name] = value;
+ xmlTextWriterStartElement(writer, BAD_CAST "list");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST name);
+
+ // recurse on all elements
+ for (ConfigurationList::const_iterator
+ elt_it = it->second.begin(); elt_it != it->second.end(); elt_it++) {
+
+ xmlTextWriterStartElement(writer, BAD_CAST name);
+ (*elt_it)->writeToXML(writer);
+ xmlTextWriterEndElement(writer);
}
- }
- xmlFreeDoc(doc);
+ xmlTextWriterEndElement(writer);
+ }
}
void Configuration::write()
@@ -98,52 +214,12 @@ void Configuration::write()
xmlTextWriterStartDocument(writer, NULL, NULL, NULL);
xmlTextWriterStartElement(writer, BAD_CAST "configuration");
- for (OptionIterator i = mOptions.begin(); i != mOptions.end(); i++)
- {
- xmlTextWriterStartElement(writer, BAD_CAST "option");
- xmlTextWriterWriteAttribute(writer,
- BAD_CAST "name", BAD_CAST i->first.c_str());
- xmlTextWriterWriteAttribute(writer,
- BAD_CAST "value", BAD_CAST i->second.c_str());
- xmlTextWriterEndElement(writer);
- }
+ writeToXML(writer);
xmlTextWriterEndDocument(writer);
xmlFreeTextWriter(writer);
}
-void Configuration::setValue(const std::string &key, std::string value)
-{
- mOptions[key] = value;
-
- // Notify listeners
- ListenerMapIterator list = mListenerMap.find(key);
- if (list != mListenerMap.end()) {
- Listeners listeners = list->second;
- for (ListenerIterator i = listeners.begin(); i != listeners.end(); i++)
- {
- (*i)->optionChanged(key);
- }
- }
-}
-
-void Configuration::setValue(const std::string &key, float value)
-{
- setValue(key, toString((value == (int)value) ? (int)value : value));
-}
-
-std::string Configuration::getValue(const std::string &key, std::string deflt)
-{
- OptionIterator iter = mOptions.find(key);
- return ((iter != mOptions.end()) ? iter->second : deflt);
-}
-
-float Configuration::getValue(const std::string &key, float deflt)
-{
- OptionIterator iter = mOptions.find(key);
- return (iter != mOptions.end()) ? atof(iter->second.c_str()) : deflt;
-}
-
void Configuration::addListener(
const std::string &key, ConfigListener *listener)
{
diff --git a/src/configuration.h b/src/configuration.h
index 72ae866c..0134f29a 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -1,52 +1,78 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_CONFIGURATION_H
-#define _TMW_CONFIGURATION_H
+#ifndef CONFIGURATION_H
+#define CONFIGURATION_H
-#include <map>
+#include <libxml/xmlwriter.h>
+
+#include <cassert>
#include <list>
+#include <map>
#include <string>
class ConfigListener;
+class ConfigurationObject;
/**
- * Configuration handler for reading (and writing).
+ * Configuration list manager interface; responsible for serlialising/deserialising
+ * configuration choices in containers.
*
- * \ingroup CORE
+ * \param T Type of the container elements to serialise
+ * \param CONT Type of the container we (de)serialise
*/
-class Configuration
+template <class T, class CONT>
+class ConfigurationListManager
{
public:
/**
- * Reads config file and parse all options into memory.
+ * Writes a value into a configuration object
*
- * \param filename path to config file
+ * \param value The value to write out
+ * \param obj The configuation object to write to
+ * \return obj, or otherwise NULL to indicate that this option should be skipped
*/
- void init(const std::string &filename);
+ virtual ConfigurationObject *writeConfigItem(T value, ConfigurationObject *obj) = 0;
/**
- * Writes the current settings back to the config file.
+ * Reads a value from a configuration object
+ *
+ * \param obj The configuration object to read from
+ * \param container The container to insert the object to
*/
- void write();
+ virtual CONT readConfigItem(ConfigurationObject *obj, CONT container) = 0;
+};
+
+/**
+ * Configuration object, mapping values to names and possibly containing
+ * lists of further configuration objects
+ *
+ * \ingroup CORE
+ */
+class ConfigurationObject
+{
+ friend class Configuration;
+
+ public:
+ virtual ~ConfigurationObject();
/**
* Sets an option using a string value.
@@ -54,7 +80,7 @@ class Configuration
* \param key Option identifier.
* \param value Value.
*/
- void setValue(const std::string &key, std::string value);
+ virtual void setValue(const std::string &key, std::string value);
/**
* Sets an option using a numeric value.
@@ -62,7 +88,7 @@ class Configuration
* \param key Option identifier.
* \param value Value.
*/
- void setValue(const std::string &key, float value);
+ virtual void setValue(const std::string &key, float value);
/**
* Gets a value as string.
@@ -81,6 +107,102 @@ class Configuration
float getValue(const std::string &key, float deflt);
/**
+ * Re-sets all data in the configuration
+ */
+ virtual void clear();
+
+ /**
+ * Serialises a container into a list of configuration options
+ *
+ * \param IT Iterator type over CONT
+ * \param T Elements that IT iterates over
+ * \param CONT The associated container type
+ *
+ * \param name Name of the list the elements should be stored under
+ * \param begin Iterator start
+ * \param end Iterator end
+ * \param manager An object capable of serialising T items
+ */
+ template <class IT, class T, class CONT>
+ void setList(const std::string &name, IT begin, IT end, ConfigurationListManager<T, CONT> *manager)
+ {
+ ConfigurationObject *nextobj = new ConfigurationObject;
+ deleteList(name);
+ ConfigurationList *list = &(mContainerOptions[name]);
+
+ for (IT it = begin; it != end; it++) {
+ ConfigurationObject *wrobj = manager->writeConfigItem(*it, nextobj);
+ if (wrobj) { // wrote something
+ assert (wrobj == nextobj);
+ nextobj = new ConfigurationObject;
+ list->push_back(wrobj);
+ } else
+ nextobj->clear(); // you never know...
+ }
+
+ delete nextobj;
+ }
+
+ /**
+ * Serialises a container into a list of configuration options
+ *
+ * \param IT Iterator type over CONT
+ * \param T Elements that IT iterates over
+ * \param CONT The associated container type
+ *
+ * \param name Name of the list the elements should be read from under
+ * \param empty Initial (empty) container to write to
+ * \param manager An object capable of deserialising items into CONT
+ */
+ template<class T, class CONT>
+ CONT getList(const std::string &name, CONT empty, ConfigurationListManager<T, CONT> *manager)
+ {
+ ConfigurationList *list = &(mContainerOptions[name]);
+ CONT container = empty;
+
+ for (ConfigurationList::const_iterator it = list->begin(); it != list->end(); it++)
+ container = manager->readConfigItem(*it, container);
+
+ return container;
+ }
+
+ protected:
+ virtual void initFromXML(xmlNodePtr node);
+ virtual void writeToXML(xmlTextWriterPtr writer);
+
+ void deleteList(const std::string &name);
+
+ typedef std::map<std::string, std::string> Options;
+ typedef Options::iterator OptionIterator;
+ Options mOptions;
+
+ typedef std::list<ConfigurationObject *> ConfigurationList;
+ std::map<std::string, ConfigurationList> mContainerOptions;
+};
+
+/**
+ * Configuration handler for reading (and writing).
+ *
+ * \ingroup CORE
+ */
+class Configuration : public ConfigurationObject
+{
+ public:
+ virtual ~Configuration() {}
+
+ /**
+ * Reads config file and parse all options into memory.
+ *
+ * \param filename path to config file
+ */
+ void init(const std::string &filename);
+
+ /**
+ * Writes the current settings back to the config file.
+ */
+ void write();
+
+ /**
* Adds a listener to the listen list of the specified config option.
*/
void addListener(const std::string &key, ConfigListener *listener);
@@ -91,11 +213,10 @@ class Configuration
*/
void removeListener(const std::string &key, ConfigListener *listener);
- private:
- typedef std::map<std::string, std::string> Options;
- typedef Options::iterator OptionIterator;
- Options mOptions;
+ virtual void setValue(const std::string &key, std::string value);
+ virtual void setValue(const std::string &key, float value);
+ private:
typedef std::list<ConfigListener*> Listeners;
typedef Listeners::iterator ListenerIterator;
typedef std::map<std::string, Listeners> ListenerMap;
diff --git a/src/effectmanager.cpp b/src/effectmanager.cpp
index 52f1eb31..d9234f66 100644
--- a/src/effectmanager.cpp
+++ b/src/effectmanager.cpp
@@ -1,33 +1,33 @@
/*
- * The Mana World
- * Copyright 2004 The Mana World Development Team
+ * 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.
*
- * The Mana World is free software; you can redistribute it and/or modify
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 "particle.h"
#include "log.h"
+#include "particle.h"
#include "sound.h"
#include "utils/xml.h"
-
EffectManager::EffectManager()
{
XML::Document doc("effects.xml");
@@ -60,22 +60,42 @@ 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)
+ for (std::list<EffectDescription>::iterator i = mEffects.begin(); i != mEffects.end(); ++i)
{
if ((*i).id == id)
{
rValue = true;
- if ((*i).GFX != "")
+ if (!(*i).GFX.empty())
particleEngine->addEffect((*i).GFX, x, y);
- if ((*i).SFX != "")
+ if (!(*i).SFX.empty())
sound.playSfx((*i).SFX);
break;
}
}
return rValue;
}
-
diff --git a/src/effectmanager.h b/src/effectmanager.h
index 4b349471..01c5a6b8 100644
--- a/src/effectmanager.h
+++ b/src/effectmanager.h
@@ -1,34 +1,38 @@
/*
- * The Mana World
- * Copyright 2004 The Mana World Development Team
+ * 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.
*
- * The Mana World is free software; you can redistribute it and/or modify
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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
+#ifndef EFFECT_MANAGER_H
+#define EFFECT_MANAGER_H
-#include <string>
#include <list>
+#include <string>
+
+class Being;
class EffectManager
{
public:
- struct EffectDescription {
+ struct EffectDescription
+ {
int id;
std::string GFX;
std::string SFX;
@@ -38,16 +42,21 @@ class EffectManager
~EffectManager();
/**
- * Triggers a effect with the id, at x,y
- * returns true if ID exists
+ * Triggers a effect with the id, at
+ * the specified being.
*/
- bool trigger(int id, int x = 0, int y = 0);
+ 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
+#endif // EFFECT_MANAGER_H
diff --git a/src/emoteshortcut.cpp b/src/emoteshortcut.cpp
new file mode 100644
index 00000000..46e13782
--- /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/stringutils.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 f191280e..872ecd57 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -1,35 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 "main.h"
#include "localplayer.h"
#include "log.h"
#include "map.h"
@@ -40,19 +33,27 @@
#include "gui/minimap.h"
#include "gui/viewport.h"
+#ifdef EATHENA_SUPPORT
+#include "net/messageout.h"
+#include "net/ea/protocol.h"
+#endif
+
#include "resources/mapreader.h"
#include "resources/monsterdb.h"
#include "resources/resourcemanager.h"
-#include "utils/dtor.h"
-#include "utils/tostring.h"
-
-extern Minimap *minimap;
+#include "utils/stringutils.h"
char itemCurrenyQ[10] = "0";
+#ifdef TMWSERV_SUPPORT
Engine::Engine():
mCurrentMap(NULL)
+#else
+Engine::Engine(Network *network):
+ mCurrentMap(NULL),
+ mNetwork(network)
+#endif
{
}
@@ -63,32 +64,60 @@ Engine::~Engine()
void Engine::changeMap(const std::string &mapPath)
{
- // Clean up floor items
+ // Clean up floor items, beings and particles
floorItemManager->clear();
-
beingManager->clear();
particleEngine->clear();
+ // Unset the map of the player so that its particles are cleared before
+ // being deleted in the next step
+ if (player_node)
+ player_node->setMap(0);
+
+ particleEngine->clear();
+
// Store full map path in global var
+#ifdef TMWSERV_SUPPORT
map_path = "maps/" + mapPath + ".tmx";
+#else
+ map_path = "maps/" + mapPath.substr(0, mapPath.rfind(".")) + ".tmx";
+#endif
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"));
+
+ // 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);
}
if (newMap->hasProperty("name"))
{
@@ -107,24 +136,32 @@ 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;
+
+#ifdef EATHENA_SUPPORT
+ // Send "map loaded"
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_MAP_LOADED);
+#endif
}
void Engine::logic()
{
beingManager->logic();
particleEngine->update();
+ if (mCurrentMap)
+ mCurrentMap->update();
gui->logic();
}
diff --git a/src/engine.h b/src/engine.h
index f676a271..60b1f6c8 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -1,31 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _ENGINE_H
#define _ENGINE_H
-#include <iosfwd>
#include <string>
class Map;
+#ifdef EATHENA_SUPPORT
+class Network;
+#endif
/**
* Game engine. Actually hardly does anything anymore except keeping track of
@@ -37,7 +39,11 @@ class Engine
/**
* Constructor.
*/
+#ifdef EATHENA_SUPPORT
+ Engine(Network *network);
+#else
Engine();
+#endif
/**
* Destructor.
@@ -51,7 +57,6 @@ class Engine
const std::string &getCurrentMapName() { return mMapName; }
-
/**
* Sets the currently active map.
*/
@@ -64,6 +69,9 @@ class Engine
private:
Map *mCurrentMap;
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+#endif
std::string mMapName;
};
diff --git a/src/equipment.cpp b/src/equipment.cpp
index aa56b791..63743263 100644
--- a/src/equipment.cpp
+++ b/src/equipment.cpp
@@ -1,34 +1,47 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <algorithm>
-
#include "equipment.h"
#include "item.h"
+#ifdef EATHENA_SUPPORT
+#include "inventory.h"
+#include "localplayer.h"
+#endif
+
+#include <algorithm>
Equipment::Equipment()
+#ifdef EATHENA_SUPPORT
+ : mArrows(0)
+#endif
{
+#ifdef TMWSERV_SUPPORT
std::fill_n(mEquipment, EQUIPMENT_SIZE, (Item*) 0);
+#else
+ std::fill_n(mEquipment, EQUIPMENT_SIZE, 0);
+#endif
}
+#ifdef TMWSERV_SUPPORT
+
Equipment::~Equipment()
{
clear();
@@ -50,3 +63,15 @@ void Equipment::setEquipment(int index, int id)
delete mEquipment[index];
mEquipment[index] = (id > 0) ? new Item(id) : 0;
}
+
+#else
+
+void Equipment::setEquipment(int index, int inventoryIndex)
+{
+ mEquipment[index] = inventoryIndex;
+ Item* item = player_node->getInventory()->getItem(inventoryIndex);
+ if (item)
+ item->setEquipped(true);
+}
+
+#endif
diff --git a/src/equipment.h b/src/equipment.h
index 736074dd..7605175a 100644
--- a/src/equipment.h
+++ b/src/equipment.h
@@ -1,28 +1,32 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_EQUIPMENT_H_
-#define _TMW_EQUIPMENT_H_
+#ifndef EQUIPMENT_H
+#define EQUIPMENT_H
+#ifdef TMWSERV_SUPPORT
#define EQUIPMENT_SIZE 11
+#else
+#define EQUIPMENT_SIZE 10
+#endif
class Item;
@@ -34,29 +38,63 @@ class Equipment
*/
Equipment();
+#ifdef TMWSERV_SUPPORT
/**
* Destructor.
*/
~Equipment();
-
- /**
- * Clears equipment.
- */
- void clear();
+#endif
/**
* Get equipment at the given slot.
*/
+#ifdef TMWSERV_SUPPORT
Item* getEquipment(int index)
+#else
+ int getEquipment(int index) const
+#endif
{ return mEquipment[index]; }
+#ifdef TMWSERV_SUPPORT
+ /**
+ * Clears equipment.
+ */
+ void clear();
+#endif
+
/**
* Set equipment at the given slot.
*/
+#ifdef TMWSERV_SUPPORT
void setEquipment(int index, int id);
+#else
+ void setEquipment(int index, int inventoryIndex);
+#endif
+
+#ifdef EATHENA_SUPPORT
+ /**
+ * Remove equipment from the given slot.
+ */
+ void removeEquipment(int index) { if (index >= 0 && index < EQUIPMENT_SIZE) mEquipment[index] = 0; }
+
+ /**
+ * Returns the item used in the arrow slot.
+ */
+ int getArrows() const { return mArrows; }
+
+ /**
+ * Set the item used in the arrow slot.
+ */
+ void setArrows(int arrows) { mArrows = arrows; }
+#endif
private:
+#ifdef TMWSERV_SUPPORT
Item* mEquipment[EQUIPMENT_SIZE];
+#else
+ int mEquipment[EQUIPMENT_SIZE];
+ int mArrows;
+#endif
};
#endif
diff --git a/src/floor_item.cpp b/src/floor_item.cpp
index 7ad3c0c0..fbe606b4 100644
--- a/src/floor_item.cpp
+++ b/src/floor_item.cpp
@@ -1,28 +1,31 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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 b747310b..444c756a 100644
--- a/src/floor_item.h
+++ b/src/floor_item.h
@@ -1,32 +1,37 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_FLOORITEM_H_
-#define _TMW_FLOORITEM_H_
+#ifndef FLOORITEM_H
+#define FLOORITEM_H
+
+#include <list>
-#include "graphics.h"
-#include "item.h"
-#include "map.h"
#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 68c84b5b..65556abb 100644
--- a/src/flooritemmanager.cpp
+++ b/src/flooritemmanager.cpp
@@ -1,27 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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/flooritemmanager.h b/src/flooritemmanager.h
index 3dbaf988..3f96b587 100644
--- a/src/flooritemmanager.h
+++ b/src/flooritemmanager.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_FLOORITEMMANAGER_H
-#define _TMW_FLOORITEMMANAGER_H
+#ifndef FLOORITEMMANAGER_H
+#define FLOORITEMMANAGER_H
#include <list>
diff --git a/src/game.cpp b/src/game.cpp
index 942c517c..cf1aa220 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -1,26 +1,24 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "game.h"
-
#include <fstream>
#include <physfs.h>
#include <sstream>
@@ -29,11 +27,16 @@
#include <guichan/exception.hpp>
#include "beingmanager.h"
+#ifdef TMWSERV_SUPPORT
#include "channelmanager.h"
#include "commandhandler.h"
+#endif
#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"
@@ -42,30 +45,29 @@
#include "log.h"
#include "npc.h"
#include "particle.h"
-#include "effectmanager.h"
+#include "player_relations.h"
-#include "gui/buddywindow.h"
#include "gui/buy.h"
#include "gui/buysell.h"
#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/guildwindow.h"
#include "gui/help.h"
#include "gui/inventorywindow.h"
-#include "gui/itemshortcutwindow.h"
-#include "gui/magic.h"
+#include "gui/shortcutwindow.h"
+#include "gui/itemshortcutcontainer.h"
#include "gui/menuwindow.h"
#include "gui/minimap.h"
#include "gui/ministatus.h"
+#include "gui/npcintegerdialog.h"
#include "gui/npclistdialog.h"
-#include "gui/npcpostdialog.h"
+#include "gui/npcstringdialog.h"
#include "gui/npc_text.h"
#include "gui/ok_dialog.h"
-#include "gui/partywindow.h"
-#include "gui/quitdialog.h"
#include "gui/sdlinput.h"
#include "gui/sell.h"
#include "gui/setup.h"
@@ -73,23 +75,42 @@
#include "gui/status.h"
#include "gui/trade.h"
#include "gui/viewport.h"
+#ifdef TMWSERV_SUPPORT
+#include "gui/buddywindow.h"
+#include "gui/guildwindow.h"
+#include "gui/magic.h"
+#include "gui/npcpostdialog.h"
+#include "gui/partywindow.h"
+#include "gui/quitdialog.h"
+#endif
-#include "net/beinghandler.h"
-#include "net/buysellhandler.h"
#include "net/chathandler.h"
-#include "net/guildhandler.h"
-#include "net/inventoryhandler.h"
#include "net/itemhandler.h"
-#include "net/network.h"
#include "net/npchandler.h"
-#include "net/partyhandler.h"
#include "net/playerhandler.h"
#include "net/tradehandler.h"
+#ifdef TMWSERV_SUPPORT
+#include "net/network.h"
+#include "net/beinghandler.h"
+#include "net/buysellhandler.h"
#include "net/effecthandler.h"
+#include "net/guildhandler.h"
+#include "net/inventoryhandler.h"
+#include "net/partyhandler.h"
+#else
+#include "net/ea/network.h"
+#include "net/ea/beinghandler.h"
+#include "net/ea/buysellhandler.h"
+#include "net/ea/equipmenthandler.h"
+#include "net/ea/inventoryhandler.h"
+#include "net/ea/protocol.h"
+#include "net/ea/skillhandler.h"
+#include "net/messageout.h"
+#endif
#include "resources/imagewriter.h"
-extern Graphics *graphics;
+#include "utils/gettext.h"
class Map;
@@ -98,12 +119,17 @@ std::string map_path;
bool done = false;
volatile int tick_time;
volatile int fps = 0, frame = 0;
+
Engine *engine = NULL;
Joystick *joystick = NULL;
extern Window *weightNotice;
extern Window *deathNotice;
+#ifdef TMWSERV_SUPPORT
QuitDialog *quitDialog = NULL;
+#else
+ConfirmDialog *exitConfirm = NULL;
+#endif
OkDialog *disconnectedDialog = NULL;
ChatWindow *chatWindow;
@@ -114,34 +140,41 @@ BuyDialog *buyDialog;
SellDialog *sellDialog;
BuySellDialog *buySellDialog;
InventoryWindow *inventoryWindow;
+EmoteWindow *emoteWindow;
+NpcIntegerDialog *npcIntegerDialog;
NpcListDialog *npcListDialog;
NpcTextDialog *npcTextDialog;
-NpcPostDialog *npcPostDialog;
+NpcStringDialog *npcStringDialog;
SkillDialog *skillDialog;
+#ifdef TMWSERV_SUPPORT
+BuddyWindow *buddyWindow;
+GuildWindow *guildWindow;
MagicDialog *magicDialog;
+NpcPostDialog *npcPostDialog;
+PartyWindow *partyWindow;
+#endif
Setup* setupWindow;
Minimap *minimap;
EquipmentWindow *equipmentWindow;
TradeWindow *tradeWindow;
-BuddyWindow *buddyWindow;
-GuildWindow *guildWindow;
HelpWindow *helpWindow;
DebugWindow *debugWindow;
-ItemShortcutWindow *itemShortcutWindow;
-PartyWindow *partyWindow;
+ShortcutWindow *itemShortcutWindow;
+ShortcutWindow *emoteShortcutWindow;
BeingManager *beingManager = NULL;
FloorItemManager *floorItemManager = NULL;
+#ifdef TMWSERV_SUPPORT
ChannelManager *channelManager = NULL;
CommandHandler *commandHandler = NULL;
+#endif
+Particle* particleEngine = NULL;
EffectManager *effectManager = NULL;
-Particle *particleEngine = NULL;
-
const int MAX_TIME = 10000;
/**
- * Listener used for exitting handling.
+ * Listener used for exiting handling.
*/
namespace {
struct ExitListener : public gcn::ActionListener
@@ -151,6 +184,9 @@ namespace {
if (event.getId() == "yes" || event.getId() == "ok") {
done = true;
}
+#ifdef EATHENA_SUPPORT
+ exitConfirm = NULL;
+#endif
disconnectedDialog = NULL;
}
} exitListener;
@@ -173,15 +209,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;
}
}
@@ -189,49 +228,67 @@ int get_elapsed_time(int start_time)
/**
* Create all the various globally accessible gui windows
*/
+#ifdef TMWSERV_SUPPORT
void createGuiWindows()
+#else
+void createGuiWindows(Network *network)
+#endif
{
// Create dialogs
+#ifdef TMWSERV_SUPPORT
chatWindow = new ChatWindow;
- menuWindow = new MenuWindow();
- statusWindow = new StatusWindow(player_node);
- miniStatusWindow = new MiniStatusWindow();
buyDialog = new BuyDialog;
sellDialog = new SellDialog;
- buySellDialog = new BuySellDialog();
- inventoryWindow = new InventoryWindow();
- npcTextDialog = new NpcTextDialog();
- npcListDialog = new NpcListDialog();
+ tradeWindow = new TradeWindow;
npcPostDialog = new NpcPostDialog();
- skillDialog = new SkillDialog();
magicDialog = new MagicDialog();
- setupWindow = new Setup();
- minimap = new Minimap();
equipmentWindow = new EquipmentWindow(player_node->mEquipment.get());
- tradeWindow = new TradeWindow;
buddyWindow = new BuddyWindow();
guildWindow = new GuildWindow();
- helpWindow = new HelpWindow();
- debugWindow = new DebugWindow();
- itemShortcutWindow = new ItemShortcutWindow();
partyWindow = new PartyWindow();
-
- // Initialize window positions
- //buddyWindow->setPosition(10, minimap->getHeight() + 30);
+#else
+ chatWindow = new ChatWindow(network);
+ buyDialog = new BuyDialog(network);
+ sellDialog = new SellDialog(network);
+ tradeWindow = new TradeWindow(network);
+ equipmentWindow = new EquipmentWindow;
+#endif
+ menuWindow = new MenuWindow;
+ statusWindow = new StatusWindow(player_node);
+ miniStatusWindow = new MiniStatusWindow;
+ buySellDialog = new BuySellDialog;
+ inventoryWindow = new InventoryWindow;
+ emoteWindow = new EmoteWindow;
+ npcTextDialog = new NpcTextDialog;
+ npcIntegerDialog = new NpcIntegerDialog;
+ npcListDialog = new NpcListDialog;
+ npcStringDialog = new NpcStringDialog;
+ skillDialog = new SkillDialog;
+ setupWindow = new Setup;
+ minimap = new Minimap;
+ helpWindow = new HelpWindow;
+ debugWindow = new DebugWindow;
+ 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(
+ minimap->getWindowName() + "Visible", true));
tradeWindow->setVisible(false);
menuWindow->setVisible((bool) config.getValue(
menuWindow->getWindowName() + "Visible", true));
itemShortcutWindow->setVisible((bool) config.getValue(
itemShortcutWindow->getWindowName() + "Visible", true));
+ emoteShortcutWindow->setVisible((bool) config.getValue(
+ emoteShortcutWindow->getWindowName() + "Visible", true));
+ minimap->setVisible((bool) config.getValue(
+ minimap->getWindowName() + "Visible", true));
if (config.getValue("logToChat", 0))
{
@@ -244,6 +301,7 @@ void createGuiWindows()
*/
void destroyGuiWindows()
{
+ logger->setChatWindow(NULL);
delete chatWindow;
delete statusWindow;
delete miniStatusWindow;
@@ -252,47 +310,71 @@ void destroyGuiWindows()
delete sellDialog;
delete buySellDialog;
delete inventoryWindow;
+ delete emoteWindow;
+ delete npcIntegerDialog;
delete npcListDialog;
delete npcTextDialog;
+ delete npcStringDialog;
+#ifdef TMWSERV_SUPPORT
delete npcPostDialog;
- delete skillDialog;
delete magicDialog;
+ delete buddyWindow;
+ delete guildWindow;
+ delete partyWindow;
+#endif
+ delete skillDialog;
delete setupWindow;
delete minimap;
delete equipmentWindow;
delete tradeWindow;
- delete buddyWindow;
- delete guildWindow;
delete helpWindow;
delete debugWindow;
delete itemShortcutWindow;
- delete partyWindow;
+ delete emoteShortcutWindow;
}
+#ifdef TMWSERV_SUPPORT
Game::Game():
mBeingHandler(new BeingHandler()),
- mBuySellHandler(new BuySellHandler()),
- mChatHandler(new ChatHandler()),
mGuildHandler(new GuildHandler()),
- mInventoryHandler(new InventoryHandler()),
- mItemHandler(new ItemHandler()),
- mNpcHandler(new NPCHandler()),
mPartyHandler(new PartyHandler()),
- mPlayerHandler(new PlayerHandler()),
- mTradeHandler(new TradeHandler()),
mEffectHandler(new EffectHandler()),
+#else
+Game::Game(Network *network):
+ mNetwork(network),
+ mBeingHandler(new BeingHandler(config.getValue("EnableSync", 0) == 1)),
+ mEquipmentHandler(new EquipmentHandler),
+ mSkillHandler(new SkillHandler),
+#endif
+ mBuySellHandler(new BuySellHandler),
+ mChatHandler(new ChatHandler),
+ mInventoryHandler(new InventoryHandler),
+ mItemHandler(new ItemHandler),
+ mNpcHandler(new NPCHandler),
+ mPlayerHandler(new PlayerHandler),
+ mTradeHandler(new TradeHandler),
mLogicCounterId(0), mSecondsCounterId(0)
{
done = false;
+#ifdef TMWSERV_SUPPORT
createGuiWindows();
engine = new Engine;
beingManager = new BeingManager;
- floorItemManager = new FloorItemManager();
+#else
+ createGuiWindows(network);
+ engine = new Engine(network);
+
+ beingManager = new BeingManager(network);
+#endif
+
+ floorItemManager = new FloorItemManager;
+#ifdef TMWSERV_SUPPORT
channelManager = new ChannelManager();
commandHandler = new CommandHandler();
- effectManager = new EffectManager();
+#endif
+ effectManager = new EffectManager;
particleEngine = new Particle(NULL);
particleEngine->setupEngine();
@@ -308,6 +390,9 @@ Game::Game():
// Initialize beings
beingManager->setPlayer(player_node);
+#ifdef EATHENA_SUPPORT
+ player_node->setNetwork(network);
+#endif
Joystick::init();
// TODO: The user should be able to choose which one to use
@@ -315,6 +400,7 @@ Game::Game():
if (Joystick::getNumberOfJoysticks() > 0)
joystick = new Joystick(0);
+#ifdef TMWSERV_SUPPORT
Net::registerHandler(mBeingHandler.get());
Net::registerHandler(mBuySellHandler.get());
Net::registerHandler(mChatHandler.get());
@@ -326,19 +412,50 @@ Game::Game():
Net::registerHandler(mPlayerHandler.get());
Net::registerHandler(mTradeHandler.get());
Net::registerHandler(mEffectHandler.get());
+#else
+ network->registerHandler(mBeingHandler.get());
+ network->registerHandler(mBuySellHandler.get());
+ network->registerHandler(mChatHandler.get());
+ network->registerHandler(mEquipmentHandler.get());
+ network->registerHandler(mInventoryHandler.get());
+ network->registerHandler(mItemHandler.get());
+ network->registerHandler(mNpcHandler.get());
+ network->registerHandler(mPlayerHandler.get());
+ network->registerHandler(mSkillHandler.get());
+ network->registerHandler(mTradeHandler.get());
+
+ /*
+ * 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
+ *
+ * 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);
+ msg.writeInt32(tick_time);
+
+ engine->changeMap(map_path);
+#endif
}
Game::~Game()
{
+#ifdef TMWSERV_SUPPORT
Net::clearHandlers();
+#endif
delete player_node;
destroyGuiWindows();
delete beingManager;
delete floorItemManager;
+#ifdef TMWSERV_SUPPORT
delete channelManager;
delete commandHandler;
+#endif
delete joystick;
delete particleEngine;
delete engine;
@@ -387,12 +504,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.");
}
@@ -438,7 +555,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();
@@ -461,20 +578,25 @@ void Game::logic()
}
// Handle network stuff
+#ifdef TMWSERV_SUPPORT
Net::flush();
-
// TODO: Fix notification when the connection is lost
- if (false /*!mNetwork->isConnected() */)
+#else
+ mNetwork->flush();
+ mNetwork->dispatchMessages();
+
+ if (!mNetwork->isConnected())
{
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();
}
}
+#endif
}
}
@@ -495,7 +617,7 @@ 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();
@@ -503,6 +625,7 @@ void Game::handleInput()
return;
}
+#ifdef TMWSERV_SUPPORT
// send straight to gui for certain windows
if (npcPostDialog->isVisible())
{
@@ -517,61 +640,118 @@ void Game::handleInput()
}
return;
}
+#endif
- switch (event.key.keysym.sym)
+ // Mode switch to emotes
+ if (keyboard.isKeyActive(keyboard.KEY_EMOTE))
{
- case SDLK_F1:
- // In-game Help
- if (helpWindow->isVisible())
- {
- helpWindow->setVisible(false);
- }
- else
- {
- helpWindow->loadHelp("index");
- helpWindow->requestMoveToTop();
- }
+ // Emotions
+ int emotion = keyboard.getKeyEmoteOffset(event.key.keysym.sym);
+ if (emotion)
+ {
+ emoteShortcut->useEmote(emotion);
used = true;
- break;
-
- case SDLK_RETURN:
- // Input chat window
- if (chatWindow->isInputFocused() ||
- deathNotice != NULL ||
- weightNotice != NULL)
- {
- break;
- }
+ return;
+ }
+ }
+ if (keyboard.isKeyActive(keyboard.KEY_TOGGLE_CHAT) ||
+ keyboard.isKeyActive(keyboard.KEY_OK))
+ {
+ // Input chat window
+ if (!(chatWindow->isInputFocused() ||
+ deathNotice ||
+ weightNotice))
+ {
+#ifdef TMWSERV_SUPPORT
// Don not focus chat input when quit dialog is active
- if(quitDialog != NULL && quitDialog->isVisible())
- break;
-
+ if (quitDialog != NULL && quitDialog->isVisible())
+ continue;
+#else
+ // Quit by pressing Enter if the exit confirm is there
+ if (exitConfirm &&
+ keyboard.isKeyActive(keyboard.KEY_TOGGLE_CHAT))
+ done = true;
+#endif
// Close the Browser if opened
- if (helpWindow->isVisible())
- {
+ else if (helpWindow->isVisible() &&
+ keyboard.isKeyActive(keyboard.KEY_OK))
helpWindow->setVisible(false);
- }
// Close the config window, cancelling changes if opened
- else if (setupWindow->isVisible())
- {
+ else if (setupWindow->isVisible() &&
+ keyboard.isKeyActive(keyboard.KEY_OK))
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 (guildWindow->isVisible())
{
// TODO: Check if a dialog is open and close it if so
}
*/
- // Else, open the chat edit box
- else
+ else if (!(keyboard.getKeyValue(
+ KeyboardConfig::KEY_TOGGLE_CHAT) ==
+ keyboard.getKeyValue(
+ KeyboardConfig::KEY_OK) &&
+ (helpWindow->isVisible() ||
+ setupWindow->isVisible() ||
+ npcStringDialog->isVisible() ||
+ npcTextDialog->isVisible() ||
+ npcListDialog->isVisible() ||
+ npcIntegerDialog->isVisible())))
{
chatWindow->requestChatFocus();
used = true;
}
+ }
+ }
+
+ const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
+ switch (tKey)
+ {
+ case KeyboardConfig::KEY_SCROLL_CHAT_UP:
+ if (chatWindow->isVisible())
+ {
+ chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL);
+ used = true;
+ }
+ break;
+ case KeyboardConfig::KEY_SCROLL_CHAT_DOWN:
+ if (chatWindow->isVisible())
+ {
+ chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL);
+ used = true;
+ return;
+ }
break;
- // Quitting confirmation dialog
- case SDLK_ESCAPE:
+ case KeyboardConfig::KEY_WINDOW_HELP:
+ // In-game Help
+ if (helpWindow->isVisible())
+ helpWindow->setVisible(false);
+ else
+ {
+ helpWindow->loadHelp("index");
+ helpWindow->requestMoveToTop();
+ }
+ used = true;
+ break;
+ // Quitting confirmation dialog
+ case KeyboardConfig::KEY_QUIT:
+#ifdef TMWSERV_SUPPORT
if (!quitDialog)
{
quitDialog = new QuitDialog(&done, &quitDialog);
@@ -581,37 +761,58 @@ void Game::handleInput()
{
quitDialog->action(gcn::ActionEvent(NULL, "cancel"));
}
+#else
+ if (!exitConfirm)
+ {
+ exitConfirm = new ConfirmDialog(_("Quit"),
+ _("Are you sure you "
+ "want to quit?"));
+ exitConfirm->addActionListener(&exitListener);
+ exitConfirm->requestMoveToTop();
+ }
+ else
+ {
+ exitConfirm->action(gcn::ActionEvent(NULL, _("no")));
+ }
+#endif
break;
-
default:
break;
}
-
if (keyboard.isEnabled() && !chatWindow->isInputFocused()
- && !guildWindow->isWindowFocused())
+ && !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:
{
+#ifdef TMWSERV_SUPPORT
const Vector &pos = player_node->getPosition();
Uint16 x = (int) pos.x / 32;
Uint16 y = (int) pos.y / 32;
+#else
+ Uint16 x = player_node->mX;
+ Uint16 y = player_node->mY;
+#endif
FloorItem *item =
floorItemManager->findByCoordinates(x, y);
@@ -630,8 +831,8 @@ void Game::handleInput()
default: break;
}
- item =
- floorItemManager->findByCoordinates(x, y);
+ item = floorItemManager->findByCoordinates(
+ x, y);
}
if (item)
@@ -640,35 +841,29 @@ void Game::handleInput()
used = true;
}
break;
-
- case KeyboardConfig::KEY_ATTACK:
- player_node->attack();
- used = true;
- break;
-
case KeyboardConfig::KEY_SIT:
// Player sit action
player_node->toggleSit();
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);
- magicDialog->setVisible(false);
setupWindow->setVisible(false);
equipmentWindow->setVisible(false);
helpWindow->setVisible(false);
debugWindow->setVisible(false);
+#ifdef TMWSERV_SUPPORT
guildWindow->setVisible(false);
buddyWindow->setVisible(false);
+#endif
}
break;
-
case KeyboardConfig::KEY_WINDOW_STATUS:
requestedWindow = statusWindow;
break;
@@ -682,6 +877,7 @@ void Game::handleInput()
requestedWindow = skillDialog;
break;
case KeyboardConfig::KEY_WINDOW_MINIMAP:
+ minimap->toggle();
requestedWindow = minimap;
break;
case KeyboardConfig::KEY_WINDOW_CHAT:
@@ -696,83 +892,55 @@ void Game::handleInput()
case KeyboardConfig::KEY_WINDOW_DEBUG:
requestedWindow = debugWindow;
break;
- }
- }
-
- if (requestedWindow)
- {
- requestedWindow->setVisible(!requestedWindow->isVisible());
- if (requestedWindow->isVisible())
- {
- requestedWindow->requestMoveToTop();
- }
- used = true;
- }
-
- // 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:
+ 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;
-
- default:
- break;
-
- case SDLK_f:
+ case KeyboardConfig::KEY_PATHFIND:
// Find path to mouse (debug purpose)
viewport->toggleDebugPath();
used = true;
break;
-
- case SDLK_t:
+ 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
{
- TradeHandler *th = static_cast<TradeHandler*>(
- mTradeHandler.get());
- th->setAcceptTradeRequests(
- !th->acceptTradeRequests());
+ chatWindow->chatLog(
+ _("Accepting incoming trade requests"),
+ BY_SERVER);
+ deflt |= PlayerRelation::TRADE;
}
+
+ player_relations.setDefault(deflt);
+
used = true;
break;
}
+ }
- // 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;
- }
-
- if (emotion)
- {
- player_node->emote(emotion);
- used = true;
- }
+ if (requestedWindow)
+ {
+ requestedWindow->setVisible(!requestedWindow->isVisible());
+ if (requestedWindow->isVisible())
+ requestedWindow->requestMoveToTop();
+ used = true;
}
}
-
// Quit event
else if (event.type == SDL_QUIT)
{
@@ -801,15 +969,31 @@ void Game::handleInput()
// Moving player around
if (player_node->mAction != Being::DEAD &&
+#ifdef EATHENA_SUPPORT
+ current_npc == 0 &&
+#endif
!chatWindow->isInputFocused())
{
// Get the state of the keyboard keys
keyboard.refreshActiveKeys();
- const Vector &pos = player_node->getPosition();
- Uint16 x = (int) pos.x / 32;
- Uint16 y = (int) pos.y / 32;
+ // Ignore input if either "ignore" key is pressed
+ // Stops the character moving about if the user's window manager
+ // uses "ignore+arrow key" to switch virtual desktops.
+ if (keyboard.isKeyActive(keyboard.KEY_IGNORE_INPUT_1) ||
+ keyboard.isKeyActive(keyboard.KEY_IGNORE_INPUT_2))
+ {
+ return;
+ }
+#ifdef TMWSERV_SUPPORT
+ const Vector &pos = player_node->getPosition();
+ const Uint16 x = (int) pos.x / 32;
+ const Uint16 y = (int) pos.y / 32;
+#else
+ const Uint16 x = player_node->mX;
+ const Uint16 y = player_node->mY;
+#endif
unsigned char direction = 0;
// Translate pressed keys to movement and direction
@@ -835,6 +1019,7 @@ void Game::handleInput()
direction |= Being::RIGHT;
}
+#ifdef TMWSERV_SUPPORT
// First if player is pressing key for the direction he is already
// going
if (direction == player_node->getWalkingDir())
@@ -854,31 +1039,100 @@ void Game::handleInput()
{
player_node->stopWalking(true);
}
+#else
+ player_node->setWalkingDir(direction);
- // Target the nearest player if 'q' is pressed
- if (keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER))
+ // Attacking monsters
+ if (keyboard.isKeyActive(keyboard.KEY_ATTACK) ||
+ (joystick && joystick->buttonPressed(0)))
{
- Being *target = beingManager->findNearestLivingBeing(
- player_node, 20, Being::PLAYER);
+ Being *target = beingManager->findNearestLivingBeing(x, y, 20,
+ Being::MONSTER);
- if (target)
+ bool newTarget = !keyboard.isKeyActive(keyboard.KEY_TARGET);
+ // A set target has highest priority
+ if (newTarget || !player_node->getTarget())
{
- player_node->setTarget(target);
+ Uint16 targetX = x, targetY = y;
+
+ 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);
+ if (!target)
+ target = beingManager->findBeing(targetX, targetY, Being::PLAYER);
}
+
+ player_node->attack(target, newTarget);
+ }
+#endif
+
+ // 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);
+
+ player_node->setTarget(target);
}
// Target the nearest monster if 'a' pressed
- if (keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST))
+ 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();
+ }
}
}
+#ifdef EATHENA_SUPPORT
+ // Stop attacking if shift is pressed
+ if (keyboard.isKeyActive(keyboard.KEY_TARGET))
+ {
+ player_node->stopAttack();
+ }
+#endif
+
if (joystick)
{
if (joystick->buttonPressed(1))
diff --git a/src/game.h b/src/game.h
index 4035584b..7eecc036 100644
--- a/src/game.h
+++ b/src/game.h
@@ -1,38 +1,37 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_GAME_
-#define _TMW_GAME_
+#ifndef GAME_H
+#define GAME_H
-#include <iosfwd>
#include <memory>
#include "SDL.h"
#include "configlistener.h"
-#define SPEECH_TIME 80
-#define SPEECH_MAX_TIME 100
-
class MessageHandler;
+#ifdef EATHENA_SUPPORT
+class Network;
+#endif
extern std::string map_path;
extern volatile int fps;
@@ -41,7 +40,11 @@ extern volatile int tick_time;
class Game : public ConfigListener
{
public:
+#ifdef TMWSERV_SUPPORT
Game();
+#else
+ Game(Network *network);
+#endif
~Game();
void logic();
@@ -51,6 +54,10 @@ class Game : public ConfigListener
void optionChanged(const std::string &name);
private:
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+#endif
+
/** Used to determine whether to draw the next frame. */
int mDrawTime;
@@ -59,17 +66,22 @@ class Game : public ConfigListener
typedef const std::auto_ptr<MessageHandler> MessageHandlerPtr;
MessageHandlerPtr mBeingHandler;
+#ifdef TMWSERV_SUPPORT
+ MessageHandlerPtr mGuildHandler;
+ MessageHandlerPtr mPartyHandler;
+ MessageHandlerPtr mEffectHandler;
+#else
+ MessageHandlerPtr mEquipmentHandler;
+ MessageHandlerPtr mSkillHandler;
+#endif
MessageHandlerPtr mBuySellHandler;
MessageHandlerPtr mChatHandler;
- MessageHandlerPtr mGuildHandler;
MessageHandlerPtr mInventoryHandler;
MessageHandlerPtr mItemHandler;
MessageHandlerPtr mNpcHandler;
- MessageHandlerPtr mPartyHandler;
MessageHandlerPtr mPlayerHandler;
MessageHandlerPtr mPostHandler;
MessageHandlerPtr mTradeHandler;
- MessageHandlerPtr mEffectHandler;
SDL_TimerID mLogicCounterId;
SDL_TimerID mSecondsCounterId;
diff --git a/src/graphics.cpp b/src/graphics.cpp
index 6920bcb0..4af7b723 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -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 efdd1ac1..172032dc 100644
--- a/src/graphics.h
+++ b/src/graphics.h
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -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/box.h b/src/gui/box.h
deleted file mode 100644
index 46654b48..00000000
--- a/src/gui/box.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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 BOX_H
-#define BOX_H
-
-#include <guichan/widgets/container.hpp>
-
-#include "../guichanfwd.h"
-
-class Box : public gcn::Container
-{
- public:
- /**
- * Returns padding.
- */
- unsigned int getPadding();
-
- /**
- * Sets padding between widgets.
- */
- void setPadding(unsigned int);
-
- protected:
- Box();
- virtual ~Box();
-
- /**
- * Spacing between client widgets.
- */
- unsigned int padding;
-
- virtual void draw(gcn::Graphics *) = 0;
-
- typedef std::list<gcn::Widget*> Widgets;
- typedef Widgets::iterator WidgetIterator;
-};
-
-#endif
diff --git a/src/gui/browserbox.cpp b/src/gui/browserbox.cpp
index 03540d31..7c0ae1a7 100644
--- a/src/gui/browserbox.cpp
+++ b/src/gui/browserbox.cpp
@@ -1,35 +1,37 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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));
}
diff --git a/src/gui/browserbox.h b/src/gui/browserbox.h
index cb4c23ed..090c03e1 100644
--- a/src/gui/browserbox.h
+++ b/src/gui/browserbox.h
@@ -1,36 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __TMW_BROWSERBOX_H__
-#define __TMW_BROWSERBOX_H__
+#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.
@@ -124,7 +121,7 @@ class BrowserBox : public gcn::Widget, public gcn::MouseListener
enum {
BLACK = 0x000000, /**< Color 0 */
RED = 0xff0000, /**< Color 1 */
- GREEN = 0x1fa052, /**< Color 2 */
+ GREEN = 0x009000, /**< Color 2 */
BLUE = 0x0000ff, /**< Color 3 */
ORANGE = 0xe0980e, /**< Color 4 */
YELLOW = 0xf1dc27, /**< Color 5 */
diff --git a/src/gui/button.cpp b/src/gui/button.cpp
index 40ecd1b7..1d3a04e4 100644
--- a/src/gui/button.cpp
+++ b/src/gui/button.cpp
@@ -1,32 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <algorithm>
-
#include <guichan/exception.hpp>
-#include <guichan/graphics.hpp>
-#include <guichan/imagefont.hpp>
+#include <guichan/font.hpp>
#include "button.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
@@ -35,6 +33,7 @@
#include "../utils/dtor.h"
int Button::mInstances = 0;
+float Button::mAlpha = config.getValue("guialpha", 0.8);
enum{
BUTTON_STANDARD, // 0
@@ -52,10 +51,10 @@ struct ButtonData
};
static ButtonData const data[BUTTON_COUNT] = {
- {"graphics/gui/button.png", 0, 0},
- {"graphics/gui/buttonhi.png", 9, 4},
- {"graphics/gui/buttonpress.png", 16, 19},
- {"graphics/gui/button_disabled.png", 25, 23}
+ { "graphics/gui/button.png", 0, 0 },
+ { "graphics/gui/buttonhi.png", 9, 4 },
+ { "graphics/gui/buttonpress.png", 16, 19 },
+ { "graphics/gui/button_disabled.png", 25, 23 }
};
ImageRect Button::button[BUTTON_COUNT];
@@ -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 f451416c..abaf5c43 100644
--- a/src/gui/button.h
+++ b/src/gui/button.h
@@ -1,28 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_BUTTON_H
-#define _TMW_BUTTON_H
-
-#include <iosfwd>
+#ifndef BUTTON_H
+#define BUTTON_H
#include <guichan/widgets/button.hpp>
@@ -33,7 +31,8 @@ class ImageRect;
*
* \ingroup GUI
*/
-class Button : public gcn::Button {
+class Button : public gcn::Button
+{
public:
/**
* Default constructor.
@@ -44,7 +43,7 @@ class Button : public gcn::Button {
* Constructor, sets the caption of the button to the given string and
* adds the given action listener.
*/
- Button(const std::string& caption, const std::string &actionEventId,
+ Button(const std::string &caption, const std::string &actionEventId,
gcn::ActionListener *listener);
/**
@@ -55,7 +54,7 @@ class Button : public gcn::Button {
/**
* Draws the button.
*/
- void draw(gcn::Graphics* graphics);
+ void draw(gcn::Graphics *graphics);
/**
* Enable/Disable highlighting
@@ -68,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 cc2262ec..15a558a3 100644
--- a/src/gui/buy.cpp
+++ b/src/gui/buy.cpp
@@ -1,29 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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"
@@ -32,12 +31,27 @@
#include "widgets/layout.h"
#include "../npc.h"
+#include "../units.h"
+
+#ifdef TMWSERV_SUPPORT
#include "../net/gameserver/player.h"
+#else
+#include "../net/messageout.h"
+#include "../net/ea/protocol.h"
+#endif
+
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
+#ifdef TMWSERV_SUPPORT
BuyDialog::BuyDialog():
+#else
+BuyDialog::BuyDialog(Network *network):
+#endif
Window(_("Buy")),
+#ifndef TMWSERV_SUPPORT
+ mNetwork(network),
+#endif
mMoney(0), mAmountItems(0), mMaxItems(0)
{
setWindowName("Buy");
@@ -52,7 +66,8 @@ BuyDialog::BuyDialog():
mScrollArea = new ScrollArea(mShopItemList);
mSlider = new Slider(1.0);
mQuantityLabel = new gcn::Label("0");
- mMoneyLabel = new gcn::Label(strprintf(_("Price: %d GP / Total: %d GP"), 0, 0));
+ mMoneyLabel = new gcn::Label(strprintf(_("Price: %s / Total: %s"),
+ "", ""));
mIncreaseButton = new Button("+", "+", this);
mDecreaseButton = new Button("-", "-", this);
mBuyButton = new Button(_("Buy"), "buy", this);
@@ -128,7 +143,7 @@ void BuyDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "quit")
{
setVisible(false);
- current_npc = 0;
+ if (current_npc) current_npc->handleDeath();
return;
}
@@ -162,8 +177,16 @@ void BuyDialog::action(const gcn::ActionEvent &event)
else if (event.getId() == "buy" && mAmountItems > 0 &&
mAmountItems <= mMaxItems)
{
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::tradeWithNPC
(mShopItems->at(selectedItem)->getId(), mAmountItems);
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_NPC_BUY_REQUEST);
+ outMsg.writeInt16(8);
+ outMsg.writeInt16(mAmountItems);
+ outMsg.writeInt16(mShopItems->at(selectedItem)->getId());
+#endif
// Update money and adjust the max number of items that can be bought
mMaxItems -= mAmountItems;
@@ -230,5 +253,7 @@ void BuyDialog::updateButtonsAndLabels()
// Update quantity and money labels
mQuantityLabel->setCaption(strprintf("%d / %d", mAmountItems, mMaxItems));
mMoneyLabel->setCaption
- (strprintf(_("Price: %d GP / Total: %d GP"), price, mMoney - price));
+ (strprintf(_("Price: %s / Total: %s"),
+ Units::formatCurrency(price).c_str(),
+ Units::formatCurrency(mMoney - price).c_str()));
}
diff --git a/src/gui/buy.h b/src/gui/buy.h
index a80ffed7..5510ccc6 100644
--- a/src/gui/buy.h
+++ b/src/gui/buy.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_BUY_H
-#define _TMW_BUY_H
+#ifndef BUY_H
+#define BUY_H
#include <guichan/actionlistener.hpp>
#include <guichan/selectionlistener.hpp>
@@ -29,6 +29,9 @@
#include "../guichanfwd.h"
+#ifndef TMWSERV_SUPPORT
+class Network;
+#endif
class ShopItems;
class ShopListBox;
class ListBox;
@@ -39,7 +42,7 @@ class ListBox;
* \ingroup Interface
*/
class BuyDialog : public Window, public gcn::ActionListener,
- gcn::SelectionListener
+ public gcn::SelectionListener
{
public:
/**
@@ -47,7 +50,11 @@ class BuyDialog : public Window, public gcn::ActionListener,
*
* @see Window::Window
*/
+#ifdef TMWSERV_SUPPORT
BuyDialog();
+#else
+ BuyDialog(Network *network);
+#endif
/**
* Destructor
@@ -95,6 +102,9 @@ class BuyDialog : public Window, public gcn::ActionListener,
void updateButtonsAndLabels();
private:
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+#endif
gcn::Button *mBuyButton;
gcn::Button *mQuitButton;
gcn::Button *mIncreaseButton;
diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp
index 42380882..2d39eac7 100644
--- a/src/gui/buysell.cpp
+++ b/src/gui/buysell.cpp
@@ -1,42 +1,43 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "buysell.h"
-
#include "button.h"
+#include "buysell.h"
#include "../npc.h"
+#include "../utils/gettext.h"
+
BuySellDialog::BuySellDialog():
- Window("Shop")
+ Window(_("Shop"))
{
Button *buyButton = 0;
- const char *buttonNames[] = {
- "Buy", "Sell", "Cancel", 0
+ static const char *buttonNames[] = {
+ N_("Buy"), N_("Sell"), N_("Cancel"), 0
};
int x = 10, y = 10;
for (const char **curBtn = buttonNames; *curBtn; curBtn++)
{
- Button *btn = new Button(*curBtn, *curBtn, this);
+ Button *btn = new Button(gettext(*curBtn), *curBtn, this);
if (!buyButton) buyButton = btn; // For focus request
btn->setPosition(x, y);
add(btn);
@@ -57,7 +58,7 @@ void BuySellDialog::action(const gcn::ActionEvent &event)
} else if (event.getId() == "Sell") {
current_npc->sell();
} else if (event.getId() == "Cancel") {
- current_npc = 0;
+ if (current_npc) current_npc->handleDeath();
}
setVisible(false);
}
diff --git a/src/gui/buysell.h b/src/gui/buysell.h
index 2391ed1c..e3cdc52a 100644
--- a/src/gui/buysell.h
+++ b/src/gui/buysell.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_BUYSELL_H
-#define _TMW_BUYSELL_H
+#ifndef BUYSELL_H
+#define BUYSELL_H
#include <guichan/actionlistener.hpp>
diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp
index f800c266..84270d10 100644
--- a/src/gui/char_select.cpp
+++ b/src/gui/char_select.cpp
@@ -1,57 +1,65 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 "radiobutton.h"
+#include "char_select.h"
#include "confirm_dialog.h"
#include "ok_dialog.h"
#include "playerbox.h"
-#include "slider.h"
#include "textfield.h"
+#ifdef TMWSERV_SUPPORT
+#include "radiobutton.h"
+#include "slider.h"
+
#include "unregisterdialog.h"
#include "changepassworddialog.h"
#include "changeemaildialog.h"
+#include "../logindata.h"
+
+#include "../net/accountserver/account.h"
+#endif
+
#include "widgets/layout.h"
#include "../game.h"
#include "../localplayer.h"
#include "../main.h"
-#include "../logindata.h"
+#include "../units.h"
-#include "../net/accountserver/account.h"
#include "../net/charserverhandler.h"
#include "../net/messageout.h"
+#include "../resources/colordb.h"
+
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
-#include "../utils/tostring.h"
-#include "../utils/trim.h"
+#include "../utils/stringutils.h"
// Defined in main.cpp, used here for setting the char create dialog
extern CharServerHandler charServerHandler;
@@ -78,24 +86,37 @@ 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);
}
+#ifdef TMWSERV_SUPPORT
CharSelectDialog::CharSelectDialog(LockedArray<LocalPlayer*> *charInfo,
LoginData *loginData):
Window(_("Account and Character Management")),
mCharInfo(charInfo), mCharSelected(false), mLoginData(loginData)
+#else
+CharSelectDialog::CharSelectDialog(Network *network,
+ LockedArray<LocalPlayer*> *charInfo,
+ Gender gender):
+ Window(_("Select Character")), mNetwork(network),
+ mCharInfo(charInfo),
+ mCharSelected(false),
+ mGender(gender)
+#endif
{
-
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);
+ mNameLabel = new gcn::Label(strprintf(_("Name: %s"), ""));
+ mLevelLabel = new gcn::Label(strprintf(_("Level: %d"), 0));
+#ifdef TMWSERV_SUPPORT
+ mNewCharButton = new Button(_("New"), "new", this);
+ mDelCharButton = new Button(_("Delete"), "delete", this);
mUnRegisterButton = new Button(_("Unregister"), "unregister", this);
mChangePasswordButton = new Button(_("Change Password"), "change_password", this);
mChangeEmailButton = new Button(_("Change Email Address"), "change_email", this);
@@ -129,6 +150,42 @@ CharSelectDialog::CharSelectDialog(LockedArray<LocalPlayer*> *charInfo,
place(0, 0, mSelectButton);
place(1, 0, mCancelButton);
reflowLayout(265, 0);
+#else
+ mCharInfo->select(0);
+ LocalPlayer *pi = mCharInfo->getEntry();
+ if (pi)
+ mMoney = Units::formatCurrency(pi->getMoney());
+ // Control that shows the Player
+ mPlayerBox = new PlayerBox;
+ mPlayerBox->setWidth(74);
+
+ mJobLevelLabel = new gcn::Label(strprintf(_("Job Level: %d"), 0));
+ mMoneyLabel = new gcn::Label(strprintf(_("Money: %s"), mMoney.c_str()));
+
+ const std::string tempString = getFont()->getWidth(_("New")) <
+ getFont()->getWidth(_("Delete")) ?
+ _("Delete") : _("New");
+
+ mNewDelCharButton = new Button(tempString, "newdel", this);
+
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
+
+ place(0, 0, mPlayerBox, 1, 6).setPadding(3);
+ 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, mPreviousButton);
+ place(1, 0, mNextButton);
+ place(4, 0, mCancelButton);
+ place(5, 0, mSelectButton);
+
+ reflowLayout(250, 0);
+#endif
setLocationRelativeTo(getParent());
setVisible(true);
@@ -138,25 +195,37 @@ CharSelectDialog::CharSelectDialog(LockedArray<LocalPlayer*> *charInfo,
void CharSelectDialog::action(const gcn::ActionEvent &event)
{
+#ifdef TMWSERV_SUPPORT
// The pointers are set to NULL if there is no character stored
if (event.getId() == "ok" && (mCharInfo->getEntry()))
+#else
+ if (event.getId() == "ok" && n_character > 0)
+#endif
{
// Start game
+#ifdef TMWSERV_SUPPORT
mNewCharButton->setEnabled(false);
mDelCharButton->setEnabled(false);
- mSelectButton->setEnabled(false);
mUnRegisterButton->setEnabled(false);
+#else
+ mNewDelCharButton->setEnabled(false);
+#endif
+ mSelectButton->setEnabled(false);
mPreviousButton->setEnabled(false);
mNextButton->setEnabled(false);
mCharSelected = true;
- Net::AccountServer::Account::selectCharacter(mCharInfo->getPos());
- mCharInfo->lock();
+ attemptCharSelect();
}
else if (event.getId() == "cancel")
{
+#ifdef TMWSERV_SUPPORT
mCharInfo->clear();
state = STATE_SWITCH_ACCOUNTSERVER_ATTEMPT;
+#else
+ state = STATE_EXIT;
+#endif
}
+#ifdef TMWSERV_SUPPORT
else if (event.getId() == "new")
{
// TODO: Search the first free slot, and start CharCreateDialog
@@ -177,14 +246,39 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
new CharDeleteConfirm(this);
}
}
+#else
+ else if (event.getId() == "newdel")
+ {
+ // Check for a character
+ if (mCharInfo->getEntry() && n_character <= MAX_SLOT + 1)
+ {
+ new CharDeleteConfirm(this);
+ }
+ else
+ {
+ // Start new character dialog
+ CharCreateDialog *charCreateDialog =
+ new CharCreateDialog(this, mCharInfo->getPos(),
+ mNetwork, mGender);
+ charServerHandler.setCharCreateDialog(charCreateDialog);
+ }
+ }
+#endif
else if (event.getId() == "previous")
{
mCharInfo->prev();
+ LocalPlayer *pi = mCharInfo->getEntry();
+ if (pi)
+ mMoney = Units::formatCurrency(pi->getMoney());
}
else if (event.getId() == "next")
{
mCharInfo->next();
+ LocalPlayer *pi = mCharInfo->getEntry();
+ if (pi)
+ mMoney = Units::formatCurrency(pi->getMoney());
}
+#ifdef TMWSERV_SUPPORT
else if (event.getId() == "unregister")
{
new UnRegisterDialog(this, mLoginData);
@@ -197,6 +291,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
{
new ChangeEmailDialog(this, mLoginData);
}
+#endif
}
void CharSelectDialog::updatePlayerInfo()
@@ -205,22 +300,39 @@ void CharSelectDialog::updatePlayerInfo()
if (pi)
{
- mNameLabel->setCaption(strprintf(_("Name: %s"), pi->getName().c_str()));
+ mNameLabel->setCaption(strprintf(_("Name: %s"),
+ pi->getName().c_str()));
mLevelLabel->setCaption(strprintf(_("Level: %d"), pi->getLevel()));
- mMoneyLabel->setCaption(strprintf(_("Money: %d"), pi->getMoney()));
+#ifndef TMWSERV_SUPPORT
+ mJobLevelLabel->setCaption(strprintf(_("Job Level: %d"),
+ pi->mJobLevel));
+#endif
+ mMoneyLabel->setCaption(strprintf(_("Money: %s"), mMoney.c_str()));
if (!mCharSelected)
{
+#ifdef TMWSERV_SUPPORT
mNewCharButton->setEnabled(false);
mDelCharButton->setEnabled(true);
+#else
+ mNewDelCharButton->setCaption(_("Delete"));
+#endif
mSelectButton->setEnabled(true);
}
}
- else {
+ else
+ {
mNameLabel->setCaption(strprintf(_("Name: %s"), ""));
mLevelLabel->setCaption(strprintf(_("Level: %d"), 0));
- mMoneyLabel->setCaption(strprintf(_("Money: %d"), 0));
+#ifndef TMWSERV_SUPPORT
+ mJobLevelLabel->setCaption(strprintf(_("Job Level: %d"), 0));
+#endif
+ mMoneyLabel->setCaption(strprintf(_("Money: %s"), ""));
+#ifdef TMWSERV_SUPPORT
mNewCharButton->setEnabled(true);
mDelCharButton->setEnabled(false);
+#else
+ mNewDelCharButton->setCaption(_("New"));
+#endif
mSelectButton->setEnabled(false);
}
@@ -229,7 +341,28 @@ void CharSelectDialog::updatePlayerInfo()
void CharSelectDialog::attemptCharDelete()
{
+#ifdef TMWSERV_SUPPORT
Net::AccountServer::Account::deleteCharacter(mCharInfo->getPos());
+#else
+ // Request character deletion
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0068);
+ outMsg.writeInt32(mCharInfo->getEntry()->mCharId);
+ outMsg.writeString("a@a.com", 40);
+#endif
+ mCharInfo->lock();
+}
+
+void CharSelectDialog::attemptCharSelect()
+{
+#ifdef TMWSERV_SUPPORT
+ Net::AccountServer::Account::selectCharacter(mCharInfo->getPos());
+#else
+ // Request character selection
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0066);
+ outMsg.writeInt8(mCharInfo->getPos());
+#endif
mCharInfo->lock();
}
@@ -246,7 +379,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)
@@ -260,14 +394,29 @@ bool CharSelectDialog::selectByName(const std::string &name)
return false;
}
-
+#ifdef TMWSERV_SUPPORT
CharCreateDialog::CharCreateDialog(Window *parent, int slot):
- Window(_("Create Character"), true, parent), mSlot(slot)
+#else
+CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network,
+ Gender gender):
+#endif
+ Window(_("Create Character"), true, parent),
+#ifndef TMWSERV_SUPPORT
+ mNetwork(network),
+#endif
+ mSlot(slot)
{
mPlayer = new Player(0, 0, NULL);
- mPlayer->setHairStyle(rand() % Being::getHairStylesNr(),
- rand() % Being::getHairColorsNr());
+#ifdef TMWSERV_SUPPORT
mPlayer->setGender(GENDER_MALE);
+#else
+ mPlayer->setGender(gender);
+#endif
+
+ int numberOfHairColors = ColorDB::size();
+
+ mPlayer->setHairStyle(rand() % mPlayer->getNumOfHairstyles(),
+ rand() % numberOfHairColors);
mNameField = new TextField("");
mNameLabel = new gcn::Label(_("Name:"));
@@ -279,19 +428,34 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot):
mHairStyleLabel = new gcn::Label(_("Hair Style:"));
mCreateButton = new Button(_("Create"), "create", this);
mCancelButton = new Button(_("Cancel"), "cancel", this);
-
+#ifdef TMWSERV_SUPPORT
mMale = new RadioButton(_("Male"), "gender");
mFemale = new RadioButton(_("Female"), "gender");
+ // Default to a Male character
+ mMale->setSelected(true);
+
+ mMale->setActionEventId("gender");
+ mFemale->setActionEventId("gender");
+
+ mMale->addActionListener(this);
+ mFemale->addActionListener(this);
+#endif
mPlayerBox = new PlayerBox(mPlayer);
+ mPlayerBox->setWidth(74);
+
+ mNameField->setActionEventId("create");
+ mNameField->addActionListener(this);
+
+#ifdef TMWSERV_SUPPORT
mAttributeLabel[0] = new gcn::Label(_("Strength:"));
mAttributeLabel[1] = new gcn::Label(_("Agility:"));
mAttributeLabel[2] = new gcn::Label(_("Dexterity:"));
mAttributeLabel[3] = new gcn::Label(_("Vitality:"));
mAttributeLabel[4] = new gcn::Label(_("Intelligence:"));
mAttributeLabel[5] = new gcn::Label(_("Willpower:"));
- for (int i=0; i<6; i++)
+ for (int i = 0; i < 6; i++)
{
mAttributeLabel[i]->setWidth(70);
mAttributeSlider[i] = new Slider(1, 20);
@@ -300,8 +464,6 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot):
mAttributesLeft = new gcn::Label(strprintf(_("Please distribute %d points"), 99));
- mNameField->setActionEventId("create");
-
int w = 200;
int h = 330;
setContentSize(w, h);
@@ -334,19 +496,8 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot):
mCancelButton->getX() - 5 - mCreateButton->getWidth(),
h - 5 - mCancelButton->getHeight());
- mNameField->addActionListener(this);
-
- mMale->setPosition( 30, 120 );
- mFemale->setPosition( 100, 120 );
-
- // Default to a Male character
- mMale->setSelected(true);
-
- mMale->setActionEventId("gender");
- mFemale->setActionEventId("gender");
-
- mMale->addActionListener(this);
- mFemale->addActionListener(this);
+ mMale->setPosition(30, 120);
+ mFemale->setPosition(100, 120);
add(mPlayerBox);
add(mNameField);
@@ -357,7 +508,7 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot):
add(mNextHairStyleButton);
add(mPrevHairStyleButton);
add(mHairStyleLabel);
- for (int i=0; i<6; i++)
+ for (int i = 0; i < 6; i++)
{
add(mAttributeSlider[i]);
add(mAttributeValue[i]);
@@ -370,6 +521,28 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot):
add(mMale);
add(mFemale);
+#else
+
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
+
+ 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);
+
+ reflowLayout(225, 0);
+#endif
+
setLocationRelativeTo(getParent());
setVisible(true);
mNameField->requestFocus();
@@ -383,14 +556,16 @@ 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);
-
+#ifdef TMWSERV_SUPPORT
unsigned int genderSelected;
if (mMale->isSelected()) {
genderSelected = GENDER_MALE;
@@ -410,26 +585,34 @@ CharCreateDialog::action(const gcn::ActionEvent &event)
(int) mAttributeSlider[4]->getValue(), // INT
(int) mAttributeSlider[5]->getValue() // WILL
);
+#else
+ attemptCharCreate();
+#endif
}
- else {
- new OkDialog(_("Error"),_("Your name needs to be at least 4 characters."), this);
+ 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());
+#ifdef TMWSERV_SUPPORT
else if (event.getId() == "statslider") {
UpdateSliders();
}
@@ -440,16 +623,17 @@ CharCreateDialog::action(const gcn::ActionEvent &event)
mPlayer->setGender(GENDER_FEMALE);
}
}
+#endif
}
-std::string
-CharCreateDialog::getName()
+std::string CharCreateDialog::getName()
{
std::string name = mNameField->getText();
trim(name);
return name;
}
+#ifdef TMWSERV_SUPPORT
void CharCreateDialog::UpdateSliders()
{
for (int i = 0; i < 6; i++)
@@ -482,13 +666,14 @@ void CharCreateDialog::UpdateSliders()
mAttributesLeft->adjustSize();
}
+#endif
-void
-CharCreateDialog::unlock()
+void CharCreateDialog::unlock()
{
mCreateButton->setEnabled(true);
}
+#ifdef TMWSERV_SUPPORT
int CharCreateDialog::getDistributedPoints()
{
int points = 0;
@@ -499,3 +684,23 @@ int CharCreateDialog::getDistributedPoints()
}
return points;
}
+#endif
+
+#ifndef TMWSERV_SUPPORT
+void CharCreateDialog::attemptCharCreate()
+{
+ // Send character infos
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0067);
+ outMsg.writeString(getName(), 24);
+ outMsg.writeInt8(5);
+ outMsg.writeInt8(5);
+ outMsg.writeInt8(5);
+ outMsg.writeInt8(5);
+ outMsg.writeInt8(5);
+ outMsg.writeInt8(5);
+ outMsg.writeInt8(mSlot);
+ outMsg.writeInt16(mPlayer->getHairColor());
+ outMsg.writeInt16(mPlayer->getHairStyle());
+}
+#endif
diff --git a/src/gui/char_select.h b/src/gui/char_select.h
index ed03cedd..0ff1d18f 100644
--- a/src/gui/char_select.h
+++ b/src/gui/char_select.h
@@ -1,38 +1,43 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _CHAR_SELECT_H
#define _CHAR_SELECT_H
+#include <guichan/actionlistener.hpp>
+
#include "window.h"
+#include "../being.h"
#include "../guichanfwd.h"
#include "../lockedarray.h"
-#include <guichan/actionlistener.hpp>
-
+#ifdef TMWSERV_SUPPORT
#include "../logindata.h"
+#else
+class Network;
+#endif
-class Player;
class LocalPlayer;
+class Player;
class PlayerBox;
/**
@@ -47,8 +52,14 @@ class CharSelectDialog : public Window, public gcn::ActionListener
/**
* Constructor.
*/
+#ifdef TMWSERV_SUPPORT
CharSelectDialog(LockedArray<LocalPlayer*> *charInfo,
LoginData *loginData);
+#else
+ CharSelectDialog(Network *network,
+ LockedArray<LocalPlayer*> *charInfo,
+ Gender gender);
+#endif
void action(const gcn::ActionEvent &event);
@@ -59,28 +70,40 @@ class CharSelectDialog : public Window, public gcn::ActionListener
bool selectByName(const std::string &name);
private:
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+#endif
LockedArray<LocalPlayer*> *mCharInfo;
gcn::Button *mSelectButton;
gcn::Button *mCancelButton;
- gcn::Button *mNewCharButton;
- gcn::Button *mDelCharButton;
gcn::Button *mPreviousButton;
gcn::Button *mNextButton;
- gcn::Button *mUnRegisterButton;
- gcn::Button *mChangePasswordButton;
- gcn::Button *mChangeEmailButton;
- gcn::Label *mAccountNameLabel;
gcn::Label *mNameLabel;
gcn::Label *mLevelLabel;
gcn::Label *mMoneyLabel;
+ std::string mMoney;
PlayerBox *mPlayerBox;
bool mCharSelected;
+#ifdef TMWSERV_SUPPORT
+ gcn::Button *mNewCharButton;
+ gcn::Button *mDelCharButton;
+ gcn::Button *mUnRegisterButton;
+ gcn::Button *mChangePasswordButton;
+ gcn::Button *mChangeEmailButton;
+ gcn::Label *mAccountNameLabel;
+
LoginData *mLoginData;
+#else
+ gcn::Button *mNewDelCharButton;
+ gcn::Label *mJobLevelLabel;
+ Gender mGender;
+#endif
+
/**
* Communicate character deletion to the server.
*/
@@ -103,7 +126,12 @@ class CharCreateDialog : public Window, public gcn::ActionListener
/**
* Constructor.
*/
+#ifdef TMWSERV_SUPPORT
CharCreateDialog(Window *parent, int slot);
+#else
+ CharCreateDialog(Window *parent, int slot, Network *network,
+ Gender gender);
+#endif
/**
* Destructor.
@@ -118,9 +146,11 @@ class CharCreateDialog : public Window, public gcn::ActionListener
void unlock();
private:
+#ifdef TMWSERV_SUPPORT
int getDistributedPoints();
void UpdateSliders();
+#endif
/**
* Returns the name of the character to create.
@@ -132,6 +162,9 @@ class CharCreateDialog : public Window, public gcn::ActionListener
*/
void attemptCharCreate();
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+#endif
gcn::TextField *mNameField;
gcn::Label *mNameLabel;
gcn::Button *mNextHairColorButton;
@@ -141,6 +174,7 @@ class CharCreateDialog : public Window, public gcn::ActionListener
gcn::Button *mPrevHairStyleButton;
gcn::Label *mHairStyleLabel;
+#ifdef TMWSERV_SUPPORT
gcn::RadioButton *mMale;
gcn::RadioButton *mFemale;
@@ -149,6 +183,10 @@ class CharCreateDialog : public Window, public gcn::ActionListener
gcn::Label *mAttributeValue[6];
gcn::Label *mAttributesLeft;
+ static const int mMaxPoints = 60;
+ int mUsedPoints;
+#endif
+
gcn::Button *mCreateButton;
gcn::Button *mCancelButton;
@@ -156,9 +194,6 @@ class CharCreateDialog : public Window, public gcn::ActionListener
PlayerBox *mPlayerBox;
int mSlot;
-
- static const int mMaxPoints = 60;
- int mUsedPoints;
};
#endif
diff --git a/src/gui/char_server.cpp b/src/gui/char_server.cpp
new file mode 100644
index 00000000..fa03bdc2
--- /dev/null
+++ b/src/gui/char_server.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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 "button.h"
+#include "char_server.h"
+#include "listbox.h"
+#include "scrollarea.h"
+
+#include "../logindata.h"
+#include "../main.h"
+#include "../serverinfo.h"
+
+#include "../utils/gettext.h"
+#include "../utils/stringutils.h"
+
+extern SERVER_INFO **server_info;
+
+/**
+ * The list model for the server list.
+ */
+class ServerListModel : public gcn::ListModel
+{
+ public:
+ virtual ~ServerListModel() {};
+
+ int getNumberOfElements();
+ std::string getElementAt(int i);
+};
+
+ServerSelectDialog::ServerSelectDialog(LoginData *loginData, int nextState):
+ Window(_("Select Server")),
+ mLoginData(loginData),
+ mNextState(nextState)
+{
+ mServerListModel = new ServerListModel;
+ mServerList = new ListBox(mServerListModel);
+ ScrollArea *mScrollArea = new ScrollArea(mServerList);
+ mOkButton = new Button(_("OK"), "ok", this);
+ Button *mCancelButton = new Button(_("Cancel"), "cancel", this);
+
+ setContentSize(200, 100);
+
+ mCancelButton->setPosition(
+ 200 - mCancelButton->getWidth() - 5,
+ 100 - mCancelButton->getHeight() - 5);
+ mOkButton->setPosition(
+ mCancelButton->getX() - mOkButton->getWidth() - 5,
+ 100 - mOkButton->getHeight() - 5);
+ mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mScrollArea->setDimension(gcn::Rectangle(
+ 5, 5, 200 - 2 * 5,
+ 100 - 3 * 5 - mCancelButton->getHeight() -
+ mScrollArea->getFrameSize()));
+
+ mServerList->setActionEventId("ok");
+
+ //mServerList->addActionListener(this);
+
+ add(mScrollArea);
+ add(mOkButton);
+ add(mCancelButton);
+
+ if (n_server == 0)
+ // Disable Ok button
+ mOkButton->setEnabled(false);
+ else
+ // Select first server
+ mServerList->setSelected(1);
+
+ setLocationRelativeTo(getParent());
+ setVisible(true);
+ mOkButton->requestFocus();
+}
+
+ServerSelectDialog::~ServerSelectDialog()
+{
+ delete mServerListModel;
+}
+
+void ServerSelectDialog::action(const gcn::ActionEvent &event)
+{
+ 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")
+ state = STATE_LOGIN;
+}
+
+int ServerListModel::getNumberOfElements()
+{
+ return n_server;
+}
+
+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
new file mode 100644
index 00000000..49a5b47b
--- /dev/null
+++ b/src/gui/char_server.h
@@ -0,0 +1,65 @@
+/*
+ * 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
+ */
+
+#ifndef _CHAR_SEL_SERVER_H
+#define _CHAR_SEL_SERVER_H
+
+#include <guichan/actionlistener.hpp>
+#include <guichan/listmodel.hpp>
+
+#include "window.h"
+
+class LoginData;
+class ServerListModel;
+
+/**
+ * The server select dialog.
+ *
+ * \ingroup Interface
+ */
+class ServerSelectDialog : public Window, public gcn::ActionListener {
+ public:
+ /**
+ * Constructor
+ *
+ * @see Window::Window
+ */
+ ServerSelectDialog(LoginData *loginData, int nextState);
+
+ /**
+ * Destructor.
+ */
+ ~ServerSelectDialog();
+
+ /**
+ * Called when receiving actions from the widgets.
+ */
+ void action(const gcn::ActionEvent &event);
+
+ private:
+ LoginData *mLoginData;
+ ServerListModel *mServerListModel;
+ gcn::ListBox *mServerList;
+ gcn::Button *mOkButton;
+ int mNextState;
+};
+
+#endif
diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp
index 3d1b5643..37250091 100644
--- a/src/gui/chat.cpp
+++ b/src/gui/chat.cpp
@@ -1,68 +1,83 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 "widgets/tab.h"
#include "widgets/tabbedarea.h"
+#include "../beingmanager.h"
+#ifdef TMWSERV_SUPPORT
#include "../commandhandler.h"
+#endif
#include "../channelmanager.h"
#include "../channel.h"
#include "../configuration.h"
#include "../game.h"
#include "../localplayer.h"
+#ifdef TMWSERV_SUPPORT
#include "../net/chatserver/chatserver.h"
#include "../net/gameserver/player.h"
+#else
+#include "../party.h"
+#include "../net/messageout.h"
+#include "../net/ea/protocol.h"
+#endif
#include "../resources/iteminfo.h"
#include "../resources/itemdb.h"
#include "../utils/dtor.h"
-#include "../utils/trim.h"
-#include "../utils/tostring.h"
+#include "../utils/gettext.h"
+#include "../utils/strprintf.h"
+#include "../utils/stringutils.h"
+#ifdef TMWSERV_SUPPORT
ChatWindow::ChatWindow():
Window("Chat"),
+#else
+ChatWindow::ChatWindow(Network * network):
+ Window(""), mNetwork(network),
+#endif
mTmpVisible(false)
{
setWindowName("Chat");
+
setResizable(true);
setDefaultSize(0, windowContainer->getHeight() - 123, 600, 123);
- setOpaque(false);
+ setMinWidth(150);
+ setMinHeight(90);
- mItemLinkHandler = new ItemLinkHandler();
+ mItemLinkHandler = new ItemLinkHandler;
mChatInput = new ChatInput;
mChatInput->setActionEventId("chatinput");
@@ -74,47 +89,51 @@ ChatWindow::ChatWindow():
textOutput->setLinkHandler(mItemLinkHandler);
ScrollArea *scrollArea = new ScrollArea(textOutput);
- scrollArea->setPosition(
- scrollArea->getFrameSize(), scrollArea->getFrameSize());
- scrollArea->setScrollPolicy(
- gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_ALWAYS);
+ scrollArea->setScrollPolicy(gcn::ScrollArea::SHOW_NEVER,
+ gcn::ScrollArea::SHOW_ALWAYS);
scrollArea->setScrollAmount(0, 1);
scrollArea->setOpaque(false);
mChatTabs = new TabbedArea();
mChatTabs->addTab("General", scrollArea);
- mChatTabs->setPosition(mChatTabs->getFrameSize(),
- mChatTabs->getFrameSize());
- mChannels.insert(
- std::make_pair("General", ChatArea(textOutput, scrollArea)));
+ place(0, 0, mChatTabs, 5, 5).setPadding(0);
+ place(0, 5, mChatInput, 5).setPadding(1);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
+ layout.setMargin(2);
- add(mChatTabs);
- add(mChatInput);
+ loadWindowState();
// Add key listener to chat input to be able to respond to up/down
mChatInput->addKeyListener(this);
mCurHist = mHistory.end();
- loadWindowState();
+#ifdef EATHENA_SUPPORT
+ // 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");
+#endif
}
ChatWindow::~ChatWindow()
{
- delete mChatInput;
- delete mChatTabs;
-}
-
-const std::string &ChatWindow::getFocused() const
-{
- return mChatTabs->getSelectedTab()->getCaption();
-}
-
-void ChatWindow::clearTab(const std::string &tab)
-{
- ChannelMap::const_iterator chan = mChannels.find(tab);
- if (chan != mChannels.end())
- chan->second.browser->clearRows();
+#ifdef EATHENA_SUPPORT
+ char partyPrefix[2] = ".";
+ *partyPrefix = mPartyPrefix;
+ config.setValue("PartyPrefix", partyPrefix);
+ config.setValue("ReturnToggles", mReturnToggles ? "1" : "0");
+ delete mRecorder;
+#endif
}
void ChatWindow::widgetResized(const gcn::Event &event)
@@ -159,7 +178,8 @@ void ChatWindow::logic()
}
}
-void ChatWindow::chatLog(std::string line, int own, std::string channelName)
+void ChatWindow::chatLog(std::string line, int own, std::string channelName,
+ bool ignoreRecord)
{
if(channelName.empty())
channelName = getFocused();
@@ -174,60 +194,122 @@ void ChatWindow::chatLog(std::string line, int own, std::string channelName)
// Trim whitespace
trim(line);
+ if (line.empty())
+ return;
+
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
+ {
+ // Fix the owner of welcome message.
+ if (line.substr(0, 7) == "Welcome")
+ {
+ own = BY_SERVER;
+ }
+ }
+
+ // *implements actions in a backwards compatible way*
+ if (own == BY_PLAYER &&
+ tmp.text.at(0) == '*' &&
+ tmp.text.at(tmp.text.length()-1) == '*')
+ {
+ tmp.text[0] = ' ';
+ tmp.text.erase(tmp.text.length() - 1);
+ own = ACT_IS;
+ }
- std::string lineColor = "##0"; // Equiv. to BrowserBox::BLACK
- switch (own) {
+ std::string lineColor = "##C";
+ switch (own)
+ {
case BY_GM:
- tmp.nick += "Global announcement: ";
- lineColor = "##1"; // Equiv. to BrowserBox::RED
+ if (tmp.nick.empty())
+ {
+ tmp.nick = std::string(_("Global announcement:"));
+ tmp.nick += " ";
+ lineColor = "##G";
+ }
+ else
+ {
+ tmp.nick = strprintf(_("Global announcement from %s:"),
+ tmp.nick.c_str());
+ tmp.nick += " ";
+ lineColor = "##1"; // Equiv. to BrowserBox::RED
+ }
break;
case BY_PLAYER:
- tmp.nick += ": ";
- lineColor = "##3"; // Equiv. to BrowserBox::BLUE
+ tmp.nick += CAT_NORMAL;
+ lineColor = "##Y";
break;
case BY_OTHER:
- tmp.nick += ": ";
- lineColor = "##0"; // Equiv. to BrowserBox::BLACK
+ tmp.nick += CAT_NORMAL;
+ lineColor = "##C";
break;
case BY_SERVER:
- tmp.nick = "Server: ";
+ tmp.nick = _("Server:");
+ tmp.nick += " ";
tmp.text = line;
- lineColor = "##7"; // Equiv. to BrowserBox::PINK
+ lineColor = "##S";
break;
case BY_CHANNEL:
tmp.nick = "";
+ // TODO: Use a predefined color
lineColor = "##2"; // Equiv. to BrowserBox::GREEN
break;
+#ifdef EATHENA_SUPPORT
+ case BY_PARTY:
+ tmp.nick += CAT_NORMAL;
+ lineColor = "##P";
+ break;
+#endif
+ case ACT_WHISPER:
+ tmp.nick = strprintf(_("%s whispers:"), tmp.nick.c_str());
+ tmp.nick += " ";
+ lineColor = "##W";
+ break;
+ case ACT_IS:
+ tmp.nick += CAT_IS;
+ 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";
+ }
+
+#ifdef EATHENA_SUPPORT
+ if (tmp.nick.empty() && tmp.text.substr(0, 17) == "Visible GM status")
+ {
+ player_node->setGM();
+ }
+#endif
+
// 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;
@@ -245,6 +327,26 @@ void ChatWindow::chatLog(std::string line, int own, std::string channelName)
}
scroll->logic();
+ mRecorder->record(line.substr(3));
+}
+
+#ifdef EATHENA_SUPPORT
+void ChatWindow::chatLog(CHATSKILL act)
+{
+ chatLog(const_msg(act), BY_SERVER);
+}
+#endif
+
+const std::string &ChatWindow::getFocused() const
+{
+ return mChatTabs->getSelectedTab()->getCaption();
+}
+
+void ChatWindow::clearTab(const std::string &tab)
+{
+ ChannelMap::const_iterator chan = mChannels.find(tab);
+ if (chan != mChannels.end())
+ chan->second.browser->clearRows();
}
void ChatWindow::action(const gcn::ActionEvent &event)
@@ -253,29 +355,36 @@ 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();
// Send the message to the server
+#ifdef TMWSERV_SUPPORT
chatSend(message);
+#else
+ chatSend(player_node->getName(), message);
+#endif
// Clear the text from the chat input
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);
}
}
}
@@ -305,6 +414,56 @@ bool ChatWindow::isInputFocused()
return mChatInput->isFocused();
}
+void ChatWindow::whisper(const std::string &nick, std::string msg)
+{
+ std::string recvnick = "";
+
+ if (msg.substr(0, 1) == "\"")
+ {
+ const std::string::size_type pos = msg.find('"', 1);
+ if (pos != std::string::npos)
+ {
+ recvnick = msg.substr(1, pos - 1);
+ msg.erase(0, pos + 2);
+ }
+ }
+ else
+ {
+ const std::string::size_type pos = msg.find(" ");
+ if (pos != std::string::npos)
+ {
+ recvnick = msg.substr(0, pos);
+ msg.erase(0, pos + 1);
+ }
+ }
+
+ trim(msg);
+
+ std::string playerName = player_node->getName();
+ std::string tempNick = recvnick;
+
+ toLower(playerName);
+ toLower(tempNick);
+
+ if (tempNick.compare(playerName) == 0 || msg.empty())
+ return;
+
+ // TODO: Implement whispering on tmwserv
+#ifdef EATHENA_SUPPORT
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CHAT_WHISPER);
+ outMsg.writeInt16(msg.length() + 28);
+ outMsg.writeString(recvnick, 24);
+ outMsg.writeString(msg, msg.length());
+
+ chatLog(strprintf(_("Whispering to %s: %s"),
+ recvnick.c_str(), msg.c_str()),
+ BY_PLAYER);
+#endif
+}
+
+#ifdef TMWSERV_SUPPORT
+
void ChatWindow::chatSend(std::string &msg)
{
if (msg.empty()) return;
@@ -415,6 +574,387 @@ void ChatWindow::sendToChannel(short channelId,
}
}
+#else
+
+void ChatWindow::chatSend(const std::string &nick, std::string msg)
+{
+ /* Some messages are managed client side, while others
+ * 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 (start+1 != end && 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);
+
+ toLower(trim(temp));
+
+ 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) != "/")
+ {
+ msg = nick + " : " + msg;
+
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CHAT_MESSAGE);
+ // 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
+ {
+ msg = msg.substr(space);
+ trim(msg);
+ }
+
+ if (command == "announce")
+ {
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0099);
+ outMsg.writeInt16(msg.length() + 4);
+ outMsg.writeString(msg, msg.length());
+ }
+ else if (command == "help")
+ {
+ trim(msg);
+ std::size_t space = msg.find(" ");
+ std::string msg1;
+
+ if (space == std::string::npos)
+ {
+ msg1 = "";
+ }
+ else
+ {
+ msg1 = msg.substr(space + 1, msg.length());
+ msg = msg.substr(0, space);
+ }
+
+ if (!msg.empty() && msg.at(0) == '/')
+ {
+ msg.erase(0, 1);
+ }
+
+ trim(msg1);
+ help(msg, msg1);
+ }
+ 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 (command == "who")
+ {
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x00c1);
+ }
+ else if (command == "clear")
+ clearTab(getFocused());
+ 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, std::string(), true);
+ }
+ else
+ {
+ chatLog(_("Present: ") + response, BY_SERVER);
+ }
+ }
+ else if (command == "me")
+ {
+ std::stringstream actionStr;
+ actionStr << "*" << msg << "*";
+ chatSend(player_node->getName(), actionStr.str());
+ }
+ else
+ {
+ chatLog(_("Unknown command"), BY_SERVER);
+ }
+}
+
+std::string ChatWindow::const_msg(CHATSKILL act)
+{
+ std::string msg;
+ if (act.success == SKILL_FAILED && act.skill == SKILL_BASIC)
+ {
+ switch (act.bskill)
+ {
+ case BSKILL_TRADE:
+ msg = _("Trade failed!");
+ break;
+ case BSKILL_EMOTE:
+ msg = _("Emote failed!");
+ break;
+ case BSKILL_SIT:
+ msg = _("Sit failed!");
+ break;
+ case BSKILL_CREATECHAT:
+ msg = _("Chat creating failed!");
+ break;
+ case BSKILL_JOINPARTY:
+ msg = _("Could not join party!");
+ break;
+ case BSKILL_SHOUT:
+ msg = _("Cannot shout!");
+ break;
+ }
+
+ msg += " ";
+
+ switch (act.reason)
+ {
+ case RFAIL_SKILLDEP:
+ msg += _("You have not yet reached a high enough lvl!");
+ break;
+ case RFAIL_INSUFHP:
+ msg += _("Insufficient HP!");
+ break;
+ case RFAIL_INSUFSP:
+ msg += _("Insufficient SP!");
+ break;
+ case RFAIL_NOMEMO:
+ msg += _("You have no memos!");
+ break;
+ case RFAIL_SKILLDELAY:
+ msg += _("You cannot do that right now!");
+ break;
+ case RFAIL_ZENY:
+ msg += _("Seems you need more money... ;-)");
+ break;
+ case RFAIL_WEAPON:
+ msg += _("You cannot use this skill with that kind of weapon!");
+ break;
+ case RFAIL_REDGEM:
+ msg += _("You need another red gem!");
+ break;
+ case RFAIL_BLUEGEM:
+ msg += _("You need another blue gem!");
+ break;
+ case RFAIL_OVERWEIGHT:
+ msg += _("You're carrying to much to do this!");
+ break;
+ default:
+ msg += _("Huh? What's that?");
+ break;
+ }
+ }
+ else
+ {
+ switch (act.skill)
+ {
+ case SKILL_WARP :
+ msg = _("Warp failed...");
+ break;
+ case SKILL_STEAL :
+ msg = _("Could not steal anything...");
+ break;
+ case SKILL_ENVENOM :
+ msg = _("Poison had no effect...");
+ break;
+ }
+ }
+
+ return msg;
+}
+
+#endif
+
+void ChatWindow::scroll(int amount)
+{
+ if (!isVisible())
+ return;
+
+ ChannelMap::const_iterator chan = mChannels.find(getFocused());
+ if (chan == mChannels.end())
+ return;
+
+ BrowserBox *browser = chan->second.browser;
+ ScrollArea *scroll = chan->second.scroll;
+
+ int range = scroll->getHeight() / 8 * amount;
+ gcn::Rectangle scr;
+ scr.y = scroll->getVerticalScrollAmount() + range;
+ scr.height = abs(range);
+ browser->showPart(scr);
+}
+
void ChatWindow::keyPressed(gcn::KeyEvent &event)
{
if (event.getKey().getValue() == Key::DOWN &&
@@ -422,11 +962,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;
}
}
@@ -446,23 +989,171 @@ void ChatWindow::setInputText(std::string input_str)
requestChatFocus();
}
-void ChatWindow::addItemText(int itemId, const std::string &item)
+void ChatWindow::addItemText(const std::string &item)
{
std::ostringstream text;
- text << "[@@" << itemId << "|" << item << "@@] ";
+ text << "[" << item << "] ";
mChatInput->setText(mChatInput->getText() + text.str());
requestChatFocus();
}
void ChatWindow::setVisible(bool isVisible)
{
- Window::setVisible(isVisible);
+ Window::setVisible(isVisible);
+
+ /*
+ * For whatever reason, if setVisible is called, the mTmpVisible effect
+ * should be disabled.
+ */
+ mTmpVisible = false;
+}
+
+#ifdef EATHENA_SUPPORT
+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);
+}
+#endif
- /*
- * For whatever reason, if setVisible is called, the mTmpVisible effect
- * should be disabled.
- */
- mTmpVisible = false;
+void ChatWindow::help(const std::string & msg1, const std::string & msg2)
+{
+ chatLog(_("-- Help --"), BY_SERVER);
+ 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(_("/me <message>: Tell something about yourself"), BY_SERVER);
+ chatLog(_("/msg <nick> <message>: Alternate form for /whisper"),
+ BY_SERVER);
+ chatLog(_("/party <command> <params>: Party commands"), 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(_("/w <nick> <message>: Short form for /whisper"), BY_SERVER);
+ chatLog(_("/where: Display map name"), BY_SERVER);
+ chatLog(_("/whisper <nick> <message>: Sends a private <message> "
+ "to <nick>"), BY_SERVER);
+ chatLog(_("/who: Display number of online users"), BY_SERVER);
+ chatLog(_("For more information, type /help <command>"), BY_SERVER);
+ }
+ 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);
+ }
+ else if (msg1 == "clear")
+ {
+ chatLog(_("Command: /clear"), BY_SERVER);
+ chatLog(_("This command clears the chat log of previous chat."),
+ BY_SERVER);
+ }
+ 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);
+ }
+ else if (msg1 == "me")
+ {
+ chatLog(_("Command: /me <msg>"), BY_SERVER);
+ chatLog(_("This command tell others you are (doing) <msg>."),
+ BY_SERVER);
+ }
+#ifdef EATHENA_SUPPORT
+ else if (msg1 == "party")
+ {
+ mParty->help(msg2);
+ }
+#endif
+ 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);
+ }
+ 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);
+ }
+ else if (msg1 == "who")
+ {
+ chatLog(_("Command: /who"), BY_SERVER);
+ chatLog(_("This command displays the number of players currently "
+ "online."), BY_SERVER);
+ }
+ else
+ {
+ chatLog(_("Unknown command."), BY_SERVER);
+ chatLog(_("Type /help for a list of commands."), BY_SERVER);
+ }
}
bool ChatWindow::tabExists(const std::string &tabName)
diff --git a/src/gui/chat.h b/src/gui/chat.h
index 114b389c..bbca76ad 100644
--- a/src/gui/chat.h
+++ b/src/gui/chat.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_CHAT_H
-#define _TMW_CHAT_H
+#ifndef CHAT_H
+#define CHAT_H
#include <list>
#include <string>
@@ -31,25 +31,86 @@
#include "window.h"
-#include "../guichanfwd.h"
-
class BrowserBox;
+class Channel;
+class Recorder;
class ScrollArea;
class TabbedArea;
-class Channel;
class ItemLinkHandler;
+#ifdef EATHENA_SUPPORT
+class Network;
+class Party;
+#endif
enum
{
- BY_GM = 0,
- BY_PLAYER = 1,
- BY_OTHER = 2,
- BY_SERVER = 3,
- BY_CHANNEL = 4,
+ BY_GM,
+#ifdef EATHENA_SUPPORT
+ BY_PARTY,
+#endif
+ BY_PLAYER,
+ BY_OTHER,
+ BY_SERVER,
+ BY_CHANNEL,
+ ACT_WHISPER, // getting whispered at
+ ACT_IS, // equivalent to "/me" on IRC
BY_LOGGER
};
/**
+ * gets in between usernick and message text depending on
+ * message type
+ */
+#define CAT_NORMAL ": "
+#define CAT_IS ""
+#define CAT_WHISPER " whispers: "
+
+#ifdef EATHENA_SUPPORT
+/** job dependend identifiers (?) */
+#define SKILL_BASIC 0x0001
+#define SKILL_WARP 0x001b
+#define SKILL_STEAL 0x0032
+#define SKILL_ENVENOM 0x0034
+
+/** basic skills identifiers */
+#define BSKILL_TRADE 0x0000
+#define BSKILL_EMOTE 0x0001
+#define BSKILL_SIT 0x0002
+#define BSKILL_CREATECHAT 0x0003
+#define BSKILL_JOINPARTY 0x0004
+#define BSKILL_SHOUT 0x0005
+#define BSKILL_PK 0x0006 // ??
+#define BSKILL_SETALLIGN 0x0007 // ??
+
+/** reasons why action failed */
+#define RFAIL_SKILLDEP 0x00
+#define RFAIL_INSUFHP 0x01
+#define RFAIL_INSUFSP 0x02
+#define RFAIL_NOMEMO 0x03
+#define RFAIL_SKILLDELAY 0x04
+#define RFAIL_ZENY 0x05
+#define RFAIL_WEAPON 0x06
+#define RFAIL_REDGEM 0x07
+#define RFAIL_BLUEGEM 0x08
+#define RFAIL_OVERWEIGHT 0x09
+#define RFAIL_GENERIC 0x0a
+
+/** should always be zero if failed */
+#define SKILL_FAILED 0x00
+
+struct CHATSKILL
+{
+ short skill;
+ short bskill;
+ short unused;
+ char success;
+ char reason;
+};
+#endif
+
+#define DEFAULT_CHAT_WINDOW_SCROLL 7 // 1 means `1/8th of the window size'.
+
+/**
* The chat window.
*
* \ingroup Interface
@@ -62,10 +123,14 @@ class ChatWindow : public Window,
/**
* Constructor.
*/
+#ifdef TMWSERV_SUPPORT
ChatWindow();
+#else
+ ChatWindow(Network *network);
+#endif
/**
- *
+ * Destructor: used to write back values to the config file
*/
~ChatWindow();
@@ -75,26 +140,36 @@ class ChatWindow : public Window,
*/
void widgetResized(const gcn::Event &event);
- /**
- * Gets the focused tab's name
- */
- const std::string& getFocused() const;
-
- /**
- * Clear the tab with the given name
- */
- void clearTab(const std::string &tab);
+ void logic();
/**
* Adds a line of text to our message list. Parameters:
*
* @param line Text message.
- * @param own Type of message (usually the owner-type).
+ * @parem own Type of message (usually the owner-type).
* @param channelName which channel to send the message to.
*/
void chatLog(std::string line,
int own = BY_SERVER,
- std::string channelName = "");
+ std::string channelName = "",
+ bool ignoreRecord = false);
+
+#ifdef EATHENA_SUPPORT
+ /**
+ * Calls original chat_log() after processing the packet.
+ */
+ void chatLog(CHATSKILL);
+#endif
+
+ /**
+ * Gets the focused tab's name
+ */
+ const std::string& getFocused() const;
+
+ /**
+ * Clear the tab with the given name
+ */
+ void clearTab(const std::string &tab);
/**
* Performs action.
@@ -111,6 +186,7 @@ class ChatWindow : public Window,
*/
bool isInputFocused();
+#ifdef TMWSERV_SUPPORT
/**
* Determines whether the message is a command or message, then
* sends the given message to the game server to be said, or to the
@@ -135,6 +211,33 @@ class ChatWindow : public Window,
void sendToChannel(short channel,
const std::string &user,
const std::string &msg);
+#else
+ /**
+ * Determines whether to send a command or an ordinary message, then
+ * contructs packets & sends them.
+ *
+ * @param nick The character's name to display in front.
+ * @param msg The message text which is to be send.
+ *
+ * NOTE:
+ * The nickname is required by the server, if not specified
+ * the message may not be sent unless a command was intended
+ * which requires another packet to be constructed! you can
+ * achieve this by putting a slash ("/") infront of the
+ * message followed by the command name and the message.
+ * of course all slash-commands need implemented handler-
+ * routines. ;-)
+ * remember, a line starting with "@" is not a command that needs
+ * to be parsed rather is sent using the normal chat-packet.
+ *
+ * EXAMPLE:
+ * // for an global announcement /- command
+ * chatlog.chat_send("", "/announce Hello to all logged in users!");
+ * // for simple message by a user /- message
+ * chatlog.chat_send("Zaeiru", "Hello to all users on the screen!");
+ */
+ void chatSend(const std::string &nick, std::string msg);
+#endif
/** Called when key is pressed */
void keyPressed(gcn::KeyEvent &event);
@@ -143,7 +246,7 @@ class ChatWindow : public Window,
void setInputText(std::string input_str);
/** Called to add item to chat */
- void addItemText(int itemid, const std::string &item);
+ void addItemText(const std::string &item);
/** Override to reset mTmpVisible */
void setVisible(bool visible);
@@ -151,14 +254,45 @@ class ChatWindow : public Window,
/** Check if tab with that name already exists */
bool tabExists(const std::string &tabName);
- void logic();
+ /**
+ * Scrolls the chat window
+ *
+ * @param amount direction and amount to scroll. Negative numbers scroll
+ * up, positive numbers scroll down. The absolute amount indicates the
+ * amount of 1/8ths of chat window real estate that should be scrolled.
+ */
+ void scroll(int amount);
+
+#ifdef EATHENA_SUPPORT
+ /**
+ * 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);
+#endif
+
+ /**
+ * help implements the /help command
+ *
+ * @param msg1 is the command that the player needs help on
+ * @param msg2 is the sub-command relating to the command
+ */
+ void help(const std::string &msg1, const std::string &msg2);
private:
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+#endif
bool mTmpVisible;
int mItems;
int mItemsKeep;
+ void whisper(const std::string &nick, std::string msg);
+
+ /** One item in the chat log */
struct CHATLOG
{
std::string nick;
@@ -166,6 +300,11 @@ class ChatWindow : public Window,
int own;
};
+#ifdef EATHENA_SUPPORT
+ /** Constructs failed messages for actions */
+ std::string const_msg(CHATSKILL);
+#endif
+
/**
* A structure combining a BrowserBox with its ScrollArea.
*/
@@ -196,6 +335,14 @@ class ChatWindow : public Window,
typedef History::iterator HistoryIterator;
History mHistory; /**< Command history. */
HistoryIterator mCurHist; /**< History iterator. */
+ Recorder *mRecorder; /**< Recording class */
+ bool mReturnToggles; /**< Marks whether <Return> toggles the chat log
+ or not */
+#ifdef EATHENA_SUPPORT
+ char mPartyPrefix; /**< Messages beginning with the prefix are sent to
+ the party */
+ Party *mParty;
+#endif
};
extern ChatWindow *chatWindow;
diff --git a/src/gui/chatinput.cpp b/src/gui/chatinput.cpp
index afe7f037..43f3cde4 100644
--- a/src/gui/chatinput.cpp
+++ b/src/gui/chatinput.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/gui/chatinput.h b/src/gui/chatinput.h
index e04dfa6e..3bc16928 100644
--- a/src/gui/chatinput.h
+++ b/src/gui/chatinput.h
@@ -1,26 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_CHATINPUT_H
-#define _TMW_CHATINPUT_H
+#ifndef CHATINPUT_H
+#define CHATINPUT_H
+
+#include <guichan/focuslistener.hpp>
#include "textfield.h"
diff --git a/src/gui/checkbox.cpp b/src/gui/checkbox.cpp
index 20e24dee..7fa4fa81 100644
--- a/src/gui/checkbox.cpp
+++ b/src/gui/checkbox.cpp
@@ -1,32 +1,34 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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,10 @@ 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);
+ checkBoxNormal->setAlpha(mAlpha);
+ checkBoxChecked->setAlpha(mAlpha);
+ checkBoxDisabled->setAlpha(mAlpha);
+ checkBoxDisabledChecked->setAlpha(mAlpha);
checkBox->decRef();
}
@@ -66,16 +72,25 @@ 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)
+ {
+ 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 839ca97e..20adb43c 100644
--- a/src/gui/checkbox.h
+++ b/src/gui/checkbox.h
@@ -1,28 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_CHECKBOX_H
-#define _TMW_CHECKBOX_H
-
-#include <iosfwd>
+#ifndef CHECKBOX_H
+#define CHECKBOX_H
#include <guichan/widgets/checkbox.hpp>
@@ -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..f9b89857
--- /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/stringutils.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', 0xa08527, _("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(char c, 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(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(char c, int rgb, const std::string &text)
+{
+ int trueRgb = (int) 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..2816cedc
--- /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 COLOR_H
+#define COLOR_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(char c, 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(char c, int r, int g, 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(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(char c, 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(char c, 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 5f2b9cb2..5ad2e26c 100644
--- a/src/gui/confirm_dialog.cpp
+++ b/src/gui/confirm_dialog.cpp
@@ -1,29 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 c9bfca02..8d8c0436 100644
--- a/src/gui/confirm_dialog.h
+++ b/src/gui/confirm_dialog.h
@@ -1,38 +1,41 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_OPTION_DIALOG_H
-#define _TMW_OPTION_DIALOG_H
+#ifndef OPTION_DIALOG_H
+#define OPTION_DIALOG_H
#include <guichan/actionlistener.hpp>
#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,16 @@ 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;
};
#endif
diff --git a/src/gui/connection.cpp b/src/gui/connection.cpp
index f54c9dd5..fbf127de 100644
--- a/src/gui/connection.cpp
+++ b/src/gui/connection.cpp
@@ -1,29 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "connection.h"
-
#include <guichan/widgets/label.hpp>
#include "button.h"
+#include "connection.h"
#include "progressbar.h"
#include "../main.h"
@@ -61,10 +60,10 @@ void ConnectionDialog::action(gcn::ActionEvent const &)
void ConnectionDialog::logic()
{
mProgress += 0.005f;
+
if (mProgress > 1.0f)
- {
mProgress = 0.0f;
- }
+
mProgressBar->setProgress(mProgress);
Window::logic();
}
diff --git a/src/gui/connection.h b/src/gui/connection.h
index 36ccd8a9..0e347266 100644
--- a/src/gui/connection.h
+++ b/src/gui/connection.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_CONNECTION_H
-#define _TMW_CONNECTION_H
+#ifndef CONNECTION_H
+#define CONNECTION_H
#include <guichan/actionlistener.hpp>
diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp
index ab09ec4e..2ed891db 100644
--- a/src/gui/debugwindow.cpp
+++ b/src/gui/debugwindow.cpp
@@ -1,113 +1,102 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 "../game.h"
+#include "widgets/layout.h"
+
#include "../engine.h"
+#include "../game.h"
#include "../particle.h"
#include "../map.h"
-#include "../utils/tostring.h"
+#include "../utils/stringutils.h"
DebugWindow::DebugWindow():
Window("Debug")
{
setWindowName("Debug");
+
setResizable(true);
setCloseButton(true);
setDefaultSize(0, 0, 400, 60);
loadWindowState();
- mFPSLabel = new gcn::Label("[0 FPS]");
- mFPSLabel->setPosition(0,0);
-
+ mFPSLabel = new gcn::Label("0 FPS");
mMusicFileLabel = new gcn::Label("Music: ");
- mMusicFileLabel->setPosition(0, 15);
-
mMapLabel = new gcn::Label("Map: ");
- mMapLabel->setPosition(0, 30);
-
mMiniMapLabel = new gcn::Label("Mini-Map: ");
- mMiniMapLabel->setPosition(0, 45);
-
- mTileMouseLabel = new gcn::Label("[Mouse: 0, 0]");
- mTileMouseLabel->setPosition(200, 0);
+ mTileMouseLabel = new gcn::Label("Mouse: 0, 0");
+ mParticleCountLabel = new gcn::Label("Particle count: 0");
- mParticleCountLabel = new gcn::Label("[Particle count: 0]");
- mParticleCountLabel->setPosition(200, 15);
+ place(0, 0, mFPSLabel);
+ place(3, 0, mTileMouseLabel);
+ place(0, 1, mMusicFileLabel, 2);
+ place(3, 1, mParticleCountLabel);
+ place(0, 2, mMapLabel, 2);
+ place(0, 3, mMiniMapLabel, 2);
- add(mFPSLabel);
- add(mMusicFileLabel);
- add(mMiniMapLabel);
- add(mMapLabel);
- add(mTileMouseLabel);
- add(mParticleCountLabel);
+ reflowLayout(375, 0);
}
-void
-DebugWindow::logic()
+void DebugWindow::logic()
{
// Get the current mouse position
int mouseX, mouseY;
SDL_GetMouseState(&mouseX, &mouseY);
- int mouseTileX = mouseX + viewport->getCameraX();
- int mouseTileY = mouseY + viewport->getCameraY();
+ int mouseTileX = mouseX / 32 + viewport->getCameraX();
+ int mouseTileY = mouseY / 32 + viewport->getCameraY();
- mFPSLabel->setCaption("[" + toString(fps) + " FPS]");
+ mFPSLabel->setCaption(toString(fps) + " FPS");
mFPSLabel->adjustSize();
- mTileMouseLabel->setCaption("[Mouse: " +
- toString(mouseTileX) + ", " + toString(mouseTileY) + "]");
+ mTileMouseLabel->setCaption("Mouse: " +
+ toString(mouseTileX) + ", " + toString(mouseTileY));
mTileMouseLabel->adjustSize();
Map *currentMap = engine->getCurrentMap();
- if (currentMap != NULL)
+ if (currentMap)
{
const std::string music =
- " [Music: " + currentMap->getProperty("music") + "]";
+ "Music: " + currentMap->getProperty("music");
mMusicFileLabel->setCaption(music);
mMusicFileLabel->adjustSize();
const std::string minimap =
- " [MiniMap: " + currentMap->getProperty("minimap") + "]";
+ "MiniMap: " + currentMap->getProperty("minimap");
mMiniMapLabel->setCaption(minimap);
mMiniMapLabel->adjustSize();
const std::string map =
- " [Map: " + currentMap->getProperty("_filename") + "]";
+ "Map: " + currentMap->getProperty("_filename");
mMapLabel->setCaption(map);
mMapLabel->adjustSize();
}
- mParticleCountLabel->setCaption("[Particle count: " +
- toString(Particle::particleCount)
- +"]");
+ mParticleCountLabel->setCaption("Particle count: " +
+ toString(Particle::particleCount));
mParticleCountLabel->adjustSize();
}
diff --git a/src/gui/debugwindow.h b/src/gui/debugwindow.h
index 8d8b7822..e089de27 100644
--- a/src/gui/debugwindow.h
+++ b/src/gui/debugwindow.h
@@ -1,35 +1,31 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_DEBUGWINDOW_H
-#define _TMW_DEBUGWINDOW_H
-
-#include <iosfwd>
+#ifndef DEBUGWINDOW_H
+#define DEBUGWINDOW_H
#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..e22b031b
--- /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/stringutils.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..a0739723
--- /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/stringutils.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..48635720
--- /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/stringutils.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/emotewindow.h b/src/gui/emotewindow.h
new file mode 100644
index 00000000..8af24a7b
--- /dev/null
+++ b/src/gui/emotewindow.h
@@ -0,0 +1,66 @@
+/*
+ * 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 EMOTEWINDOW_H
+#define EMOTEWINDOW_H
+
+#include <guichan/actionlistener.hpp>
+#include <guichan/selectionlistener.hpp>
+
+#include "window.h"
+
+class EmoteContainer;
+class TextBox;
+
+/**
+ * Emote dialog.
+ *
+ * \ingroup Interface
+ */
+class EmoteWindow : public Window, gcn::ActionListener,
+ gcn::SelectionListener
+{
+ public:
+ /**
+ * Constructor.
+ */
+ EmoteWindow();
+
+ /**
+ * Called when receiving actions from the widgets.
+ */
+ void action(const gcn::ActionEvent &event);
+
+ /**
+ * Returns the selected item.
+ */
+ int getSelectedEmote() const;
+
+ private:
+ EmoteContainer *mEmotes;
+
+ gcn::Button *mUseButton;
+ gcn::ScrollArea *mEmoteScroll;
+};
+
+extern EmoteWindow *emoteWindow;
+
+#endif
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index 6848b4d8..a44ae3ec 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -1,73 +1,100 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define BOX_WIDTH 36
#define BOX_HEIGHT 36
-#include "equipmentwindow.h"
+#include <guichan/font.hpp>
#include "button.h"
+#include "equipmentwindow.h"
+#include "itempopup.h"
+#include "playerbox.h"
+#include "viewport.h"
+#include "../equipment.h"
#include "../graphics.h"
+#include "../inventory.h"
#include "../item.h"
#include "../localplayer.h"
#include "../resources/image.h"
+#include "../resources/iteminfo.h"
#include "../resources/resourcemanager.h"
#include "../utils/gettext.h"
+#include "../utils/stringutils.h"
// Positions of the boxes, 2nd dimension is X and Y respectively.
static const int boxPosition[][2] = {
- {90, 100}, // EQUIP_TORSO_SLOT
- {135, 60}, // EQUIP_ARMS_SLOT
- {90, 10}, // EQUIP_HEAD_SLOT
- {90, 145}, // EQUIP_LEGS_SLOT
- {90, 190}, // EQUIP_FEET_SLOT
- {35, 105}, // EQUIP_RING1_SLOT
- {145, 105}, // EQUIP_RING2_SLOT
- {90, 55}, // EQUIP_NECKLACE_SLOT
- {20, 150}, // EQUIP_FIGHT1_SLOT
- {160, 150}, // EQUIP_FIGHT2_SLOT
- {45, 60} // EQUIP_PROJECTILE_SLOT
+ {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
};
+#ifdef TMWSERV_SUPPORT
EquipmentWindow::EquipmentWindow(Equipment *equipment):
+#else
+EquipmentWindow::EquipmentWindow():
+#endif
Window(_("Equipment")),
+#ifdef TMWSERV_SUPPORT
mEquipment(equipment),
+#endif
mBackground(NULL),
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, 195, 216, 260);
+ 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);
+#ifdef TMWSERV_SUPPORT
for (int i = 0; i < EQUIPMENT_SIZE; i++)
+#else
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
+#endif
{
mEquipBox[i].posX = boxPosition[i][0] + getPadding();
mEquipBox[i].posY = boxPosition[i][1] + getTitleBarHeight();
@@ -76,11 +103,17 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment):
ResourceManager *resman = ResourceManager::getInstance();
mBackground = resman->getImage("graphics/gui/equip_bg.png");
mBackground->setAlpha(0.3);
+
+#ifdef EATHENA_SUPPORT
+ mEquipment = player_node->mEquipment.get();
+ mInventory = player_node->getInventory();
+#endif
}
EquipmentWindow::~EquipmentWindow()
{
mBackground->decRef();
+ delete mItemPopup;
delete mUnequip;
}
@@ -91,21 +124,36 @@ void EquipmentWindow::draw(gcn::Graphics *graphics)
Graphics *g = static_cast<Graphics*>(graphics);
- if (mBackground)
- {
- g->drawImage(mBackground, getPadding() + 10, 0);
- }
-
Window::drawChildren(graphics);
+#ifdef TMWSERV_SUPPORT
for (int i = 0; i < EQUIPMENT_SIZE; i++)
+#else
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
+#endif
{
+#ifdef TMWSERV_SUPPORT
Item *item = mEquipment->getEquipment(i);
+#else
+ Item *item = (i != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(i)) :
+ mInventory->getItem(mEquipment->getArrows());
+#endif
if (item)
{
// Draw Item.
Image *image = item->getImage();
g->drawImage(image, mEquipBox[i].posX, mEquipBox[i].posY);
+#ifdef EATHENA_SUPPORT
+ 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);
+ }
+#endif
}
if (i == mSelected)
@@ -118,6 +166,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics)
// 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));
@@ -128,11 +177,43 @@ void EquipmentWindow::action(const gcn::ActionEvent &event)
{
if (event.getId() == "unequip" && mSelected > -1)
{
+#ifdef TMWSERV_SUPPORT
player_node->unequipItem(mSelected);
+#else
+ Item* item = (mSelected != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(mSelected)) :
+ mInventory->getItem(mEquipment->getArrows());
+ player_node->unequipItem(item);
+#endif
mSelected = -1;
}
}
+Item* EquipmentWindow::getItem(int x, int y) const
+{
+#ifdef TMWSERV_SUPPORT
+ for (int i = 0; i < EQUIPMENT_SIZE; i++)
+#else
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
+#endif
+ {
+ gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT);
+
+ if (tRect.isPointInRect(x, y))
+ {
+#ifdef TMWSERV_SUPPORT
+ return mEquipment->getEquipment(i);
+#else
+ return (i != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(i)) :
+ mInventory->getItem(mEquipment->getArrows());
+#endif
+ }
+ }
+ return NULL;
+}
+
void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent)
{
Window::mousePressed(mouseEvent);
@@ -140,17 +221,77 @@ void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent)
const int x = mouseEvent.getX();
const int y = mouseEvent.getY();
- // Checks if any of the presses were in the equip boxes.
- for (int i = 0; i < EQUIPMENT_SIZE; i++)
+ Item* item;
+
+ if (mouseEvent.getButton() == gcn::MouseEvent::LEFT)
{
- gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY,
- BOX_WIDTH, BOX_HEIGHT);
- if (tRect.isPointInRect(x, y))
+ // Checks if any of the presses were in the equip boxes.
+#ifdef TMWSERV_SUPPORT
+ for (int i = 0; i < EQUIPMENT_SIZE; i++)
+#else
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
+#endif
{
- if (mEquipment->getEquipment(i))
+#ifdef TMWSERV_SUPPORT
+ item = mEquipment->getEquipment(i);
+#else
+ item = (i != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(i)) :
+ mInventory->getItem(mEquipment->getArrows());
+#endif
+ gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT);
+
+ if (tRect.isPointInRect(x, y))
{
- mSelected = i;
+ 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
+ {
+ mItemPopup->setVisible(false);
+ }
+}
+
+// Hide ItemTooltip
+void EquipmentWindow::mouseExited(gcn::MouseEvent &event)
+{
+ mItemPopup->setVisible(false);
}
diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h
index b6d2e2f4..7f7150ff 100644
--- a/src/gui/equipmentwindow.h
+++ b/src/gui/equipmentwindow.h
@@ -1,35 +1,37 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_EQUIPMENT_H
-#define _TMW_EQUIPMENT_H
-
-#include "window.h"
+#ifndef EQUIPMENTWINDOW_H
+#define EQUIPMENTWINDOW_H
#include <guichan/actionlistener.hpp>
-#include "../equipment.h"
+#include "window.h"
class Equipment;
class Image;
+class Inventory;
+class Item;
+class ItemPopup;
+class PlayerBox;
/**
* Equipment box.
@@ -51,7 +53,11 @@ class EquipmentWindow : public Window, public gcn::ActionListener
/**
* Constructor.
*/
+#ifdef TMWSERV_SUPPORT
EquipmentWindow(Equipment *equipment);
+#else
+ EquipmentWindow();
+#endif
/**
* Destructor.
@@ -67,6 +73,7 @@ class EquipmentWindow : public Window, public gcn::ActionListener
void mousePressed(gcn::MouseEvent& mouseEvent);
+#ifdef TMWSERV_SUPPORT
enum{
// Equipment rules:
EQUIP_TORSO_SLOT = 0,
@@ -79,15 +86,46 @@ class EquipmentWindow : public Window, public gcn::ActionListener
EQUIP_NECKLACE_SLOT = 7,
EQUIP_FIGHT1_SLOT = 8,
EQUIP_FIGHT2_SLOT = 9,
- EQUIP_PROJECTILE_SLOT = 10
+ EQUIP_PROJECTILE_SLOT = 10,
+ EQUIP_VECTOREND
};
+#else
+ 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
+ };
+#endif
+
private:
+ void mouseExited(gcn::MouseEvent &event);
+ void mouseMoved(gcn::MouseEvent &event);
+
+ Item* getItem(int x, int y) const;
+
Equipment *mEquipment;
- gcn::Button *mUnequip; /**< Button for unequipping. */
+#ifdef EATHENA_SUPPORT
+ Inventory *mInventory;
+#endif
+ gcn::Button *mUnequip; /**< Button for unequipping. */
Image *mBackground; /**< Background Image. */
- EquipBox mEquipBox[EQUIPMENT_SIZE]; /**< Equipment Boxes. */
+ EquipBox mEquipBox[EQUIP_VECTOREND]; /**< Equipment Boxes. */
+
+ ItemPopup *mItemPopup;
+
+ PlayerBox *mPlayerBox;
- int mSelected; /**< Index of selected item. */
+ int mSelected; /**< Index of selected item. */
};
extern EquipmentWindow *equipmentWindow;
diff --git a/src/gui/focushandler.cpp b/src/gui/focushandler.cpp
index 1bda568e..b9cfd789 100644
--- a/src/gui/focushandler.cpp
+++ b/src/gui/focushandler.cpp
@@ -1,33 +1,32 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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 a5218485..b0639bd8 100644
--- a/src/gui/focushandler.h
+++ b/src/gui/focushandler.h
@@ -1,33 +1,31 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_FOCUSHANDLER_H
-#define _TMW_FOCUSHANDLER_H
+#ifndef FOCUSHANDLER_H
+#define FOCUSHANDLER_H
#include <list>
#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/gccontainer.cpp b/src/gui/gccontainer.cpp
index ec3c8a5c..8325ccd4 100644
--- a/src/gui/gccontainer.cpp
+++ b/src/gui/gccontainer.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/gui/gccontainer.h b/src/gui/gccontainer.h
index cc7c9336..da584a42 100644
--- a/src/gui/gccontainer.h
+++ b/src/gui/gccontainer.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_GUI_GCCONTAINER_H
-#define _TMW_GUI_GCCONTAINER_H
+#ifndef GUI_GCCONTAINER_H
+#define GUI_GCCONTAINER_H
#include <list>
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index dc6306b4..1ef0219a 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -1,31 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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,20 +38,21 @@
#include "../resources/image.h"
#include "../resources/imageset.h"
-#include "../resources/resourcemanager.h"
#include "../resources/imageloader.h"
+#include "../resources/resourcemanager.h"
// Guichan stuff
-Gui *gui;
-Viewport *viewport; /**< Viewport on the map. */
-SDLInput *guiInput;
+Gui *gui = 0;
+Viewport *viewport = 0; /**< Viewport on the map. */
+SDLInput *guiInput = 0;
// Fonts used in showing hits
-gcn::Font *hitRedFont;
-gcn::Font *hitBlueFont;
-gcn::Font *hitYellowFont;
-// Font used to display speech and player names
-gcn::Font *speechFont;
+gcn::Font *hitRedFont = 0;
+gcn::Font *hitBlueFont = 0;
+gcn::Font *hitYellowFont = 0;
+
+// Bolded font
+gcn::Font *boldFont = 0;
class GuiConfigListener : public ConfigListener
{
@@ -63,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);
}
@@ -96,7 +97,7 @@ Gui::Gui(Graphics *graphics):
mFocusHandler = new FocusHandler;
// Initialize top GUI widget
- WindowContainer *guiTop = new WindowContainer();
+ WindowContainer *guiTop = new WindowContainer;
guiTop->setDimension(gcn::Rectangle(0, 0,
graphics->getWidth(), graphics->getHeight()));
guiTop->setOpaque(false);
@@ -107,35 +108,48 @@ Gui::Gui(Graphics *graphics):
// Set global font
std::string path = resman->getPath(
- branding.getValue("guiFont","fonts/dejavusans.ttf"));
- if (!path.empty())
+ branding.getValue("font", "fonts/dejavusans.ttf"));
+ try
+ {
+ const int fontSize = (int)config.getValue("fontSize", 11);
+ mGuiFont = new TrueTypeFont(path, fontSize);
+ }
+ catch (gcn::Exception e)
{
- mGuiFont = new TrueTypeFont(path.c_str(), 11);
+ logger->error(std::string("Unable to load dejavusans.ttf: ")
+ + e.getMessage());
}
- // Set speech font
+ // Set bold font
path = resman->getPath(
- branding.getValue("speechFont","fonts/dejavusans.ttf"));
- if (!path.empty())
+ branding.getValue("boldFont", "fonts/dejavusans.ttf"));
+ try
{
- speechFont = new TrueTypeFont(path.c_str(), 11);
+ const int fontSize = (int)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 ");
}
catch (gcn::Exception e)
{
- logger->log("Unable to load colored hits' fonts: %s", e.getMessage().c_str());
- throw;
+ logger->error(std::string("Unable to load colored hits' fonts: ")
+ + e.getMessage());
}
// Initialize mouse cursor and listen for changes to the option
@@ -144,7 +158,7 @@ Gui::Gui(Graphics *graphics):
config.addListener("customcursor", mConfigListener);
// Create the viewport
- viewport = new Viewport();
+ viewport = new Viewport;
viewport->setDimension(gcn::Rectangle(0, 0,
graphics->getWidth(), graphics->getHeight()));
guiTop->add(viewport);
@@ -164,7 +178,7 @@ Gui::~Gui()
mMouseCursors->decRef();
delete mGuiFont;
- delete speechFont;
+ delete boldFont;
delete viewport;
delete getTop();
@@ -174,12 +188,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();
}
@@ -224,9 +239,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
{
@@ -234,7 +248,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 7d390df9..5c0c24f7 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -1,33 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_GUI
-#define _TMW_GUI
+#ifndef GUI
+#define GUI
#include <guichan/gui.hpp>
#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 */
/**
@@ -124,9 +123,10 @@ extern SDLInput *guiInput; /**< GUI input */
extern gcn::Font *hitRedFont;
extern gcn::Font *hitBlueFont;
extern gcn::Font *hitYellowFont;
+
/**
- * Font used to display speech and player names
+ * Bolded text font
*/
-extern gcn::Font *speechFont;
+extern gcn::Font *boldFont;
#endif
diff --git a/src/gui/hbox.cpp b/src/gui/hbox.cpp
deleted file mode 100644
index 020e85c6..00000000
--- a/src/gui/hbox.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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 "hbox.h"
-
-void HBox::draw(gcn::Graphics *graphics)
-{
- int widgetCount = mWidgets.size();
- int childHeight = getHeight();
- if (widgetCount == 0)
- return;
- int childWidth = getWidth() / widgetCount;
-
- int i = 0;
- for (WidgetIterator w = mWidgets.begin(); w != mWidgets.end(); w++) {
- (*w)->setPosition(childWidth * i - padding, 0);
- (*w)->setSize(childWidth, childHeight);
- i++;
- }
- gcn::Container::draw(graphics);
-}
diff --git a/src/gui/help.cpp b/src/gui/help.cpp
index 290679b9..30c6a9c4 100644
--- a/src/gui/help.cpp
+++ b/src/gui/help.cpp
@@ -1,42 +1,48 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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"
+
HelpWindow::HelpWindow():
- Window("Help")
+ Window(_("Help"))
{
+ setMinWidth(300);
+ setMinHeight(250);
setContentSize(455, 350);
setWindowName("Help");
+ setResizable(true);
- mBrowserBox = new BrowserBox();
+ mBrowserBox = new BrowserBox;
mBrowserBox->setOpaque(false);
mScrollArea = new ScrollArea(mBrowserBox);
- Button *okButton = new Button("Close", "close", this);
+ Button *okButton = new Button(_("Close"), "close", this);
mScrollArea->setDimension(gcn::Rectangle(
5, 5, 445, 335 - okButton->getHeight()));
@@ -46,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 053df723..98e3aa67 100644
--- a/src/gui/help.h
+++ b/src/gui/help.h
@@ -1,33 +1,31 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_HELP_H
-#define _TMW_HELP_H
+#ifndef HELP_H
+#define HELP_H
#include <guichan/actionlistener.hpp>
-#include "window.h"
#include "linkhandler.h"
-
-#include "../guichanfwd.h"
+#include "window.h"
class BrowserBox;
diff --git a/src/gui/inttextbox.cpp b/src/gui/inttextbox.cpp
deleted file mode 100644
index 644601cf..00000000
--- a/src/gui/inttextbox.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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 "inttextbox.h"
-
-#include "sdlinput.h"
-
-#include "../utils/tostring.h"
-
-IntTextBox::IntTextBox(int i):
- mValue(i)
-{
-}
-
-void
-IntTextBox::keyPressed(gcn::KeyEvent &event)
-{
- const gcn::Key &key = event.getKey();
-
- if (key.getValue() == Key::BACKSPACE ||
- key.getValue() == Key::DELETE)
- {
- setText(std::string());
- event.consume();
- }
-
- if (!key.isNumber()) return;
- TextField::keyPressed(event);
-
- std::istringstream s(getText());
- int i;
- s >> i;
- setInt(i);
- distributeActionEvent();
-}
-
-void IntTextBox::setRange(int min, int max)
-{
- mMin = min;
- mMax = max;
-}
-
-int IntTextBox::getInt()
-{
- return getText().empty() ? mMin : mValue;
-}
-
-void IntTextBox::setInt(int i)
-{
- if (i >= mMin && i <= mMax)
- mValue = i;
-
- const std::string valStr = toString(mValue);
- setText(valStr);
- setCaretPosition(valStr.length() + 1);
-}
diff --git a/src/gui/inttextfield.cpp b/src/gui/inttextfield.cpp
new file mode 100644
index 00000000..d3fe448b
--- /dev/null
+++ b/src/gui/inttextfield.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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 "inttextfield.h"
+#include "sdlinput.h"
+
+#include "../utils/stringutils.h"
+
+IntTextField::IntTextField(int def):
+ TextField(toString(def)),
+ mDefault(def),
+ mValue(def)
+{
+}
+
+void IntTextField::keyPressed(gcn::KeyEvent &event)
+{
+ const gcn::Key &key = event.getKey();
+
+ if (key.getValue() == Key::BACKSPACE ||
+ key.getValue() == Key::DELETE)
+ {
+ setText(std::string());
+ event.consume();
+ }
+
+ if (!key.isNumber())
+ return;
+
+ TextField::keyPressed(event);
+
+ std::istringstream s(getText());
+ int i;
+ s >> i;
+ setValue(i);
+}
+
+void IntTextField::setRange(int min, int max)
+{
+ mMin = min;
+ mMax = max;
+
+ if (mValue < mMin)
+ mValue = mMin;
+ else if (mValue > mMax)
+ mValue = mMax;
+
+ if (mDefault < mMin)
+ mDefault = mMin;
+ else if (mDefault > mMax)
+ mDefault = mMax;
+}
+
+int IntTextField::getValue()
+{
+ return getText().empty() ? mMin : mValue;
+}
+
+void IntTextField::setValue(int i)
+{
+ if (i < mMin)
+ mValue = mMin;
+ else if (i > mMax)
+ mValue = mMax;
+ else
+ mValue = i;
+
+ const std::string valStr = toString(mValue);
+ setText(valStr);
+ setCaretPosition(valStr.length() + 1);
+}
+
+void IntTextField::setDefaultValue(int value)
+{
+ if (value < mMin)
+ mDefault = mMin;
+ else if (value > mMax)
+ mDefault = mMax;
+ else
+ mDefault = value;
+}
+
+void IntTextField::reset()
+{
+ setValue(mDefault);
+}
diff --git a/src/gui/inttextbox.h b/src/gui/inttextfield.h
index 8dad0c39..ec768bea 100644
--- a/src/gui/inttextbox.h
+++ b/src/gui/inttextfield.h
@@ -1,39 +1,39 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef INTTEXTBOX_H
-#define INTTEXTBOX_H
+#ifndef INTTEXTFIELD_H
+#define INTTEXTFIELD_H
#include "textfield.h"
/**
* TextBox which only accepts numbers as input.
*/
-class IntTextBox : public TextField
+class IntTextField : public TextField
{
public:
/**
- * Constructor, sets initial value.
+ * Constructor, sets default value.
*/
- IntTextBox(int value=0);
+ IntTextField(int def = 0);
/**
* Sets the minimum and maximum values of the text box.
@@ -43,22 +43,32 @@ class IntTextBox : public TextField
/**
* Returns the value in the text box.
*/
- int getInt();
+ int getValue();
+
+ /**
+ * Reset the field to the default value.
+ */
+ void reset();
/**
* Set the value of the text box to the specified value.
*/
- void setInt(int value);
+ void setValue(int value);
+
+ /**
+ * Set the default value of the text box to the specified value.
+ */
+ void setDefaultValue(int value);
/**
* Responds to key presses.
*/
- void
- keyPressed(gcn::KeyEvent &event);
+ void keyPressed(gcn::KeyEvent &event);
private:
int mMin; /**< Minimum value */
int mMax; /**< Maximum value */
+ int mDefault; /**< Default value */
int mValue; /**< Current value */
};
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index b4a96394..d18490a4 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -1,56 +1,57 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 <guichan/widgets/checkbox.hpp>
-#include <guichan/widgets/textbox.hpp>
#include "button.h"
-#include "gui.h"
+#include "inventorywindow.h"
#include "item_amount.h"
#include "itemcontainer.h"
-#include "itempopup.h"
+#include "progressbar.h"
#include "scrollarea.h"
#include "sdlinput.h"
#include "viewport.h"
#include "widgets/layout.h"
+#include "../inventory.h"
#include "../item.h"
#include "../localplayer.h"
#include "../log.h"
+#include "../units.h"
#include "../resources/iteminfo.h"
#include "../utils/gettext.h"
+#include "../utils/stringutils.h"
#include "../utils/strprintf.h"
-InventoryWindow::InventoryWindow():
+InventoryWindow::InventoryWindow(int invSize):
Window(_("Inventory")),
+ mMaxSlots(invSize),
mSplit(false),
mItemDesc(false)
{
@@ -65,28 +66,67 @@ InventoryWindow::InventoryWindow():
setDefaultSize(115, 30, 375, 283);
addKeyListener(this);
- 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);
+#ifdef TMWSERV_SUPPORT
mSplitButton = new Button(_("Split"), "split", this);
+#endif
- mItems = new ItemContainer(player_node->mInventory, 10, 5);
+#ifdef TMWSERV_SUPPORT
+ mItems = new ItemContainer(player_node->getInventory(), 10, 5);
+#else
+ mItems = new ItemContainer(player_node->getInventory(), 10, 5, 2);
+#endif
mItems->addSelectionListener(this);
mInvenScroll = new ScrollArea(mItems);
+ mInvenScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+
+ mTotalWeight = -1;
+ mMaxWeight = -1;
+ 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, 100).setPadding(3);
+ place(0, 2, mUseButton);
+ place(1, 2, mDropButton);
+#ifdef TMWSERV_SUPPORT
+ place(2, 2, mSplitButton);
+#endif
- place(0, 0, mInvenScroll, 100).setPadding(3);
- place(0, 1, mUseButton);
- place(1, 1, mDropButton);
- place(2, 1, mSplitButton);
Layout &layout = getLayout();
- layout.setColWidth(0, 48);
- layout.setColWidth(1, 48);
- layout.setColWidth(2, 48);
layout.setRowHeight(0, Layout::AUTO_SET);
loadWindowState();
}
+InventoryWindow::~InventoryWindow()
+{
+ delete mItems;
+}
+
void InventoryWindow::logic()
{
Window::logic();
@@ -95,24 +135,69 @@ void InventoryWindow::logic()
// redesign of InventoryWindow and ItemContainer probably.
updateButtons();
- // Update weight information
- // mWeightLabel->setCaption(strprintf(_("Total Weight: %d - Maximum Weight: %d"), player_node->getTotalWeight(), player_node->getMaxWeight()));
+ if (mMaxWeight != player_node->getMaxWeight() ||
+ mTotalWeight != player_node->getTotalWeight() ||
+ mUsedSlots != toString(player_node->getInventory()->getNumberOfSlotsUsed()))
+ {
+ mTotalWeight = player_node->getTotalWeight();
+ mMaxWeight = player_node->getMaxWeight();
+ mUsedSlots = toString(player_node->getInventory()->getNumberOfSlotsUsed());
+
+ // Weight Bar coloration
+ if (int(player_node->getTotalWeight()) < int(player_node->getMaxWeight() / 3))
+ {
+ mWeightBar->setColor(0, 0, 255); // Blue
+ }
+ else if (int(player_node->getTotalWeight()) <
+ int((player_node->getMaxWeight() / 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->getTotalWeight() /
+ player_node->getMaxWeight());
+
+ mSlotsBar->setText(strprintf("%s/%d", mUsedSlots.c_str(), mMaxSlots));
+ mWeightBar->setText(strprintf("%s/%s",
+ Units::formatWeight(mTotalWeight).c_str(),
+ Units::formatWeight(mMaxWeight).c_str()));
+ }
}
void InventoryWindow::action(const gcn::ActionEvent &event)
{
- Item *item = mItems->getItem();
+ Item *item = mItems->getSelectedItem();
+
if (!item)
return;
if (event.getId() == "use")
{
+#ifdef TMWSERV_SUPPORT
if (item->isEquipment()) {
player_node->equipItem(item);
}
else {
player_node->useItem(item->getInvIndex());
}
+#else
+ if (item->isEquipment())
+ {
+ if (item->isEquipped())
+ player_node->unequipItem(item);
+ else
+ player_node->equipItem(item);
+ }
+ else
+ player_node->useItem(item);
+#endif
}
else if (event.getId() == "drop")
{
@@ -134,18 +219,9 @@ void InventoryWindow::action(const gcn::ActionEvent &event)
}
}
-void InventoryWindow::valueChanged(const gcn::SelectionEvent &event)
+Item* InventoryWindow::getSelectedItem() const
{
- Item *item = mItems->getItem();
-
- if (mSplit)
- {
- if (item && !item->isEquipment() && item->getQuantity() > 1)
- {
- mSplit = false;
- new ItemAmountWindow(AMOUNT_ITEM_SPLIT, this, item, (item->getQuantity() - 1));
- }
- }
+ return mItems->getSelectedItem();
}
void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
@@ -154,7 +230,7 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
if (event.getButton() == gcn::MouseEvent::RIGHT)
{
- Item *item = mItems->getItem();
+ Item *item = mItems->getSelectedItem();
if (!item)
return;
@@ -168,31 +244,7 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
}
}
-void InventoryWindow::updateButtons()
-{
- Item *item = mItems->getItem();
-
- if (item && item->isEquipment()) {
- mUseButton->setCaption(_("Equip"));
- }
- else {
- mUseButton->setCaption(_("Use"));
- }
- mUseButton->setEnabled(!!item);
- mDropButton->setEnabled(!!item);
- if (item && !item->isEquipment() && item->getQuantity() > 1) {
- mSplitButton->setEnabled(true);
- }
- else {
- mSplitButton->setEnabled(false);
- }
-}
-
-Item* InventoryWindow::getItem()
-{
- return mItems->getItem();
-}
-
+#ifdef TMWSERV_SUPPORT
void InventoryWindow::keyPressed(gcn::KeyEvent &event)
{
switch (event.getKey().getValue())
@@ -214,3 +266,49 @@ void InventoryWindow::keyReleased(gcn::KeyEvent &event)
break;
}
}
+#endif
+
+void InventoryWindow::valueChanged(const gcn::SelectionEvent &event)
+{
+ if (mSplit)
+ {
+ Item *item = mItems->getSelectedItem();
+
+ if (item && !item->isEquipment() && item->getQuantity() > 1)
+ {
+ mSplit = false;
+ new ItemAmountWindow(AMOUNT_ITEM_SPLIT, this, item, (item->getQuantity() - 1));
+ }
+ }
+}
+
+void InventoryWindow::updateButtons()
+{
+ const Item *selectedItem = mItems->getSelectedItem();
+
+ if (selectedItem && selectedItem->isEquipment())
+ {
+#ifdef EATHENA_SUPPORT
+ if (selectedItem->isEquipped())
+ mUseButton->setCaption(_("Unequip"));
+ else
+#endif
+ mUseButton->setCaption(_("Equip"));
+ }
+ else
+ mUseButton->setCaption(_("Use"));
+
+ mUseButton->setEnabled(selectedItem != 0);
+ mDropButton->setEnabled(selectedItem != 0);
+
+#ifdef TMWSERV_SUPPORT
+ if (selectedItem && !selectedItem->isEquipment() &&
+ selectedItem->getQuantity() > 1)
+ {
+ mSplitButton->setEnabled(true);
+ }
+ else {
+ mSplitButton->setEnabled(false);
+ }
+#endif
+}
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index 9d342c83..6a51c66d 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -1,38 +1,39 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_INVENTORYWINDOW_H
-#define _TMW_INVENTORYWINDOW_H
+#ifndef INVENTORYWINDOW_H
+#define INVENTORYWINDOW_H
#include <guichan/actionlistener.hpp>
-#include <guichan/keylistener.hpp>
#include <guichan/selectionlistener.hpp>
-#include <guichan/widgets/checkbox.hpp>
+#include <guichan/keylistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
+#include "../localplayer.h"
class Item;
class ItemContainer;
+class ProgressBar;
+class TextBox;
/**
* Inventory dialog.
@@ -48,7 +49,16 @@ class InventoryWindow : public Window,
/**
* Constructor.
*/
- InventoryWindow();
+#ifdef TMWSERV_SUPPORT
+ InventoryWindow(int invSize = (INVENTORY_SIZE));
+#else
+ InventoryWindow(int invSize = (INVENTORY_SIZE - 2));
+#endif
+
+ /**
+ * Destructor.
+ */
+ ~InventoryWindow();
/**
* Logic (updates buttons and weight information).
@@ -61,10 +71,16 @@ class InventoryWindow : public Window,
void action(const gcn::ActionEvent &event);
/**
+ * Returns the selected item.
+ */
+ Item* getSelectedItem() const;
+
+ /**
* Handles the mouse clicks.
*/
void mouseClicked(gcn::MouseEvent &event);
+#ifdef TMWSERV_SUPPORT
/**
* Handles the key presses.
*/
@@ -74,8 +90,7 @@ class InventoryWindow : public Window,
* Handles the key releases.
*/
void keyReleased(gcn::KeyEvent &event);
-
- Item* getItem();
+#endif
/**
* Updates labels to currently selected item.
@@ -87,13 +102,25 @@ class InventoryWindow : public Window,
ItemContainer *mItems;
- /**< Use, Drop, Split Item Buttons. */
- gcn::Button *mUseButton, *mDropButton, *mSplitButton;
-
+ std::string mWeight;
+ std::string mSlots;
+ std::string mUsedSlots;
+ int mTotalWeight, mMaxWeight;
+ gcn::Button *mUseButton;
+ gcn::Button *mDropButton;
+#ifdef TMWSERV_SUPPORT
+ gcn::Button *mSplitButton;
+#endif
gcn::ScrollArea *mInvenScroll; /**< Inventory Scroll Area. */
+ gcn::Label *mWeightLabel;
+ gcn::Label *mSlotsLabel;
- bool mSplit;
+ ProgressBar *mWeightBar;
+ ProgressBar *mSlotsBar;
+ int mMaxSlots;
+
+ bool mSplit;
bool mItemDesc;
};
diff --git a/src/gui/item_amount.cpp b/src/gui/item_amount.cpp
index cae681d4..3bd388f4 100644
--- a/src/gui/item_amount.cpp
+++ b/src/gui/item_amount.cpp
@@ -1,28 +1,27 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "item_amount.h"
-
#include "button.h"
-#include "inttextbox.h"
+#include "inttextfield.h"
+#include "item_amount.h"
#include "slider.h"
#include "trade.h"
@@ -44,11 +43,11 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item,
}
// Integer field
- mItemAmountTextBox = new IntTextBox(1);
- mItemAmountTextBox->setRange(1, maxRange);
- mItemAmountTextBox->setWidth(30);
- mItemAmountTextBox->setActionEventId("Dummy");
- mItemAmountTextBox->addActionListener(this);
+ mItemAmountTextField = new IntTextField(1);
+ mItemAmountTextField->setRange(1, maxRange);
+ mItemAmountTextField->setWidth(30);
+ mItemAmountTextField->setActionEventId("Dummy");
+ mItemAmountTextField->addActionListener(this);
// Slider
mItemAmountSlide = new Slider(1.0, maxRange);
@@ -66,7 +65,7 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item,
// Set positions
place(0, 0, minusButton);
- place(1, 0, mItemAmountTextBox).setPadding(2);
+ place(1, 0, mItemAmountTextField).setPadding(2);
place(2, 0, plusButton);
place(0, 1, mItemAmountSlide, 6);
place(4, 2, okButton);
@@ -75,7 +74,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");
@@ -98,12 +98,12 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item,
void ItemAmountWindow::resetAmount()
{
- mItemAmountTextBox->setInt(1);
+ mItemAmountTextField->setValue(1);
}
void ItemAmountWindow::action(const gcn::ActionEvent &event)
{
- int amount = mItemAmountTextBox->getInt();
+ int amount = mItemAmountTextField->getValue();
if (event.getId() == "Cancel")
{
@@ -123,19 +123,21 @@ void ItemAmountWindow::action(const gcn::ActionEvent &event)
}
else if (event.getId() == "Drop")
{
- player_node->dropItem(mItem, mItemAmountTextBox->getInt());
+ player_node->dropItem(mItem, mItemAmountTextField->getValue());
scheduleDelete();
}
else if (event.getId() == "AddTrade")
{
- tradeWindow->tradeItem(mItem, mItemAmountTextBox->getInt());
+ tradeWindow->tradeItem(mItem, mItemAmountTextField->getValue());
scheduleDelete();
}
+#ifdef TMWSERV_SUPPORT
else if (event.getId() == "Split")
{
- player_node->splitItem(mItem, mItemAmountTextBox->getInt());
+ player_node->splitItem(mItem, mItemAmountTextField->getValue());
scheduleDelete();
}
- mItemAmountTextBox->setInt(amount);
+#endif
+ mItemAmountTextField->setValue(amount);
mItemAmountSlide->setValue(amount);
}
diff --git a/src/gui/item_amount.h b/src/gui/item_amount.h
index c0d2b2c0..4fdb8dc6 100644
--- a/src/gui/item_amount.h
+++ b/src/gui/item_amount.h
@@ -1,36 +1,32 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ITEM_AMOUNT_WINDOW_H
-#define _TMW_ITEM_AMOUNT_WINDOW_H
-
-#include <iosfwd>
+#ifndef ITEM_AMOUNT_WINDOW_H
+#define ITEM_AMOUNT_WINDOW_H
#include <guichan/actionlistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
-
-class IntTextBox;
+class IntTextField;
class Item;
#define AMOUNT_TRADE_ADD 1
@@ -61,7 +57,7 @@ class ItemAmountWindow : public Window, public gcn::ActionListener
void resetAmount();
private:
- IntTextBox *mItemAmountTextBox; /**< Item amount caption. */
+ IntTextField *mItemAmountTextField; /**< Item amount caption. */
Item *mItem;
/**
@@ -70,4 +66,4 @@ class ItemAmountWindow : public Window, public gcn::ActionListener
gcn::Slider *mItemAmountSlide;
};
-#endif /* _TMW_ITEM_AMOUNT_WINDOW_H */
+#endif /* ITEM_AMOUNT_WINDOW_H */
diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp
index 4a90510c..bdae9ada 100644
--- a/src/gui/itemcontainer.cpp
+++ b/src/gui/itemcontainer.cpp
@@ -1,27 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "itemcontainer.h"
#include "chat.h"
+#include "itempopup.h"
+
#include <guichan/mouseinput.hpp>
#include <guichan/selectionlistener.hpp>
@@ -32,12 +34,12 @@
#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"
+#include "../utils/stringutils.h"
// TODO: Add support for adding items to the item shortcut window (global
// itemShortcut).
@@ -55,10 +57,13 @@ enum
};
ItemContainer::ItemContainer(Inventory *inventory,
- int gridColumns = 1, int gridRows = 1):
+ int gridColumns,
+ int gridRows,
+ int offset):
mInventory(inventory),
mGridColumns(gridColumns),
mGridRows(gridRows),
+ mOffset(offset),
mSelectedItem(NULL),
mHighlightedItem(NULL),
mSelectionStatus(SEL_NONE),
@@ -71,17 +76,19 @@ ItemContainer::ItemContainer(Inventory *inventory,
ResourceManager *resman = ResourceManager::getInstance();
mSelImg = resman->getImage("graphics/gui/selection.png");
+ if (!mSelImg) logger->error("Unable to load selection.png");
addKeyListener(this);
addMouseListener(this);
setSize((BOX_WIDTH - 1) * mGridColumns + 1,
- (BOX_HEIGHT - 1) * mGridRows + 1);
+ (BOX_HEIGHT - 1) * mGridRows + 1);
}
ItemContainer::~ItemContainer()
{
mSelImg->decRef();
+ delete mItemPopup;
}
void ItemContainer::draw(gcn::Graphics *graphics)
@@ -174,8 +181,7 @@ void ItemContainer::distributeValueChangedEvent()
}
}
-void
-ItemContainer::keyPressed(gcn::KeyEvent &event)
+void ItemContainer::keyPressed(gcn::KeyEvent &event)
{
switch (event.getKey().getValue())
{
@@ -204,8 +210,7 @@ ItemContainer::keyPressed(gcn::KeyEvent &event)
}
}
-void
-ItemContainer::keyReleased(gcn::KeyEvent &event)
+void ItemContainer::keyReleased(gcn::KeyEvent &event)
{
switch (event.getKey().getValue())
{
@@ -219,8 +224,7 @@ ItemContainer::keyReleased(gcn::KeyEvent &event)
}
}
-void
-ItemContainer::mousePressed(gcn::MouseEvent &event)
+void ItemContainer::mousePressed(gcn::MouseEvent &event)
{
const int button = event.getButton();
if (button == gcn::MouseEvent::LEFT || button == gcn::MouseEvent::RIGHT)
@@ -235,7 +239,7 @@ ItemContainer::mousePressed(gcn::MouseEvent &event)
// put item name into chat window
if (mDescItems)
{
- chatWindow->addItemText(item->getId(), item->getInfo().getName());
+ chatWindow->addItemText(item->getInfo().getName());
}
if (mSelectedItem && mSelectedItem == item)
@@ -246,6 +250,8 @@ ItemContainer::mousePressed(gcn::MouseEvent &event)
{
setSelectedItem(item);
mSelectionStatus = SEL_SELECTING;
+
+ itemShortcut->setItemSelected(item->getId());
}
else
{
@@ -255,8 +261,7 @@ ItemContainer::mousePressed(gcn::MouseEvent &event)
}
}
-void
-ItemContainer::mouseDragged(gcn::MouseEvent &event)
+void ItemContainer::mouseDragged(gcn::MouseEvent &event)
{
if (mSelectionStatus != SEL_NONE)
{
@@ -297,15 +302,16 @@ void ItemContainer::mouseReleased(gcn::MouseEvent &event)
// Show ItemTooltip
void ItemContainer::mouseMoved(gcn::MouseEvent &event)
{
- Item *item = mInventory->getItem( getSlotIndex(event.getX(), event.getY() ) );
+ Item *item = mInventory->getItem(getSlotIndex(event.getX(), event.getY()));
- if( item )
+ if (item)
{
- mItemPopup->setPosition(getParent()->getParent()->getX() + getParent()->getParent()->getWidth(), getParent()->getParent()->getY());
+ int mouseX, mouseY;
+ SDL_GetMouseState(&mouseX, &mouseY);
mItemPopup->setItem(item->getInfo());
-
- mItemPopup->setVisible(true);
+ mItemPopup->setOpaque(false);
+ mItemPopup->view(mouseX, mouseY);
}
else
{
@@ -313,14 +319,6 @@ void ItemContainer::mouseMoved(gcn::MouseEvent &event)
}
}
-
-// Show ItemTooltip
-void ItemContainer::mouseEntered(gcn::MouseEvent &event)
-{
-
-}
-
-
// Hide ItemTooltip
void ItemContainer::mouseExited(gcn::MouseEvent &event)
{
diff --git a/src/gui/itemcontainer.h b/src/gui/itemcontainer.h
index 7636ef0c..38eaba01 100644
--- a/src/gui/itemcontainer.h
+++ b/src/gui/itemcontainer.h
@@ -1,39 +1,37 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ITEMCONTAINER_H__
-#define _TMW_ITEMCONTAINER_H__
+#ifndef ITEMCONTAINER_H
+#define ITEMCONTAINER_H
+
+#include <list>
#include <guichan/keylistener.hpp>
#include <guichan/mouselistener.hpp>
-
#include <guichan/widget.hpp>
-#include "itempopup.h"
-
-#include <list>
-
class Image;
class Inventory;
class Item;
+class ItemPopup;
namespace gcn {
class SelectionListener;
@@ -53,9 +51,11 @@ class ItemContainer : public gcn::Widget,
* Constructor. Initializes the graphic.
* @param inventory
* @param gridColumns Amount of columns in grid.
- * @param gridRows Amount of rows in grid.
+ * @param gridRows Amount of rows in grid.
+ * @param offset Index offset
*/
- ItemContainer(Inventory *inventory, int gridColumns, int gridRows);
+ ItemContainer(Inventory *inventory, int gridColumns, int gridRows,
+ int offset = 0);
/**
* Destructor.
@@ -95,7 +95,7 @@ class ItemContainer : public gcn::Widget,
/**
* Returns the selected item.
*/
- Item* getItem() const
+ Item* getSelectedItem() const
{ return mSelectedItem; }
/**
@@ -133,7 +133,6 @@ class ItemContainer : public gcn::Widget,
*/
void keyAction();
- void mouseEntered(gcn::MouseEvent &event);
void mouseExited(gcn::MouseEvent &event);
void mouseMoved(gcn::MouseEvent &event);
@@ -150,6 +149,16 @@ class ItemContainer : public gcn::Widget,
void setSelectedItem(Item *item);
/**
+ * Find the current item index by the most recently used item ID
+ */
+ void refindSelectedItem();
+
+ /**
+ * Determine and set the height of the container.
+ */
+ void recalculateHeight();
+
+ /**
* Sends out selection events to the list of selection listeners.
*/
void distributeValueChangedEvent();
@@ -161,10 +170,11 @@ class ItemContainer : public gcn::Widget,
* @param posY The Y Coordinate position.
* @return The slot index on success, -1 on failure.
*/
- int getSlotIndex(const int posX, const int posY) const;
+ int getSlotIndex(int posX, int posY) const;
Inventory *mInventory;
int mGridColumns, mGridRows;
+ int mOffset;
Image *mSelImg;
Item *mSelectedItem, *mHighlightedItem;
int mSelectionStatus;
diff --git a/src/gui/itemlinkhandler.cpp b/src/gui/itemlinkhandler.cpp
index bdfa2ca6..4060b303 100644
--- a/src/gui/itemlinkhandler.cpp
+++ b/src/gui/itemlinkhandler.cpp
@@ -1,33 +1,35 @@
/*
* The Mana World
- * Copyright 2009 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; 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"
-#include <sstream>
-#include <string>
-
ItemLinkHandler::ItemLinkHandler()
{
mItemPopup = new ItemPopup;
@@ -47,14 +49,15 @@ void ItemLinkHandler::handleLink(const std::string &link)
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->setVisible(true);
- }
+ mItemPopup->view(mouseX, mouseY);
}
}
diff --git a/src/gui/itemlinkhandler.h b/src/gui/itemlinkhandler.h
index 973aab75..c04afa9e 100644
--- a/src/gui/itemlinkhandler.h
+++ b/src/gui/itemlinkhandler.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2009 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ITEM_LINK_HANDLER_H_
-#define _TMW_ITEM_LINK_HANDLER_H_
+#ifndef ITEM_LINK_HANDLER_H
+#define ITEM_LINK_HANDLER_H
#include "linkhandler.h"
diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp
index 7a662151..25e6e78e 100644
--- a/src/gui/itempopup.cpp
+++ b/src/gui/itempopup.cpp
@@ -5,107 +5,216 @@
*
* This file is part of The Mana World.
*
- * The Mana World is free software; you can redistribute it and/or modify
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "itempopup.h"
+#include <guichan/font.hpp>
+
#include <guichan/widgets/label.hpp>
-#include "widgets/layout.h"
#include "gui.h"
+#include "itempopup.h"
+#include "scrollarea.h"
+#include "textbox.h"
+#include "windowcontainer.h"
+
+#include "widgets/layout.h"
+
+#include "../units.h"
-#include "../resources/image.h"
-#include "../resources/resourcemanager.h"
#include "../resources/iteminfo.h"
-#include "../utils/gettext.h"
-#include "../utils/strprintf.h"
+#include "../utils/gettext.h"
+#include "../utils/stringutils.h"
-ItemPopup::ItemPopup()
+ItemPopup::ItemPopup():
+ Window()
{
-
setResizable(false);
+ setShowTitle(false);
setTitleBarHeight(0);
- loadSkin("graphics/gui/gui.xml");
// Item Name
mItemName = new gcn::Label("Label");
- mItemName->setFont(gui->getFont());
+ mItemName->setFont(boldFont);
mItemName->setPosition(2, 2);
- mItemName->setWidth(getWidth() - 4);
// Item Description
- mItemDesc = new TextBox();
+ 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, 14));
+ mItemDescScroll->setDimension(gcn::Rectangle(0, 0, 196, getFont()->getHeight()));
mItemDescScroll->setOpaque(false);
- mItemDescScroll->setPosition(2, 15);
+ mItemDescScroll->setPosition(2, getFont()->getHeight());
// Item Effect
- mItemEffect = new TextBox();
+ 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, 14));
+ mItemEffectScroll->setDimension(gcn::Rectangle(0, 0, 196, getFont()->getHeight()));
mItemEffectScroll->setOpaque(false);
- mItemEffectScroll->setPosition(2, 35);
+ 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());
+}
- // LEEOR / TODO: This causes an exception error.
- //moveToBottom(getParent());
-
- mItemDesc->setTextWrapped( "" );
- mItemEffect->setTextWrapped( "" );
+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());
- mItemDesc->setTextWrapped(item.getDescription());
- mItemEffect->setTextWrapped(item.getEffect());
+#ifdef EATHENA_SUPPORT
+ mItemName->setForegroundColor(getColor(item.getType()));
+#endif
+ mItemName->setWidth(boldFont->getWidth(item.getName()));
+ mItemDesc->setTextWrapped(item.getDescription(), 196);
+ mItemEffect->setTextWrapped(item.getEffect(), 196);
+ mItemWeight->setTextWrapped(_("Weight: ") +
+ Units::formatWeight(item.getWeight()), 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();
- if(item.getEffect() == "")
- {
- setContentSize(200, (numRowsDesc * 14) + 30);
- } else {
- setContentSize(200, (numRowsDesc * 14) + (numRowsEffect*14) + 30);
- }
+ mItemDescScroll->setDimension(gcn::Rectangle(2, 0, minWidth,
+ numRowsDesc * getFont()->getHeight()));
- mItemDescScroll->setDimension(gcn::Rectangle(2, 0, 196, numRowsDesc * 14));
+ mItemEffectScroll->setDimension(gcn::Rectangle(2, 0, minWidth,
+ numRowsEffect * getFont()->getHeight()));
- mItemEffectScroll->setDimension(gcn::Rectangle(2, 0, 196, numRowsEffect * 14));
+ 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 * 15) + 25);
+ 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();
+ 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
index 8da0b32a..c820e3a0 100644
--- a/src/gui/itempopup.h
+++ b/src/gui/itempopup.h
@@ -5,44 +5,50 @@
*
* This file is part of The Mana World.
*
- * The Mana World is free software; you can redistribute it and/or modify
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ITEMPOPUP_H__
-#define _TMW_ITEMPOPUP_H__
+#ifndef ITEMPOPUP_H
+#define ITEMPOPUP_H
-#include "textbox.h"
-#include "scrollarea.h"
#include "window.h"
-#include "../item.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 // _TMW_ITEMPOPUP_H__
+#endif // ITEMPOPUP_H
diff --git a/src/gui/itemshortcutcontainer.cpp b/src/gui/itemshortcutcontainer.cpp
index e0604c78..8864cbd9 100644
--- a/src/gui/itemshortcutcontainer.cpp
+++ b/src/gui/itemshortcutcontainer.cpp
@@ -1,62 +1,70 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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"
-#include "../utils/tostring.h"
+#include "../utils/stringutils.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();
@@ -69,11 +77,11 @@ ItemShortcutContainer::logic()
}
}
-void
-ItemShortcutContainer::draw(gcn::Graphics *graphics)
+void ItemShortcutContainer::draw(gcn::Graphics *graphics)
{
Graphics *g = static_cast<Graphics*>(graphics);
+ graphics->setColor(gcn::Color(0, 0, 0));
graphics->setFont(getFont());
for (int i = 0; i < mMaxItems; i++)
@@ -85,19 +93,27 @@ 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)
continue;
- Item *item = player_node->searchForItem(itemShortcut->getItem(i));
- if (item) {
+ Item *item =
+ player_node->getInventory()->findItem(itemShortcut->getItem(i));
+ if (item)
+ {
// Draw item icon.
Image* image = item->getImage();
- if (image) {
- // TODO: Have label indicate equipped status
- const std::string label = toString(item->getQuantity());
+
+ if (image)
+ {
+ const std::string label =
+#ifdef EATHENA_SUPPORT
+ item->isEquipped() ? "Eq." :
+#endif
+ toString(item->getQuantity());
g->drawImage(image, itemX, itemY);
g->drawText(
label,
@@ -124,36 +140,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) {
+ const int itemId = itemShortcut->getItem(index);
+
+ if (index == -1)
return;
- }
- if (itemShortcut->getItem(index) < 0)
+
+ if (itemId < 0)
return;
- Item *item = player_node->searchForItem(itemShortcut->getItem(index));
+
+ Item *item = player_node->getInventory()->findItem(itemId);
+
if (item)
{
mItemMoved = item;
@@ -167,39 +177,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;
}
@@ -207,25 +234,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 76ca870c..22d94ec2 100644
--- a/src/gui/itemshortcutcontainer.h
+++ b/src/gui/itemshortcutcontainer.h
@@ -1,42 +1,41 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ITEMSHORTCUTCONTAINER_H__
-#define _TMW_ITEMSHORTCUTCONTAINER_H__
+#ifndef ITEMSHORTCUTCONTAINER_H
+#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/linkhandler.h b/src/gui/linkhandler.h
index 44f906db..fc9da6da 100644
--- a/src/gui/linkhandler.h
+++ b/src/gui/linkhandler.h
@@ -1,26 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_LINK_HANDLER_H_
-#define _TMW_LINK_HANDLER_H_
+#ifndef LINK_HANDLER_H
+#define LINK_HANDLER_H
+
+#include <string>
#include <string>
diff --git a/src/gui/listbox.cpp b/src/gui/listbox.cpp
index 204d7961..74d0b9ad 100644
--- a/src/gui/listbox.cpp
+++ b/src/gui/listbox.cpp
@@ -1,70 +1,74 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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)
{
}
-ListBox::ListBox():
- gcn::ListBox()
-{
-
-}
-
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 = (int)(mAlpha * 255.0f);
+
+ 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 d42c7d3e..12fcb955 100644
--- a/src/gui/listbox.h
+++ b/src/gui/listbox.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_LISTBOX_H
-#define _TMW_LISTBOX_H
+#ifndef LISTBOX_H
+#define LISTBOX_H
#include <guichan/widgets/listbox.hpp>
@@ -40,7 +40,6 @@ class ListBox : public gcn::ListBox
* Constructor.
*/
ListBox(gcn::ListModel *listModel);
- ListBox();
/**
* Draws the list box.
@@ -48,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 615045b6..e68a8da1 100644
--- a/src/gui/login.cpp
+++ b/src/gui/login.cpp
@@ -1,72 +1,127 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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/stringutils.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)
{
gcn::Label *userLabel = new gcn::Label(_("Name:"));
gcn::Label *passLabel = new gcn::Label(_("Password:"));
+#ifdef EATHENA_SUPPORT
+ 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;
+#endif
+
mUserField = new TextField(mLoginData->username);
mPassField = new PasswordField(mLoginData->password);
+#ifdef EATHENA_SUPPORT
+ mServerField = new TextField(mServerList->getServerAt(0));
+ mPortField = new TextField(mServerList->getPortAt(0));
+ mServerDropDown = new DropDown(mServerList,
+ mServerScrollArea,
+ mServerListBox);
+ mServerDropDown->setOpaque(false);
+#endif
+
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");
+#ifdef EATHENA_SUPPORT
+ mServerField->setActionEventId("ok");
+ mPortField->setActionEventId("ok");
+ mServerDropDown->setActionEventId("changeSelection");
+#endif
mUserField->addKeyListener(this);
mPassField->addKeyListener(this);
+#ifdef EATHENA_SUPPORT
+ mServerField->addKeyListener(this);
+ mPortField->addKeyListener(this);
+ mServerDropDown->addKeyListener(this);
+#endif
mUserField->addActionListener(this);
mPassField->addActionListener(this);
+#ifdef EATHENA_SUPPORT
+ mServerField->addActionListener(this);
+ mPortField->addActionListener(this);
+ mServerDropDown->addActionListener(this);
mKeepCheck->addActionListener(this);
+#endif
place(0, 0, userLabel);
place(0, 1, passLabel);
- place(1, 0, mUserField, 3).setPadding(2);
- place(1, 1, mPassField, 3).setPadding(2);
- place(0, 2, mKeepCheck, 4);
- place(0, 3, mRegisterButton).setHAlign(LayoutCell::LEFT);
- place(2, 3, mOkButton);
- place(3, 3, mCancelButton);
+#ifdef EATHENA_SUPPORT
+ place(0, 2, serverLabel);
+ place(0, 3, portLabel);
+ place(0, 4, dropdownLabel);
+#endif
+ place(1, 0, mUserField, 3).setPadding(1);
+ place(1, 1, mPassField, 3).setPadding(1);
+#ifdef EATHENA_SUPPORT
+ place(1, 2, mServerField, 3).setPadding(1);
+ place(1, 3, mPortField, 3).setPadding(1);
+ place(1, 4, mServerDropDown, 3).setPadding(1);
+#endif
+ 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());
@@ -81,14 +136,14 @@ LoginDialog::LoginDialog(LoginData *loginData):
mOkButton->setEnabled(canSubmit());
}
-LoginDialog::~LoginDialog()
-{
-}
-
void LoginDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "ok" && canSubmit())
{
+#ifdef EATHENA_SUPPORT
+ mLoginData->hostname = mServerField->getText();
+ mLoginData->port = getUShort(mPortField->getText());
+#endif
mLoginData->username = mUserField->getText();
mLoginData->password = mPassField->getText();
mLoginData->remember = mKeepCheck->isSelected();
@@ -96,16 +151,43 @@ void LoginDialog::action(const gcn::ActionEvent &event)
mOkButton->setEnabled(false);
mRegisterButton->setEnabled(false);
-
+#ifdef EATHENA_SUPPORT
+ mServerList->save(mServerField->getText(), mPortField->getText());
+ state = STATE_ACCOUNT;
+#else
state = STATE_LOGIN_ATTEMPT;
+#endif
}
+#ifdef EATHENA_SUPPORT
+ else if (event.getId() == "changeSelection")
+ {
+ int selected = mServerListBox->getSelected();
+ mServerField->setText(mServerList->getServerAt(selected));
+ mPortField->setText(mServerList->getPortAt(selected));
+ }
+#endif
else if (event.getId() == "cancel")
{
+#ifdef TMWSERV_SUPPORT
state = STATE_SWITCH_ACCOUNTSERVER;
+#else
+ state = STATE_EXIT;
+#endif
}
else if (event.getId() == "register")
{
+#ifdef EATHENA_SUPPORT
// 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;
+ }
+#endif
mLoginData->username = mUserField->getText();
mLoginData->password = mPassField->getText();
@@ -122,5 +204,143 @@ bool LoginDialog::canSubmit()
{
return !mUserField->getText().empty() &&
!mPassField->getText().empty() &&
+#ifdef EATHENA_SUPPORT
+ !mServerField->getText().empty() &&
+ isUShort(mPortField->getText()) &&
+#endif
state == STATE_LOGIN;
}
+
+#ifdef EATHENA_SUPPORT
+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);
+}
+#endif
diff --git a/src/gui/login.h b/src/gui/login.h
index 1c23a0f5..9a97cd4d 100644
--- a/src/gui/login.h
+++ b/src/gui/login.h
@@ -1,35 +1,43 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_LOGIN_H
-#define _TMW_LOGIN_H
+#ifndef LOGIN_H
+#define LOGIN_H
+
+#include <string>
+#include <vector>
-#include <iosfwd>
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
+#ifdef EATHENA_SUPPORT
+#include <guichan/listmodel.hpp>
+#endif
#include "window.h"
-#include "../guichanfwd.h"
class LoginData;
+#ifdef EATHENA_SUPPORT
+class DropDown;
+class ScrollArea;
+#endif
/**
* The login dialog.
@@ -48,11 +56,6 @@ class LoginDialog : public Window, public gcn::ActionListener,
LoginDialog(LoginData *loginData);
/**
- * Destructor
- */
- ~LoginDialog();
-
- /**
* Called when receiving actions from the widgets.
*/
void action(const gcn::ActionEvent &event);
@@ -67,17 +70,71 @@ 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();
+
+#ifdef EATHENA_SUPPORT
+ /**
+ * 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);
+
+#endif
gcn::TextField *mUserField;
gcn::TextField *mPassField;
+#ifdef EATHENA_SUPPORT
+ gcn::TextField *mServerField;
+ gcn::TextField *mPortField;
+ DropDown *mServerDropDown;
+#endif
gcn::CheckBox *mKeepCheck;
gcn::Button *mOkButton;
gcn::Button *mCancelButton;
gcn::Button *mRegisterButton;
LoginData *mLoginData;
+
+#ifdef EATHENA_SUPPORT
+ /**
+ * 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
};
#endif
diff --git a/src/gui/magic.cpp b/src/gui/magic.cpp
index 2c81321b..0e56e853 100644
--- a/src/gui/magic.cpp
+++ b/src/gui/magic.cpp
@@ -29,7 +29,6 @@
#include "../localplayer.h"
#include "../utils/dtor.h"
-#include "../utils/tostring.h"
#include "../utils/gettext.h"
MagicDialog::MagicDialog():
diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp
index 9415188e..25ece461 100644
--- a/src/gui/menuwindow.cpp
+++ b/src/gui/menuwindow.cpp
@@ -1,44 +1,47 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 *magicDialog;
extern Window *statusWindow;
-extern Window *guildWindow;
-extern Window *itemShortcutWindow;
+#ifdef TMWSERV_SUPPORT
extern Window *buddyWindow;
+extern Window *guildWindow;
+extern Window *magicDialog;
+#endif
namespace {
struct MenuWindowListener : public gcn::ActionListener
@@ -54,20 +57,25 @@ MenuWindow::MenuWindow():
Window()
{
setResizable(false);
+ setWindowName("Menu");
setMovable(false);
setTitleBarHeight(0);
// Buttons
static const char *buttonNames[] =
{
+ N_("Chat"),
N_("Status"),
N_("Equipment"),
N_("Inventory"),
N_("Skills"),
+#ifdef TMWSERV_SUPPORT
N_("Magic"),
N_("Guilds"),
N_("Buddys"),
+#endif
N_("Shortcut"),
+ N_("Emote"),
N_("Setup"),
0
};
@@ -96,7 +104,11 @@ 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;
}
@@ -112,6 +124,7 @@ void MenuWindowListener::action(const gcn::ActionEvent &event)
{
window = skillDialog;
}
+#ifdef TMWSERV_SUPPORT
else if (event.getId() == "Magic")
{
window = magicDialog;
@@ -124,10 +137,15 @@ void MenuWindowListener::action(const gcn::ActionEvent &event)
{
window = buddyWindow;
}
+#endif
else if (event.getId() == "Shortcut")
{
window = itemShortcutWindow;
}
+ 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 03ec3380..9bb54e29 100644
--- a/src/gui/menuwindow.h
+++ b/src/gui/menuwindow.h
@@ -1,31 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_MENU_H
-#define _TMW_MENU_H
+#ifndef MENU_H
+#define MENU_H
#include "window.h"
-#include "../guichanfwd.h"
-
/**
* The Button Menu.
*
diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp
index f7749755..4347c9cc 100644
--- a/src/gui/minimap.cpp
+++ b/src/gui/minimap.cpp
@@ -1,28 +1,31 @@
/*
* The Mana World
- * Copyright 2004-2005 The Mana World Development Team
+ * Copyright (C) 2004-2005 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 "minimap.h"
#include "../being.h"
#include "../beingmanager.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../localplayer.h"
@@ -30,22 +33,27 @@
#include "../utils/gettext.h"
+bool Minimap::mShow = true;
+
Minimap::Minimap():
Window(_("MiniMap")),
- mMapImage(NULL)
+ mMapImage(NULL),
+ mProportion(0.5)
{
setWindowName("MiniMap");
+ mShow = config.getValue(getWindowName() + "Show", true);
setDefaultSize(5, 25, 100, 100);
+ setResizable(true);
+
loadWindowState();
- // LEEOR: The Window class needs to modified to accept
- // setAlignment calls.
- setAlignment(gcn::Graphics::CENTER);
}
Minimap::~Minimap()
{
if (mMapImage)
mMapImage->decRef();
+
+ config.setValue(getWindowName() + "Show", mShow);
}
void Minimap::setMapImage(Image *img)
@@ -55,30 +63,94 @@ void Minimap::setMapImage(Image *img)
mMapImage = img;
- if (mMapImage) {
- mMapImage->setAlpha(0.7);
- setContentSize(mMapImage->getWidth(), mMapImage->getHeight());
+ if (mMapImage)
+ {
+ 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();
- int mapOriginX = a.x;
- int mapOriginY = a.y;
+ graphics->pushClipArea(a);
+
+ int mapOriginX = 0;
+ int mapOriginY = 0;
if (mMapImage)
{
if (mMapImage->getWidth() > a.width ||
mMapImage->getHeight() > a.height)
{
- const Vector &pos = player_node->getPosition();
- mapOriginX += (a.width - (int) (pos.x / 32)) / 2;
- mapOriginY += (a.height - (int) (pos.y / 32)) / 2;
+#ifdef TMWSERV_SUPPORT
+ const Vector &p = player_node->getPosition();
+ mapOriginX = (int) (((a.width) / 2) - (int) (p.x * mProportion) / 32);
+ mapOriginY = (int) (((a.height) / 2) - (int) (p.y * mProportion) / 32);
+#else
+ mapOriginX = (int) (((a.width) / 2) - (player_node->mX * mProportion));
+ mapOriginY = (int) (((a.height) / 2) - (player_node->mY * mProportion));
+#endif
+
+ const int minOriginX = a.width - mMapImage->getWidth();
+ const int minOriginY = a.height - mMapImage->getHeight();
+
+ if (mapOriginX < minOriginX)
+ mapOriginX = minOriginX;
+ if (mapOriginY < minOriginY)
+ mapOriginY = minOriginY;
+ if (mapOriginX > 0)
+ mapOriginX = 0;
+ if (mapOriginY > 0)
+ mapOriginY = 0;
}
+
static_cast<Graphics*>(graphics)->
drawImage(mMapImage, mapOriginX, mapOriginY);
}
@@ -102,24 +174,26 @@ void Minimap::draw(gcn::Graphics *graphics)
graphics->setColor(gcn::Color(61, 52, 209));
break;
- case Being::NPC:
- graphics->setColor(gcn::Color(255, 255, 0));
- break;
-
case Being::MONSTER:
graphics->setColor(gcn::Color(209, 52, 61));
break;
+ case Being::NPC:
+ graphics->setColor(gcn::Color(255, 255, 0));
+ break;
+
default:
continue;
}
- const int offset = (dotSize - 1) / 2;
+ const int offset = (int) ((dotSize - 1) * mProportion);
const Vector &pos = being->getPosition();
graphics->fillRectangle(gcn::Rectangle(
- (int) pos.x / 64 + mapOriginX - offset,
- (int) pos.x / 64 + mapOriginY - offset,
+ (int) (pos.x * mProportion) / 32 + mapOriginX - offset,
+ (int) (pos.x * mProportion) / 32 + mapOriginY - offset,
dotSize, dotSize));
}
+
+ graphics->popClipArea();
}
diff --git a/src/gui/minimap.h b/src/gui/minimap.h
index f91dc22d..3ce0aacd 100644
--- a/src/gui/minimap.h
+++ b/src/gui/minimap.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004-2005 The Mana World Development Team
+ * Copyright (C) 2004-2005 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_MINIMAP_H
-#define _TMW_MINIMAP_H
+#ifndef MINIMAP_H
+#define MINIMAP_H
#include "window.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 86e5a8f1..5bc25bdb 100644
--- a/src/gui/ministatus.cpp
+++ b/src/gui/ministatus.cpp
@@ -1,65 +1,94 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "ministatus.h"
-
-#include <guichan/widgets/label.hpp>
-
#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"
+#include "../utils/stringutils.h"
MiniStatusWindow::MiniStatusWindow()
{
+ setWindowName("MiniStatus");
setResizable(false);
setMovable(false);
setTitleBarHeight(0);
mHpBar = new ProgressBar(1.0f, 100, 20, 0, 171, 34);
- mHpLabel = new gcn::Label("");
+#ifdef EATHENA_SUPPORT
+ mMpBar = new ProgressBar(1.0f, 100, 20, 26, 102, 230);
+ mXpBar = new ProgressBar(1.0f, 100, 20, 143, 192, 211);
+#endif
mHpBar->setPosition(0, 3);
+#ifdef EATHENA_SUPPORT
+ mMpBar->setPosition(mHpBar->getWidth() + 3, 3);
+ mXpBar->setPosition(mMpBar->getX() + mMpBar->getWidth() + 3, 3);
+#endif
- mHpLabel->setDimension(mHpBar->getDimension());
+ add(mHpBar);
+#ifdef EATHENA_SUPPORT
+ add(mMpBar);
+ add(mXpBar);
+#endif
+
+#ifdef EATHENA_SUPPORT
+ setContentSize(mXpBar->getX() + mXpBar->getWidth(),
+ mXpBar->getY() + mXpBar->getHeight());
+#else
+ setContentSize(mHpBar->getX() + mHpBar->getWidth(),
+ mHpBar->getY() + mHpBar->getHeight());
+#endif
+ setDefaultSize(0, 0, getWidth(), getHeight());
+ loadWindowState();
+}
- mHpLabel->setForegroundColor(gcn::Color(255, 255, 255));
+void MiniStatusWindow::setIcon(int index, AnimatedSprite *sprite)
+{
+ if (index >= (int) mIcons.size())
+ mIcons.resize(index + 1, NULL);
- mHpLabel->setFont(speechFont);
+ if (mIcons[index])
+ delete mIcons[index];
- mHpLabel->setAlignment(gcn::Graphics::CENTER);
+ mIcons[index] = sprite;
+}
- add(mHpBar);
- add(mHpLabel);
+void MiniStatusWindow::eraseIcon(int index)
+{
+ mIcons.erase(mIcons.begin() + index);
}
+extern volatile int tick_time;
+
void MiniStatusWindow::update()
{
// HP Bar coloration
- int maxHp = player_node->getMaxHP();
- int hp = player_node->getHP();
+ int maxHp = player_node->getMaxHp();
+ int hp = player_node->getHp();
if (hp < int(maxHp / 3))
{
mHpBar->setColor(223, 32, 32); // Red
@@ -73,10 +102,47 @@ void MiniStatusWindow::update()
mHpBar->setColor(0, 171, 34); // Green
}
+#ifdef EATHENA_SUPPORT
+ 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;
+#endif
+
mHpBar->setProgress((float) hp / maxHp);
+#ifdef EATHENA_SUPPORT
+ mMpBar->setProgress((float) player_node->mMp / player_node->mMaxMp);
+ mXpBar->setProgress(xp);
+#endif
// Update labels
- mHpLabel->setCaption(toString(hp));
+ mHpBar->setText(toString(player_node->getHp()));
+#ifdef EATHENA_SUPPORT
+ mMpBar->setText(toString(player_node->mMp));
+
+ std::stringstream updatedText;
+ 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)
+ {
+ updatedText << " | "
+ << (int)(((float)player_node->mXpForNextLevel - (float)player_node->mXp)
+ / (float)config.getValue("xpBarMonsterCounterExp", 0))
+ << " "
+ << config.getValue("xpBarMonsterCounterName", "Monsters") <<" left...";
+ }
+ */
+
+ mXpBar->setText(updatedText.str());
+#endif
+
+ for (unsigned int i = 0; i < mIcons.size(); i++)
+ if (mIcons[i])
+ mIcons[i]->update(tick_time * 10);
}
void MiniStatusWindow::draw(gcn::Graphics *graphics)
@@ -84,3 +150,19 @@ void MiniStatusWindow::draw(gcn::Graphics *graphics)
update();
drawChildren(graphics);
}
+
+void MiniStatusWindow::drawIcons(Graphics *graphics)
+{
+ // Draw icons
+#ifdef TMWSERV_SUPPORT
+ int icon_x = mHpBar->getX() + mHpBar->getWidth() + 4;
+#else
+ int icon_x = mXpBar->getX() + mXpBar->getWidth() + 4;
+#endif
+ for (unsigned int i = 0; i < mIcons.size(); i++) {
+ if (mIcons[i]) {
+ mIcons[i]->draw(graphics, icon_x, 3);
+ icon_x += 2 + mIcons[i]->getWidth();
+ }
+ }
+}
diff --git a/src/gui/ministatus.h b/src/gui/ministatus.h
index f512ef25..b69f9a14 100644
--- a/src/gui/ministatus.h
+++ b/src/gui/ministatus.h
@@ -1,33 +1,32 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_MINISTATUS_H
-#define _TMW_MINISTATUS_H
-
-#include <iosfwd>
+#ifndef MINISTATUS_H
+#define MINISTATUS_H
#include "window.h"
-#include "../guichanfwd.h"
+#include <vector>
+class AnimatedSprite;
class ProgressBar;
/**
@@ -44,13 +43,22 @@ class MiniStatusWindow : public Window
MiniStatusWindow();
/**
- * Draw this window
+ * Draw this window.
*/
void draw(gcn::Graphics *graphics);
+ /**
+ * Sets one of the icons.
+ */
+ void setIcon(int index, AnimatedSprite *sprite);
+
+ void eraseIcon(int index);
+
+ void drawIcons(Graphics *graphics);
+
private:
/**
- * Updates this dialog with values from player_node
+ * Updates this dialog with values from player_node.
*/
void update();
@@ -58,7 +66,12 @@ class MiniStatusWindow : public Window
* Mini Status Bars
*/
ProgressBar *mHpBar;
- gcn::Label *mHpLabel;
+#ifdef EATHENA_SUPPORT
+ ProgressBar *mMpBar;
+ ProgressBar *mXpBar;
+#endif
+
+ std::vector<AnimatedSprite *> mIcons;
};
#endif
diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp
index c9ace303..48f2adb7 100644
--- a/src/gui/npc_text.cpp
+++ b/src/gui/npc_text.cpp
@@ -1,102 +1,117 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 "npc_text.h"
-
-#include <string>
-
#include "scrollarea.h"
-#include "button.h"
#include "textbox.h"
+#include "widgets/layout.h"
+
#include "../npc.h"
#include "../utils/gettext.h"
NpcTextDialog::NpcTextDialog():
- Window(_("NPC"))
+ Window(_("NPC")),
+ mState(NPC_TEXT_STATE_WAITING)
{
setResizable(true);
setMinWidth(200);
setMinHeight(150);
+ setDefaultSize(0, 0, 260, 200);
+
mTextBox = new TextBox;
mTextBox->setEditable(false);
+ mTextBox->setOpaque(false);
- scrollArea = new ScrollArea(mTextBox);
- okButton = new Button(_("OK"), "ok", this);
+ mScrollArea = new ScrollArea(mTextBox);
+ mButton = new Button(_("Waiting for server"), "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());
+ mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mScrollArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS);
- add(scrollArea);
- add(okButton);
+ place(0, 0, mScrollArea, 5).setPadding(3);
+ place(4, 1, mButton);
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
+
+ loadWindowState();
setLocationRelativeTo(getParent());
}
void NpcTextDialog::setText(const std::string &text)
{
mText = text;
- mTextBox->setTextWrapped(mText);
+ mTextBox->setTextWrapped(mText, mScrollArea->getWidth() - 15);
}
void NpcTextDialog::addText(const std::string &text)
{
setText(mText + text + "\n");
+ mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll());
}
-void NpcTextDialog::widgetResized(const gcn::Event &event)
+void NpcTextDialog::showNextButton()
{
- 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());
+ mButton->setCaption(_("Next"));
+ mState = NPC_TEXT_STATE_NEXT;
+ mButton->setEnabled(true);
+}
- // Set the text again so that it gets wrapped according to the new size
- mTextBox->setTextWrapped(mText);
+void NpcTextDialog::showCloseButton()
+{
+ mButton->setCaption(_("Close"));
+ mState = NPC_TEXT_STATE_CLOSE;
+ mButton->setEnabled(true);
}
void NpcTextDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "ok")
{
- setText("");
- setVisible(false);
- if (current_npc)
+ if (mState == NPC_TEXT_STATE_NEXT && current_npc) {
current_npc->nextDialog();
- current_npc = 0;
+ addText("\n> Next\n");
+ } else if (mState == NPC_TEXT_STATE_CLOSE ||
+ (mState == NPC_TEXT_STATE_NEXT && !current_npc)) {
+ setText("");
+ setVisible(false);
+ if (current_npc) current_npc->handleDeath();
+ } else return;
}
+ else return;
+
+ mButton->setEnabled(false);
+ mButton->setCaption(_("Waiting for server"));
+ mState = NPC_TEXT_STATE_WAITING;
+}
+
+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 b6eccf95..a1373830 100644
--- a/src/gui/npc_text.h
+++ b/src/gui/npc_text.h
@@ -1,28 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NPC_TEXT_H
-#define _TMW_NPC_TEXT_H
+#ifndef NPC_TEXT_H
+#define NPC_TEXT_H
+
+#include <string>
-#include <iosfwd>
#include <guichan/actionlistener.hpp>
#include "window.h"
@@ -45,16 +46,14 @@ class NpcTextDialog : public Window, public gcn::ActionListener
NpcTextDialog();
/**
- * Called when resizing the window.
- *
- * @param event The calling event
+ * Called when receiving actions from the widgets.
*/
- void widgetResized(const gcn::Event &event);
+ void action(const gcn::ActionEvent &event);
/**
- * Called when receiving actions from the widgets.
+ * Clears the text shown in the dialog.
*/
- void action(const gcn::ActionEvent &event);
+ void clearText();
/**
* Sets the text shows in the dialog.
@@ -71,12 +70,30 @@ class NpcTextDialog : public Window, public gcn::ActionListener
*/
void addText(const std::string &string);
+ void showNextButton();
+
+ void showCloseButton();
+
+ /**
+ * Called when resizing the window.
+ *
+ * @param event The calling event
+ */
+ void widgetResized(const gcn::Event &event);
+
private:
- gcn::Button *okButton;
- gcn::ScrollArea *scrollArea;
+ gcn::ScrollArea *mScrollArea;
TextBox *mTextBox;
+ gcn::Button *mButton;
std::string mText;
+
+ enum NPCTextState {
+ NPC_TEXT_STATE_WAITING,
+ NPC_TEXT_STATE_NEXT,
+ NPC_TEXT_STATE_CLOSE
+ };
+ int mState;
};
-#endif // _TMW_NPC_TEXT_H
+#endif // NPC_TEXT_H
diff --git a/src/gui/npcintegerdialog.cpp b/src/gui/npcintegerdialog.cpp
new file mode 100644
index 00000000..463f46ae
--- /dev/null
+++ b/src/gui/npcintegerdialog.cpp
@@ -0,0 +1,125 @@
+/*
+ * 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 "button.h"
+#include "inttextfield.h"
+#include "npc_text.h"
+#include "npcintegerdialog.h"
+
+#include "widgets/layout.h"
+
+#include "../npc.h"
+
+#include "../utils/gettext.h"
+#include "../utils/strprintf.h"
+
+extern NpcTextDialog *npcTextDialog;
+
+NpcIntegerDialog::NpcIntegerDialog():
+ Window(_("NPC Number Request"))
+{
+ mValueField = new IntTextField;
+
+ mDecButton = new Button("-", "decvalue", this);
+ mIncButton = new Button("+", "incvalue", this);
+ gcn::Button *okButton = new Button(_("OK"), "ok", this);
+ gcn::Button *cancelButton = new Button(_("Cancel"), "cancel", this);
+ gcn::Button *resetButton = new Button(_("Reset"), "reset", this);
+
+ mDecButton->setSize(20, 20);
+ mIncButton->setSize(20, 20);
+
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
+
+ place(0, 0, mDecButton);
+ place(1, 0, mValueField, 3);
+ place(4, 0, mIncButton);
+ place.getCell().matchColWidth(1, 0);
+ place = getPlacer(0, 1);
+ place(0, 0, resetButton);
+ place(2, 0, cancelButton);
+ place(3, 0, okButton);
+ reflowLayout(175, 0);
+
+ setLocationRelativeTo(getParent());
+}
+
+void NpcIntegerDialog::setRange(int min, int max)
+{
+ mValueField->setRange(min, max);
+}
+
+int NpcIntegerDialog::getValue()
+{
+ return mValueField->getValue();
+}
+
+void NpcIntegerDialog::action(const gcn::ActionEvent &event)
+{
+ int finish = 0;
+
+ if (event.getId() == "ok")
+ {
+ finish = 1;
+ npcTextDialog->addText(strprintf("\n> %d\n", mValueField->getValue()));
+ }
+ else if (event.getId() == "cancel")
+ {
+ finish = 1;
+ mValueField->reset();
+ npcTextDialog->addText(_("\n> Cancel\n"));
+ }
+ else if (event.getId() == "decvalue")
+ {
+ mValueField->setValue(mValueField->getValue() - 1);
+ }
+ else if (event.getId() == "incvalue")
+ {
+ mValueField->setValue(mValueField->getValue() + 1);
+ }
+ else if (event.getId() == "reset")
+ {
+ mValueField->reset();
+ }
+
+ if (finish)
+ {
+ setVisible(false);
+ current_npc->integerInput(mValueField->getValue());
+ mValueField->reset();
+ }
+}
+
+void NpcIntegerDialog::setDefaultValue(int value)
+{
+ mValueField->setDefaultValue(value);
+}
+
+bool NpcIntegerDialog::isInputFocused()
+{
+ return mValueField->isFocused();
+}
+
+void NpcIntegerDialog::requestFocus()
+{
+ mValueField->requestFocus();
+}
diff --git a/src/gui/npcintegerdialog.h b/src/gui/npcintegerdialog.h
new file mode 100644
index 00000000..941bb55a
--- /dev/null
+++ b/src/gui/npcintegerdialog.h
@@ -0,0 +1,87 @@
+/*
+ * 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
+ */
+
+#ifndef GUI_NPCINTEGERDIALOG_H
+#define GUI_NPCINTEGERDIALOG_H
+
+#include <guichan/actionlistener.hpp>
+
+#include "window.h"
+
+class IntTextField;
+
+/**
+ * The npc integer input dialog.
+ *
+ * \ingroup Interface
+ */
+class NpcIntegerDialog : public Window, public gcn::ActionListener
+{
+ public:
+ /**
+ * Constructor.
+ *
+ * @see Window::Window
+ */
+ NpcIntegerDialog();
+
+ /**
+ * Called when receiving actions from the widgets.
+ */
+ void action(const gcn::ActionEvent &event);
+
+ /**
+ * Returns the current value.
+ */
+ int getValue();
+
+ /**
+ * Prepares the NPC dialog.
+ *
+ * @param min The minimum value to allow
+ * @param max The maximum value to allow
+ */
+ void setRange(int min, int max);
+
+ /**
+ * Sets the default value.
+ *
+ * @param value The new default value
+ */
+ void setDefaultValue(int value);
+
+ /**
+ * 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;
+ IntTextField *mValueField;
+};
+
+#endif // GUI_NPCINTEGERDIALOG_H
diff --git a/src/gui/npclistdialog.cpp b/src/gui/npclistdialog.cpp
index c55255ea..82e05fd5 100644
--- a/src/gui/npclistdialog.cpp
+++ b/src/gui/npclistdialog.cpp
@@ -1,35 +1,40 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 "npc_text.h"
+#include "npclistdialog.h"
+#include "scrollarea.h"
+
+#include "widgets/layout.h"
#include "../npc.h"
#include "../utils/gettext.h"
+#include "../utils/strprintf.h"
+
+extern NpcTextDialog *npcTextDialog;
NpcListDialog::NpcListDialog():
Window(_("NPC"))
@@ -39,30 +44,25 @@ NpcListDialog::NpcListDialog():
setMinWidth(200);
setMinHeight(150);
+ setDefaultSize(0, 0, 260, 200);
+
mItemList = new ListBox(this);
- scrollArea = new ScrollArea(mItemList);
- okButton = new Button(_("OK"), "ok", this);
- cancelButton = new Button(_("Cancel"), "cancel", this);
+ mItemList->setWrappingEnabled(true);
+ gcn::ScrollArea *scrollArea = new ScrollArea(mItemList);
+ gcn::Button *okButton = new Button(_("OK"), "ok", this);
+ gcn::Button *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");
+ place(0, 0, scrollArea, 5).setPadding(3);
+ place(3, 1, okButton);
+ place(4, 1, cancelButton);
- mItemList->addActionListener(this);
-
- add(scrollArea);
- add(okButton);
- add(cancelButton);
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
+ loadWindowState();
setLocationRelativeTo(getParent());
}
@@ -81,33 +81,23 @@ void NpcListDialog::addItem(const std::string &item)
mItems.push_back(item);
}
-void NpcListDialog::reset()
+void NpcListDialog::parseItems(const std::string &itemString)
{
- mItems.clear();
+ std::istringstream iss(itemString);
+
+ std::string tmp;
+ while (getline(iss, tmp, ':'))
+ mItems.push_back(tmp);
}
-void NpcListDialog::widgetResized(const gcn::Event &event)
+void NpcListDialog::reset()
{
- 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());
+ mItems.clear();
}
void NpcListDialog::action(const gcn::ActionEvent &event)
{
int choice = 0;
-
if (event.getId() == "ok")
{
// Send the selected index back to the server
@@ -115,11 +105,14 @@ void NpcListDialog::action(const gcn::ActionEvent &event)
if (selectedIndex > -1)
{
choice = selectedIndex + 1;
+ npcTextDialog->addText(strprintf("\n> \"%s\"\n",
+ mItems[selectedIndex].c_str()));
}
}
else if (event.getId() == "cancel")
{
choice = 0xff; // 0xff means cancel
+ npcTextDialog->addText(_("\n> Cancel\n"));
}
if (choice)
@@ -127,6 +120,5 @@ void NpcListDialog::action(const gcn::ActionEvent &event)
setVisible(false);
reset();
current_npc->dialogChoice(choice);
- current_npc = 0;
}
}
diff --git a/src/gui/npclistdialog.h b/src/gui/npclistdialog.h
index 65281f58..7e37c7e6 100644
--- a/src/gui/npclistdialog.h
+++ b/src/gui/npclistdialog.h
@@ -1,36 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_GUI_NPCLISTDIALOG_H
-#define _TMW_GUI_NPCLISTDIALOG_H
+#ifndef GUI_NPCLISTDIALOG_H
+#define GUI_NPCLISTDIALOG_H
-#include <iosfwd>
-#include <vector>
+#include "window.h"
#include <guichan/actionlistener.hpp>
#include <guichan/listmodel.hpp>
-#include "window.h"
-
-#include "../guichanfwd.h"
+#include <vector>
/**
* 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);
@@ -76,17 +66,21 @@ class NpcListDialog : public Window, public gcn::ActionListener,
void addItem(const std::string &);
/**
+ * Fills the options list for an NPC dialog.
+ *
+ * @param itemString A string with the options separated with colons.
+ */
+ void parseItems(const std::string &itemString);
+
+ /**
* Resets the list by removing all items.
*/
void reset();
private:
gcn::ListBox *mItemList;
- gcn::ScrollArea *scrollArea;
- gcn::Button *okButton;
- gcn::Button *cancelButton;
std::vector<std::string> mItems;
};
-#endif // _TMW_GUI_NPCLISTDIALOG_H
+#endif // GUI_NPCLISTDIALOG_H
diff --git a/src/gui/npcstringdialog.cpp b/src/gui/npcstringdialog.cpp
new file mode 100644
index 00000000..d9bf5682
--- /dev/null
+++ b/src/gui/npcstringdialog.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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 "button.h"
+#include "npc_text.h"
+#include "npcstringdialog.h"
+#include "textfield.h"
+
+#include "widgets/layout.h"
+
+#include "../npc.h"
+
+#include "../utils/gettext.h"
+#include "../utils/strprintf.h"
+
+extern NpcTextDialog *npcTextDialog;
+
+NpcStringDialog::NpcStringDialog():
+ Window(_("NPC Text Request"))
+{
+ mValueField = new TextField("");
+
+ gcn::Button *okButton = new Button(_("OK"), "ok", this);
+ gcn::Button *cancelButton = new Button(_("Cancel"), "cancel", this);
+
+ place(0, 0, mValueField, 3);
+ place(1, 1, cancelButton);
+ place(2, 1, okButton);
+ reflowLayout(175, 0);
+
+ setLocationRelativeTo(getParent());
+}
+
+std::string NpcStringDialog::getValue()
+{
+ return mValueField->getText();
+}
+
+void NpcStringDialog::setValue(const std::string &value)
+{
+ mValueField->setText(value);
+ mDefault = value;
+}
+
+void NpcStringDialog::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == "cancel")
+ {
+ mValueField->setText(mDefault);
+ npcTextDialog->addText(_("\n> Cancel\n"));
+ }
+ else
+ {
+ npcTextDialog->addText(strprintf("\n> \"%s\"\n",
+ mValueField->getText().c_str()));
+ }
+
+ setVisible(false);
+ current_npc->stringInput(mValueField->getText());
+ 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
new file mode 100644
index 00000000..0faaf203
--- /dev/null
+++ b/src/gui/npcstringdialog.h
@@ -0,0 +1,76 @@
+/*
+ * 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
+ */
+
+#ifndef GUI_NPCSTRINGDIALOG_H
+#define GUI_NPCSTRINGDIALOG_H
+
+#include "window.h"
+
+#include <guichan/actionlistener.hpp>
+
+/**
+ * The npc integer input dialog.
+ *
+ * \ingroup Interface
+ */
+class NpcStringDialog : public Window, public gcn::ActionListener
+{
+ public:
+ /**
+ * Constructor.
+ *
+ * @see Window::Window
+ */
+ NpcStringDialog();
+
+ /**
+ * Called when receiving actions from the widgets.
+ */
+ void action(const gcn::ActionEvent &event);
+
+ /**
+ * Returns the current value.
+ */
+ std::string getValue();
+
+ /**
+ * Chnages the current value.
+ *
+ * @param value The new value
+ */
+ void setValue(const std::string &value);
+
+ /**
+ * Checks whether NpcStringDialog is Focused or not.
+ */
+ bool isInputFocused();
+
+ /**
+ * Requests the textfield to take focus for input.
+ */
+ void requestFocus();
+
+ private:
+ gcn::TextField *mValueField;
+ std::string mDefault;
+};
+
+#endif // GUI_NPCSTRINGDIALOG_H
diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp
index b03c3964..4df3fa07 100644
--- a/src/gui/ok_dialog.cpp
+++ b/src/gui/ok_dialog.cpp
@@ -1,29 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "ok_dialog.h"
-
-#include <guichan/widgets/label.hpp>
+#include <guichan/font.hpp>
#include "button.h"
+#include "ok_dialog.h"
+#include "scrollarea.h"
+#include "textbox.h"
#include "../utils/gettext.h"
@@ -31,22 +32,44 @@ OkDialog::OkDialog(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 *okButton = new Button(_("Ok"), "ok", this);
- int w = textLabel->getWidth() + 20;
- int h = textLabel->getHeight() + 25 + okButton->getHeight();
+ mTextArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mTextArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mTextArea->setOpaque(false);
+
+ mTextBox->setTextWrapped(msg, 260);
+
+ int numRows = mTextBox->getNumberOfRows();
- if (okButton->getWidth() + 10 > w) {
- w = okButton->getWidth() + 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) + 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));
}
- setContentSize(w, h);
- textLabel->setPosition(10, 10);
- okButton->setPosition((w - okButton->getWidth()) / 2,
- h - 5 - okButton->getHeight());
+ okButton->setPosition((mTextBox->getMinWidth() - okButton->getWidth()) / 2,
+ (numRows * 14) + okButton->getHeight() - 8);
- add(textLabel);
+ add(mTextArea);
add(okButton);
setLocationRelativeTo(getParent());
@@ -54,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 cba12d72..24325c2f 100644
--- a/src/gui/ok_dialog.h
+++ b/src/gui/ok_dialog.h
@@ -1,30 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _OK_DIALOG_H
-#define _OK_DIALOG_H
+#ifndef OK_DIALOG_H
+#define OK_DIALOG_H
+
+#include "window.h"
#include <guichan/actionlistener.hpp>
-#include "window.h"
+class ScrollArea;
+class TextBox;
/**
* An 'Ok' button dialog.
@@ -41,10 +44,16 @@ 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;
};
#endif
diff --git a/src/gui/passwordfield.cpp b/src/gui/passwordfield.cpp
index 01c7e15d..345ee1c3 100644
--- a/src/gui/passwordfield.cpp
+++ b/src/gui/passwordfield.cpp
@@ -1,28 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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 8a14b72a..86195bd1 100644
--- a/src/gui/passwordfield.h
+++ b/src/gui/passwordfield.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_PASSWORDFIELD_H_
-#define _TMW_PASSWORDFIELD_H_
+#ifndef PASSWORDFIELD_H
+#define PASSWORDFIELD_H
#include "textfield.h"
@@ -29,7 +29,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 6888d69a..2bfa798c 100644
--- a/src/gui/playerbox.cpp
+++ b/src/gui/playerbox.cpp
@@ -1,30 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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++;
}
}
@@ -80,9 +82,29 @@ void PlayerBox::draw(gcn::Graphics *graphics)
{
// Draw character
const int bs = getFrameSize();
+#ifdef TMWSERV_SUPPORT
const int x = getWidth() / 2 + bs;
const int y = getHeight() - bs - 8;
mPlayer->draw(static_cast<Graphics*>(graphics), x, y);
+#else
+ const int x = getWidth() / 2 - 16 + bs;
+ const int y = getHeight() / 2 + bs;
+ for (int i = 0; i < Being::VECTOREND_SPRITE; i++)
+ {
+ if (mPlayer->getSprite(i))
+ {
+ mPlayer->getSprite(i)->draw(static_cast<Graphics*>(graphics), x, y);
+ }
+ }
+#endif
+ }
+
+ 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 78eeee91..7c08defd 100644
--- a/src/gui/playerbox.h
+++ b/src/gui/playerbox.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __TMW_PLAYERBOX_H__
-#define __TMW_PLAYERBOX_H__
+#ifndef PLAYERBOX_H
+#define PLAYERBOX_H
#include <guichan/widgets/scrollarea.hpp>
@@ -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 a430ff10..ced44f42 100644
--- a/src/gui/popupmenu.cpp
+++ b/src/gui/popupmenu.cpp
@@ -1,43 +1,46 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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"
+#include "../beingmanager.h"
#include "../floor_item.h"
#include "../item.h"
#include "../localplayer.h"
#include "../npc.h"
+#include "../player_relations.h"
+
+#ifdef EATHENA_SUPPORT
+#include "../net/messageout.h"
+#include "../net/ea/protocol.h"
+#endif
-#include "../resources/iteminfo.h"
#include "../resources/itemdb.h"
#include "../utils/gettext.h"
@@ -47,14 +50,15 @@ extern std::string tradePartnerName;
PopupMenu::PopupMenu():
Window(),
- mBeing(NULL),
+ mBeingId(0),
mFloorItem(NULL),
mItem(NULL)
{
setResizable(false);
setTitleBarHeight(0);
+ setShowTitle(false);
- mBrowserBox = new BrowserBox();
+ mBrowserBox = new BrowserBox;
mBrowserBox->setPosition(4, 4);
mBrowserBox->setHighlightMode(BrowserBox::BACKGROUND);
mBrowserBox->setOpaque(false);
@@ -64,22 +68,47 @@ PopupMenu::PopupMenu():
void PopupMenu::showPopup(int x, int y, Being *being)
{
- mBeing = being;
+ mBeingId = being->getId();
mBrowserBox->clearRows();
- switch (mBeing->getType())
+ switch (being->getType())
{
case Being::PLAYER:
{
// Players can be traded with. Later also attack, follow and
// add as buddy will be options in this menu.
- const std::string &name = mBeing->getName();
+ 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("@@follow|Follow " + name + "@@");
- //mBrowserBox->addRow("@@buddy|Add " + name + " to Buddy List@@");
+
+ mBrowserBox->addRow("##3---");
+
+ switch (player_relations.getRelation(name)) {
+ 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(strprintf(_("@@guild|Invite %s@@"), name.c_str()));
mBrowserBox->addRow(strprintf(_("@@party|Invite %s to join your party@@"), name.c_str()));
+
+ mBrowserBox->addRow("##3---");
+ mBrowserBox->addRow(strprintf(_("@@party-invite|Invite %s to party@@"), name.c_str()));
}
break;
@@ -119,37 +148,76 @@ void PopupMenu::showPopup(int x, int y, FloorItem *floorItem)
void PopupMenu::handleLink(const std::string& link)
{
+ Being *being = beingManager->findBeing(mBeingId);
+
// Talk To action
if (link == "talk" &&
- mBeing != NULL &&
- mBeing->getType() == Being::NPC)
+ being &&
+ being->getType() == Being::NPC &&
+ current_npc == 0)
{
- static_cast<NPC*>(mBeing)->talk();
+ dynamic_cast<NPC*>(being)->talk();
}
// Trade action
else if (link == "trade" &&
- mBeing != NULL &&
- mBeing->getType() == Being::PLAYER)
+ being &&
+ being->getType() == Being::PLAYER)
+ {
+ player_node->trade(being);
+ tradePartnerName = being->getName();
+ }
+#ifdef EATHENA_SUPPORT
+ // Attack action
+ else if (link == "attack" &&
+ being &&
+ being->getType() == Being::PLAYER)
{
- player_node->trade(mBeing);
- tradePartnerName = mBeing->getName();
+ player_node->attack(being, true);
+ }
+#endif
+ else if (link == "unignore" &&
+ being &&
+ being->getType() == Being::PLAYER)
+ {
+ player_relations.setRelation(being->getName(), PlayerRelation::NEUTRAL);
}
+ else if (link == "ignore" &&
+ being &&
+ being->getType() == Being::PLAYER)
+ {
+ player_relations.setRelation(being->getName(), PlayerRelation::IGNORED);
+ }
+
+ else if (link == "disregard" &&
+ being &&
+ being->getType() == Being::PLAYER)
+ {
+ player_relations.setRelation(being->getName(), PlayerRelation::DISREGARDED);
+ }
+
+ else if (link == "friend" &&
+ being &&
+ being->getType() == Being::PLAYER)
+ {
+ player_relations.setRelation(being->getName(), PlayerRelation::FRIEND);
+ }
+#ifdef TMWSERV_SUPPORT
// Guild action
else if (link == "guild" &&
- mBeing != NULL &&
- mBeing->getType() == Being::PLAYER)
+ being != NULL &&
+ being->getType() == Being::PLAYER)
{
- player_node->inviteToGuild(mBeing);
+ player_node->inviteToGuild(being);
}
// Add player to your party
else if (link == "party")
{
- player_node->inviteToParty(mBeing->getName());
+ player_node->inviteToParty(being->getName());
}
-
+#endif
/*
// Follow Player action
else if (link == "follow")
@@ -158,16 +226,16 @@ void PopupMenu::handleLink(const std::string& link)
/*
// Add Buddy action
- else if ((link == "buddy") && mBeing != NULL && mBeing->isPlayer())
+ else if ((link == "buddy") && being && being->isPlayer())
{
if (!buddyWindow->isVisible())
buddyWindow->setVisible(true);
- buddyWindow->addBuddy(mBeing->getName());
+ buddyWindow->addBuddy(being->getName());
}*/
// Pick Up Floor Item action
- else if ((link == "pickup") && mFloorItem != NULL)
+ else if ((link == "pickup") && mFloorItem)
{
player_node->pickUp(mFloorItem);
}
@@ -182,13 +250,34 @@ void PopupMenu::handleLink(const std::string& link)
assert(mItem);
if (mItem->isEquipment())
{
+#ifdef TMWSERV_SUPPORT
player_node->equipItem(mItem);
+#else
+ if (mItem->isEquipped())
+ {
+ player_node->unequipItem(mItem);
+ }
+ else
+ {
+ player_node->equipItem(mItem);
+ }
+#endif
}
else
{
+#ifdef TMWSERV_SUPPORT
player_node->useItem(mItem->getInvIndex());
+#else
+ player_node->useItem(mItem);
+#endif
}
}
+
+ else if (link == "chat")
+ {
+ chatWindow->addItemText(mItem->getInfo().getName());
+ }
+
else if (link == "split")
{
new ItemAmountWindow(AMOUNT_ITEM_SPLIT, inventoryWindow, mItem);
@@ -197,12 +286,16 @@ void PopupMenu::handleLink(const std::string& link)
{
new ItemAmountWindow(AMOUNT_ITEM_DROP, inventoryWindow, mItem);
}
-
- else if (link == "description")
+#ifdef EATHENA_SUPPORT
+ 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());
}
+#endif
// Unknown actions
else
@@ -212,7 +305,7 @@ void PopupMenu::handleLink(const std::string& link)
setVisible(false);
- mBeing = NULL;
+ mBeingId = 0;
mFloorItem = NULL;
mItem = NULL;
}
@@ -225,14 +318,24 @@ void PopupMenu::showPopup(int x, int y, Item *item)
if (item->isEquipment())
{
+#ifdef TMWSERV_SUPPORT
mBrowserBox->addRow(_("@@use|Equip@@"));
+#else
+ if (item->isEquipped())
+ mBrowserBox->addRow(_("@@use|Unequip@@"));
+ else
+ mBrowserBox->addRow(_("@@use|Equip@@"));
+#endif
}
else
mBrowserBox->addRow(_("@@use|Use@@"));
+
mBrowserBox->addRow(_("@@drop|Drop@@"));
- mBrowserBox->addRow(_("@@description|Description@@"));
+#ifdef TMWSERV_SUPPORT
if (!item->isEquipment())
- { mBrowserBox->addRow(_("@@split|Split@@")); }
+ mBrowserBox->addRow(_("@@split|Split@@"));
+#endif
+ 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 2d10e6eb..2694abd8 100644
--- a/src/gui/popupmenu.h
+++ b/src/gui/popupmenu.h
@@ -1,36 +1,37 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_POPUP_MENU_H
-#define _TMW_POPUP_MENU_H
+#ifndef POPUP_MENU_H
+#define POPUP_MENU_H
+
+#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.
*/
@@ -67,7 +68,7 @@ class PopupMenu : public Window, public LinkHandler
private:
BrowserBox* mBrowserBox;
- Being* mBeing;
+ Uint32 mBeingId;
FloorItem* mFloorItem;
Item *mItem;
diff --git a/src/gui/progressbar.cpp b/src/gui/progressbar.cpp
index 9a47eefc..85f21604 100644
--- a/src/gui/progressbar.cpp
+++ b/src/gui/progressbar.cpp
@@ -1,26 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 "gui.h"
#include "progressbar.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
@@ -28,6 +32,7 @@
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,
@@ -56,6 +61,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();
}
@@ -109,32 +120,62 @@ void ProgressBar::logic()
mProgress = mProgressToGo;
}
-void
-ProgressBar::draw(gcn::Graphics *graphics)
+void ProgressBar::draw(gcn::Graphics *graphics)
{
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ 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 = (int)(mAlpha * 255.0f);
+
// 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)),
+ (int) (mProgress * (getWidth() - 8)),
getHeight() - 8));
}
+
+ // The label
+ if (!mText.empty())
+ {
+ 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, 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, alpha));
+ graphics->drawText(mText, textX, textY, gcn::Graphics::CENTER);
+
+ graphics->setColor(gcn::Color(0, 0, 0));
+ }
}
-void
-ProgressBar::setProgress(float progress)
+void ProgressBar::setProgress(float progress)
{
if (progress < 0.0f) mProgressToGo = 0.0;
else if (progress > 1.0f) mProgressToGo = 1.0;
else mProgressToGo = progress;
}
-void
-ProgressBar::setColor(Uint8 red, Uint8 green, Uint8 blue)
+void ProgressBar::setColor(Uint8 red, Uint8 green, Uint8 blue)
{
mRedToGo = red;
mGreenToGo = green;
diff --git a/src/gui/progressbar.h b/src/gui/progressbar.h
index 0b1616f5..49bc3edd 100644
--- a/src/gui/progressbar.h
+++ b/src/gui/progressbar.h
@@ -1,26 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_PROGRESSBAR_H
-#define _TMW_PROGRESSBAR_H
+#ifndef PROGRESSBAR_H
+#define PROGRESSBAR_H
+
+#include <string>
#include <guichan/widget.hpp>
@@ -28,13 +30,13 @@
class ImageRect;
-
/**
* A progress bar.
*
* \ingroup GUI
*/
-class ProgressBar : public gcn::Widget {
+class ProgressBar : public gcn::Widget
+{
public:
/**
* Constructor, initializes the progress with the given value.
@@ -51,63 +53,65 @@ class ProgressBar : public gcn::Widget {
/**
* Performs progress bar logic (fading colors)
*/
- void
- logic();
+ void logic();
/**
* Draws the progress bar.
*/
- void
- draw(gcn::Graphics *graphics);
+ void draw(gcn::Graphics *graphics);
/**
* Sets the current progress.
*/
- void
- setProgress(float progress);
+ void setProgress(float progress);
/**
* Returns the current progress.
*/
- float
- getProgress() { return mProgress; }
+ float getProgress() const { return mProgress; }
/**
* Change the filling of the progress bar.
*/
- void
- setColor(Uint8, Uint8 green, Uint8 blue);
+ void setColor(Uint8, Uint8 green, Uint8 blue);
+
+ /**
+ * Returns the red value of color.
+ */
+ Uint8 getRed() const { return mRed; }
/**
- * Get The red value of color
+ * Returns the green value of color.
*/
- Uint8
- getRed() { return mRed; }
+ Uint8 getGreen() const { return mGreen; }
- /**
- * Get The red value of color
+ /**
+ * Returns the blue value of color.
*/
- Uint8
- getGreen() { return mGreen; }
+ Uint8 getBlue() const { return mBlue; }
/**
- * Get The red value of color
+ * Sets the text shown on the progress bar.
*/
- Uint8
- getBlue() { return mBlue; }
+ void setText(const std::string &text)
+ { mText = text; }
/**
- * Set wether the progress is moved smoothly
+ * Returns the text shown on the progress bar.
*/
- void
- setSmoothProgress(bool smoothProgress)
+ const std::string &text() const
+ { return mText; }
+
+ /**
+ * Set wether the progress is moved smoothly.
+ */
+ void setSmoothProgress(bool smoothProgress)
{ mSmoothProgress = smoothProgress; }
/**
- * Set wether the color changing is made smoothly
+ * Set wether the color changing is made smoothly.
*/
- void
- setSmoothColorChange(bool smoothColorChange)
+ void setSmoothColorChange(bool smoothColorChange)
{ mSmoothColorChange = smoothColorChange; }
@@ -119,8 +123,11 @@ class ProgressBar : public gcn::Widget {
Uint8 mRedToGo, mGreenToGo, mBlueToGo;
bool mSmoothColorChange;
+ std::string mText;
+
static ImageRect mBorder;
static int mInstances;
+ static float mAlpha;
};
#endif
diff --git a/src/gui/radiobutton.cpp b/src/gui/radiobutton.cpp
index 619ec84f..c8ae2fad 100644
--- a/src/gui/radiobutton.cpp
+++ b/src/gui/radiobutton.cpp
@@ -1,32 +1,34 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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 09f703dc..3d952b3f 100644
--- a/src/gui/radiobutton.h
+++ b/src/gui/radiobutton.h
@@ -1,36 +1,36 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_RADIOBUTTON_H
-#define _TMW_RADIOBUTTON_H
+#ifndef RADIOBUTTON_H
+#define RADIOBUTTON_H
#include <guichan/widgets/radiobutton.hpp>
class Image;
-
/*
* Guichan based RadioButton with custom look
*/
-class RadioButton : public gcn::RadioButton {
+class RadioButton : public gcn::RadioButton
+{
public:
/*
* Constructor.
@@ -56,10 +56,11 @@ class RadioButton : public gcn::RadioButton {
private:
static int instances;
+ static float mAlpha;
static Image *radioNormal;
static Image *radioChecked;
static Image *radioDisabled;
static Image *radioDisabledChecked;
};
-#endif /* _TMW_RADIOBUTTON_H */
+#endif /* RADIOBUTTON_H */
diff --git a/src/gui/recorder.cpp b/src/gui/recorder.cpp
new file mode 100644
index 00000000..ce097db2
--- /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/stringutils.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 051c0fa4..216ac211 100644
--- a/src/gui/register.cpp
+++ b/src/gui/register.cpp
@@ -1,55 +1,52 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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/stringutils.h"
-void
-WrongDataNoticeListener::setTarget(gcn::TextField *textField)
+void WrongDataNoticeListener::setTarget(gcn::TextField *textField)
{
mTarget = textField;
}
-void
-WrongDataNoticeListener::action(const gcn::ActionEvent &event)
+void WrongDataNoticeListener::action(const gcn::ActionEvent &event)
{
if (event.getId() == "ok")
{
@@ -57,54 +54,61 @@ WrongDataNoticeListener::action(const gcn::ActionEvent &event)
}
}
+
RegisterDialog::RegisterDialog(LoginData *loginData):
Window(_("Register")),
- mWrongDataNoticeListener(new WrongDataNoticeListener()),
+ mWrongDataNoticeListener(new WrongDataNoticeListener),
mLoginData(loginData)
{
gcn::Label *userLabel = new gcn::Label(_("Name:"));
gcn::Label *passwordLabel = new gcn::Label(_("Password:"));
gcn::Label *confirmLabel = new gcn::Label(_("Confirm:"));
- gcn::Label *emailLabel = new gcn::Label(_("Email:"));
+#ifdef EATHENA_SUPPORT
+ gcn::Label *serverLabel = new gcn::Label(_("Server:"));
+ gcn::Label *portLabel = new gcn::Label(_("Port:"));
+#endif
mUserField = new TextField(loginData->username);
mPasswordField = new PasswordField(loginData->password);
- mConfirmField = new PasswordField();
- mEmailField = new TextField();
+ mConfirmField = new PasswordField;
+#ifdef EATHENA_SUPPORT
+ mServerField = new TextField(loginData->hostname);
+ mPortField = new TextField(toString(loginData->port));
+ mMaleButton = new RadioButton(_("Male"), "sex", true);
+ mFemaleButton = new RadioButton(_("Female"), "sex", false);
+#endif
mRegisterButton = new Button(_("Register"), "register", this);
mCancelButton = new Button(_("Cancel"), "cancel", this);
- const int width = 220;
- const int height = 130;
- setContentSize(width, height);
-
- mUserField->setPosition(65, 5);
- mUserField->setWidth(width - 70);
- mPasswordField->setPosition(
- 65, mUserField->getY() + mUserField->getHeight() + 7);
- mPasswordField->setWidth(mUserField->getWidth());
- mConfirmField->setPosition(
- 65, mPasswordField->getY() + mPasswordField->getHeight() + 7);
- mConfirmField->setWidth(mUserField->getWidth());
- mEmailField->setPosition(
- 65, mConfirmField->getY() + mConfirmField->getHeight() + 7);
- mEmailField->setWidth(mUserField->getWidth());
-
- userLabel->setPosition(5, mUserField->getY() + 1);
- passwordLabel->setPosition(5, mPasswordField->getY() + 1);
- confirmLabel->setPosition(5, mConfirmField->getY() + 1);
- emailLabel->setPosition(5, mEmailField->getY() + 1);
-
- mCancelButton->setPosition(
- width - mCancelButton->getWidth() - 5,
- height - mCancelButton->getHeight() - 5);
- mRegisterButton->setPosition(
- mCancelButton->getX() - mRegisterButton->getWidth() - 5,
- height - mRegisterButton->getHeight() - 5);
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
+ place(0, 0, userLabel);
+ place(0, 1, passwordLabel);
+ place(0, 2, confirmLabel);
+#ifdef EATHENA_SUPPORT
+ place(1, 3, mMaleButton);
+ place(2, 3, mFemaleButton);
+ place(0, 4, serverLabel);
+ place(0, 5, portLabel);
+#endif
+ place(1, 0, mUserField, 3).setPadding(2);
+ place(1, 1, mPasswordField, 3).setPadding(2);
+ place(1, 2, mConfirmField, 3).setPadding(2);
+#ifdef EATHENA_SUPPORT
+ place(1, 4, mServerField, 3).setPadding(2);
+ place(1, 5, mPortField, 3).setPadding(2);
+#endif
+ place = getPlacer(0, 2);
+ place(1, 0, mRegisterButton);
+ place(2, 0, mCancelButton);
+ reflowLayout(250, 0);
mUserField->addKeyListener(this);
mPasswordField->addKeyListener(this);
mConfirmField->addKeyListener(this);
- mEmailField->addKeyListener(this);
+#ifdef EATHENA_SUPPORT
+ mServerField->addKeyListener(this);
+ mPortField->addKeyListener(this);
+#endif
/* TODO:
* This is a quick and dirty way to respond to the ENTER key, regardless of
@@ -114,22 +118,18 @@ RegisterDialog::RegisterDialog(LoginData *loginData):
mUserField->setActionEventId("register");
mPasswordField->setActionEventId("register");
mConfirmField->setActionEventId("register");
- mEmailField->setActionEventId("register");
+
mUserField->addActionListener(this);
mPasswordField->addActionListener(this);
mConfirmField->addActionListener(this);
- mEmailField->addActionListener(this);
-
- add(userLabel);
- add(passwordLabel);
- add(emailLabel);
- add(confirmLabel);
- add(mUserField);
- add(mPasswordField);
- add(mConfirmField);
- add(mEmailField);
- add(mRegisterButton);
- add(mCancelButton);
+
+#ifdef EATHENA_SUPPORT
+ mServerField->setActionEventId("register");
+ mPortField->setActionEventId("register");
+
+ mServerField->addActionListener(this);
+ mPortField->addActionListener(this);
+#endif
setLocationRelativeTo(getParent());
setVisible(true);
@@ -144,8 +144,7 @@ RegisterDialog::~RegisterDialog()
delete mWrongDataNoticeListener;
}
-void
-RegisterDialog::action(const gcn::ActionEvent &event)
+void RegisterDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "cancel")
{
@@ -225,25 +224,73 @@ RegisterDialog::action(const gcn::ActionEvent &event)
mLoginData->username = mUserField->getText();
mLoginData->password = mPasswordField->getText();
+#ifdef EATHENA_SUPPORT
+ mLoginData->hostname = mServerField->getText();
+ mLoginData->port = getUShort(mPortField->getText());
+ mLoginData->username += mFemaleButton->isSelected() ? "_F" : "_M";
+#else
mLoginData->email = mEmailField->getText();
+#endif
mLoginData->registerLogin = true;
+#ifdef TMWSERV_SUPPORT
state = STATE_REGISTER_ATTEMPT;
+#else
+ state = STATE_ACCOUNT;
+#endif
}
}
}
-void
-RegisterDialog::keyPressed(gcn::KeyEvent &keyEvent)
+void RegisterDialog::keyPressed(gcn::KeyEvent &keyEvent)
{
mRegisterButton->setEnabled(canSubmit());
}
-bool
-RegisterDialog::canSubmit()
+bool RegisterDialog::canSubmit() const
{
return !mUserField->getText().empty() &&
!mPasswordField->getText().empty() &&
!mConfirmField->getText().empty() &&
+#ifdef EATHENA_SUPPORT
+ !mServerField->getText().empty() &&
+ isUShort(mPortField->getText()) &&
+#endif
state == STATE_REGISTER;
}
+
+#ifdef EATHENA_SUPPORT
+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);
+}
+#endif
diff --git a/src/gui/register.h b/src/gui/register.h
index 79578461..fde82a40 100644
--- a/src/gui/register.h
+++ b/src/gui/register.h
@@ -1,33 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_REGISTER_H
-#define _TMW_REGISTER_H
+#ifndef REGISTER_H
+#define REGISTER_H
+
+#include <string>
-#include <iosfwd>
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
class LoginData;
class OkDialog;
@@ -82,16 +82,44 @@ class RegisterDialog : public Window, public gcn::ActionListener,
* Returns whether submit can be enabled. This is true in the register
* state, when all necessary fields have some text.
*/
- bool
- canSubmit();
+ bool canSubmit() const;
+
+#ifdef EATHENA_SUPPORT
+ /**
+ * 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);
+#endif
gcn::TextField *mUserField;
gcn::TextField *mPasswordField;
gcn::TextField *mConfirmField;
+#ifdef EATHENA_SUPPORT
+ gcn::TextField *mServerField;
+ gcn::TextField *mPortField;
+#else
gcn::TextField *mEmailField;
+#endif
gcn::Button *mRegisterButton;
gcn::Button *mCancelButton;
+#ifdef EATHENA_SUPPORT
+ gcn::RadioButton *mMaleButton;
+ gcn::RadioButton *mFemaleButton;
+#endif
WrongDataNoticeListener *mWrongDataNoticeListener;
diff --git a/src/gui/scrollarea.cpp b/src/gui/scrollarea.cpp
index 032e3f78..70504a03 100644
--- a/src/gui/scrollarea.cpp
+++ b/src/gui/scrollarea.cpp
@@ -1,28 +1,27 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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,20 +30,21 @@
#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():
gcn::ScrollArea(),
- mGC(gc)
+ mOpaque(true)
{
init();
}
-ScrollArea::ScrollArea(gcn::Widget *widget, bool gc):
+ScrollArea::ScrollArea(gcn::Widget *widget):
gcn::ScrollArea(widget),
- mGC(gc)
+ mOpaque(true)
{
init();
}
@@ -52,9 +52,7 @@ ScrollArea::ScrollArea(gcn::Widget *widget, bool gc):
ScrollArea::~ScrollArea()
{
// Garbage collection
- if (mGC) {
- delete getContent();
- }
+ delete getContent();
instances--;
@@ -88,12 +86,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 +107,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 +150,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 +192,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 +211,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 +222,12 @@ void ScrollArea::setOpaque(bool opaque)
{
mOpaque = opaque;
- if (mOpaque) {
+ if (mOpaque)
+ {
setFrameSize(2);
}
- else {
+ else
+ {
setFrameSize(0);
}
}
@@ -220,7 +237,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 d21dae11..e9aa5ed2 100644
--- a/src/gui/scrollarea.h
+++ b/src/gui/scrollarea.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __TMW_SCROLLAREA_H__
-#define __TMW_SCROLLAREA_H__
+#ifndef SCROLLAREA_H
+#define SCROLLAREA_H
#include <guichan/widgets/scrollarea.hpp>
@@ -30,6 +30,10 @@ class ImageRect;
/**
* A scroll area.
*
+ * Contrary to Guichan's scroll area, this scroll area takes ownership over its
+ * content. However, it won't delete a previously set content widget when
+ * setContent is called!
+ *
* \ingroup GUI
*/
class ScrollArea : public gcn::ScrollArea
@@ -38,12 +42,12 @@ class ScrollArea : public gcn::ScrollArea
/**
* Constructor.
*/
- ScrollArea(bool gc = true);
+ ScrollArea();
/**
* Constructor.
*/
- ScrollArea(gcn::Widget *content, bool gc = true);
+ ScrollArea(gcn::Widget *content);
/**
* Destructor.
@@ -100,12 +104,12 @@ 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];
bool mOpaque;
- bool mGC;
};
#endif
diff --git a/src/gui/sdlinput.cpp b/src/gui/sdlinput.cpp
index ee94b2c6..51442798 100644
--- a/src/gui/sdlinput.cpp
+++ b/src/gui/sdlinput.cpp
@@ -7,7 +7,7 @@
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004, 2005, 2006, 2007 Olof Naessén and Per Larsson
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 2007 The Mana World Development Team
*
* Js_./
* Per Larsson a.k.a finalman _RqZ{a<^_aa
@@ -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/sdlinput.h b/src/gui/sdlinput.h
index 72d949e1..3901589a 100644
--- a/src/gui/sdlinput.h
+++ b/src/gui/sdlinput.h
@@ -7,7 +7,7 @@
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004, 2005, 2006, 2007 Olof Naessén and Per Larsson
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 2007 The Mana World Development Team
*
* Js_./
* Per Larsson a.k.a finalman _RqZ{a<^_aa
@@ -55,8 +55,8 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _TMW_SDLINPUT_
-#define _TMW_SDLINPUT_
+#ifndef SDLINPUT_
+#define SDLINPUT_
#include <queue>
diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp
index 9aee4bee..957ff861 100644
--- a/src/gui/sell.cpp
+++ b/src/gui/sell.cpp
@@ -1,47 +1,56 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 "../units.h"
+
+#include "../net/messageout.h"
+#ifdef TMWSERV_SUPPORT
#include "../net/gameserver/player.h"
-#include "../resources/iteminfo.h"
+#else
+#include "../net/ea/protocol.h"
+#endif
+
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
+#ifdef TMWSERV_SUPPORT
SellDialog::SellDialog():
Window(_("Sell")),
+#else
+SellDialog::SellDialog(Network *network):
+ Window(_("Sell")),
+ mNetwork(network),
+#endif
mMaxItems(0), mAmountItems(0)
{
setWindowName("Sell");
@@ -50,13 +59,14 @@ SellDialog::SellDialog():
setMinHeight(230);
setDefaultSize(0, 0, 260, 230);
- mShopItems = new ShopItems();
+ mShopItems = new ShopItems;
mShopItemList = new ShopListBox(mShopItems, mShopItems);
mScrollArea = new ScrollArea(mShopItemList);
mSlider = new Slider(1.0);
mQuantityLabel = new gcn::Label("0");
- mMoneyLabel = new gcn::Label(strprintf(_("Price: %d GP / Total: %d GP"), 0, 0));
+ mMoneyLabel = new gcn::Label(strprintf(_("Price: %s / Total: %s"),
+ "", ""));
mIncreaseButton = new Button("+", "+", this);
mDecreaseButton = new Button("-", "-", this);
mSellButton = new Button(_("Sell"), "sell", this);
@@ -111,12 +121,30 @@ void SellDialog::reset()
updateButtonsAndLabels();
}
+#ifdef TMWSERV_SUPPORT
+
void SellDialog::addItem(int item, int amount, int price)
{
mShopItems->addItem(item, amount, price);
mShopItemList->adjustSize();
}
+#else
+
+void SellDialog::addItem(const Item *item, int price)
+{
+ if (!item)
+ return;
+
+ mShopItems->addItem(
+ item->getInvIndex(), item->getId(),
+ item->getQuantity(), price);
+
+ mShopItemList->adjustSize();
+}
+
+#endif
+
void SellDialog::action(const gcn::ActionEvent &event)
{
int selectedItem = mShopItemList->getSelected();
@@ -124,7 +152,7 @@ void SellDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "quit")
{
setVisible(false);
- current_npc = 0;
+ if (current_npc) current_npc->handleDeath();
return;
}
@@ -155,8 +183,17 @@ void SellDialog::action(const gcn::ActionEvent &event)
else if (event.getId() == "sell" && mAmountItems > 0
&& mAmountItems <= mMaxItems)
{
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::tradeWithNPC
(mShopItems->at(selectedItem)->getId(), mAmountItems);
+#else
+ // Attempt sell
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_NPC_SELL_REQUEST);
+ outMsg.writeInt16(8);
+ outMsg.writeInt16(mShopItems->at(selectedItem)->getInvIndex());
+ outMsg.writeInt16(mAmountItems);
+#endif
mMaxItems -= mAmountItems;
mShopItems->getShop()->at(selectedItem)->setQuantity(mMaxItems);
@@ -239,7 +276,7 @@ void SellDialog::updateButtonsAndLabels()
// Update the quantity and money labels
mQuantityLabel->setCaption(strprintf("%d / %d", mAmountItems, mMaxItems));
- mMoneyLabel->setCaption
- (strprintf(_("Price: %d GP / Total: %d GP"),
- income, mPlayerMoney + income));
+ mMoneyLabel->setCaption(strprintf(_("Price: %s / Total: %s"),
+ Units::formatCurrency(income).c_str(),
+ Units::formatCurrency(mPlayerMoney - income).c_str()));
}
diff --git a/src/gui/sell.h b/src/gui/sell.h
index 742c28fb..f64a6fd5 100644
--- a/src/gui/sell.h
+++ b/src/gui/sell.h
@@ -1,35 +1,38 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SELL_H
-#define _TMW_SELL_H
+#ifndef SELL_H
+#define SELL_H
#include <guichan/actionlistener.hpp>
#include <guichan/selectionlistener.hpp>
-#include "window.h"
+#include <SDL_types.h>
-#include "../guichanfwd.h"
+#include "window.h"
class Item;
+#ifdef EATHENA_SUPPORT
+class Network;
+#endif
class ShopItems;
class ShopListBox;
@@ -46,7 +49,11 @@ class SellDialog : public Window, gcn::ActionListener, gcn::SelectionListener
*
* @see Window::Window
*/
+#ifdef TMWSERV_SUPPORT
SellDialog();
+#else
+ SellDialog(Network *network);
+#endif
/**
* Destructor
@@ -61,7 +68,11 @@ class SellDialog : public Window, gcn::ActionListener, gcn::SelectionListener
/**
* Adds an item to the inventory.
*/
+#ifdef TMWSERV_SUPPORT
void addItem(int item, int amount, int price);
+#else
+ void addItem(const Item *item, int price);
+#endif
/**
* Called when receiving actions from the widgets.
@@ -86,6 +97,9 @@ class SellDialog : public Window, gcn::ActionListener, gcn::SelectionListener
*/
void updateButtonsAndLabels();
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+#endif
gcn::Button *mSellButton;
gcn::Button *mQuitButton;
gcn::Button *mIncreaseButton;
diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp
index b11aea6c..a8074b0c 100644
--- a/src/gui/serverdialog.cpp
+++ b/src/gui/serverdialog.cpp
@@ -41,7 +41,7 @@
#include "../main.h"
#include "../utils/gettext.h"
-#include "../utils/tostring.h"
+#include "../utils/stringutils.h"
const short MAX_SERVERLIST = 5;
diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp
index 59b54be0..c8b7f900 100644
--- a/src/gui/setup.cpp
+++ b/src/gui/setup.cpp
@@ -1,71 +1,80 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <algorithm>
-
-#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"
-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;
+#ifdef TMWSERV_SUPPORT
extern Window *magicDialog;
extern Window *guildWindow;
-extern Window *itemShortcutWindow;
+#endif
Setup::Setup():
Window(_("Setup"))
{
setCloseButton(true);
- int width = 260;
- int height = 265;
+ int width = 340;
+ int height = 340;
setContentSize(width, height);
static const char *buttonNames[] = {
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);
add(btn);
+
+ // Disable this button when the windows aren't created yet
+ if (!strcmp(*curBtn, "Reset Windows"))
+ btn->setEnabled(statusWindow != NULL);
}
- TabbedArea *panel = new TabbedArea();
- panel->setDimension(gcn::Rectangle(5, 5, 260, 225));
+ TabbedArea *panel = new TabbedArea;
+ panel->setDimension(gcn::Rectangle(5, 5, width - 10, height - 40));
SetupTab *tab;
@@ -85,6 +94,14 @@ 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);
+
add(panel);
setLocationRelativeTo(getParent());
@@ -109,6 +126,11 @@ void Setup::action(const gcn::ActionEvent &event)
}
else if (event.getId() == "Reset Windows")
{
+ // Bail out if this action happens to be activated before the windows
+ // are created (though it should be disabled then)
+ if (!statusWindow)
+ return;
+
statusWindow->resetToDefaultSize();
minimap->resetToDefaultSize();
chatWindow->resetToDefaultSize();
@@ -116,8 +138,13 @@ void Setup::action(const gcn::ActionEvent &event)
equipmentWindow->resetToDefaultSize();
helpWindow->resetToDefaultSize();
skillDialog->resetToDefaultSize();
+ itemShortcutWindow->resetToDefaultSize();
+ emoteShortcutWindow->resetToDefaultSize();
+ emoteWindow->resetToDefaultSize();
+ tradeWindow->resetToDefaultSize();
+#ifdef TMWSERV_SUPPORT
magicDialog->resetToDefaultSize();
guildWindow->resetToDefaultSize();
- itemShortcutWindow->resetToDefaultSize();
+#endif
}
}
diff --git a/src/gui/setup.h b/src/gui/setup.h
index 2142a67d..e4eb0902 100644
--- a/src/gui/setup.h
+++ b/src/gui/setup.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SETUP_H
-#define _TMW_SETUP_H
+#ifndef SETUP_H
+#define SETUP_H
#include <list>
@@ -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 4f09cde0..43cc28e6 100644
--- a/src/gui/setup_audio.cpp
+++ b/src/gui/setup_audio.cpp
@@ -1,32 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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"
+
#include "../configuration.h"
#include "../log.h"
#include "../sound.h"
@@ -54,19 +55,24 @@ Setup_Audio::Setup_Audio():
mMusicSlider->addActionListener(this);
mSoundCheckBox->setPosition(10, 10);
- mSfxSlider->setDimension(gcn::Rectangle(10, 30, 100, 10));
- mMusicSlider->setDimension(gcn::Rectangle(10, 50, 100, 10));
- sfxLabel->setPosition(20 + mSfxSlider->getWidth(), 27);
- musicLabel->setPosition(20 + mMusicSlider->getWidth(), 47);
mSfxSlider->setValue(mSfxVolume);
mMusicSlider->setValue(mMusicVolume);
- add(mSoundCheckBox);
- add(mSfxSlider);
- add(mMusicSlider);
- add(sfxLabel);
- add(musicLabel);
+ mSfxSlider->setWidth(90);
+ mMusicSlider->setWidth(90);
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, mSoundCheckBox);
+ place(0, 1, mSfxSlider);
+ place(1, 1, sfxLabel);
+ place(0, 2, mMusicSlider);
+ place(1, 2, musicLabel);
+
+ setDimension(gcn::Rectangle(0, 0, 325, 280));
}
void Setup_Audio::apply()
@@ -104,8 +110,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 eaa55de6..9e951895 100644
--- a/src/gui/setup_audio.h
+++ b/src/gui/setup_audio.h
@@ -1,32 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_GUI_SETUP_AUDIO_H
-#define _TMW_GUI_SETUP_AUDIO_H
-
-#include "setuptab.h"
+#ifndef GUI_SETUP_AUDIO_H
+#define GUI_SETUP_AUDIO_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..49c99996
--- /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/stringutils.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, 325, 280));
+}
+
+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..2831297f
--- /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_COLORS_H
+#define SETUP_COLORS_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 9de5be9f..c0c04949 100644
--- a/src/gui/setup_joystick.cpp
+++ b/src/gui/setup_joystick.cpp
@@ -1,30 +1,32 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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"
+
#include "../configuration.h"
#include "../joystick.h"
@@ -38,25 +40,29 @@ Setup_Joystick::Setup_Joystick():
mJoystickEnabled(new CheckBox(_("Enable joystick")))
{
setOpaque(false);
- setDimension(gcn::Rectangle(0, 0, 250, 200));
- mJoystickEnabled->setPosition(10, 10);
- mCalibrateLabel->setPosition(10, 25);
- mCalibrateButton->setPosition(10, 30 + mCalibrateLabel->getHeight());
-
- mOriginalJoystickEnabled = (int)config.getValue("joystickEnabled", 0) != 0;
+ mOriginalJoystickEnabled = !config.getValue("joystickEnabled", false);
mJoystickEnabled->setSelected(mOriginalJoystickEnabled);
mJoystickEnabled->addActionListener(this);
- add(mCalibrateLabel);
- add(mCalibrateButton);
- add(mJoystickEnabled);
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, mJoystickEnabled);
+ place(0, 1, mCalibrateLabel);
+ place.getCell().matchColWidth(0, 0);
+ place = h.getPlacer(0, 1);
+ place(0, 0, mCalibrateButton);
+
+ setDimension(gcn::Rectangle(0, 0, 325, 75));
}
void Setup_Joystick::action(const gcn::ActionEvent &event)
{
- if (!joystick) {
+ if (!joystick)
+ {
return;
}
@@ -66,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 0b7ebe98..eba8a2cc 100644
--- a/src/gui/setup_joystick.h
+++ b/src/gui/setup_joystick.h
@@ -1,32 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_GUI_SETUP_JOYSTICK_H
-#define _TMW_GUI_SETUP_JOYSTICK_H
-
-#include "setuptab.h"
+#ifndef GUI_SETUP_JOYSTICK_H
+#define GUI_SETUP_JOYSTICK_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 e4d1af0c..aba8cf35 100644
--- a/src/gui/setup_keyboard.cpp
+++ b/src/gui/setup_keyboard.cpp
@@ -1,25 +1,26 @@
/*
- * The Mana World
- * Copyright 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.
*
- * The Mana World is free software; you can redistribute it and/or modify
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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,14 +29,14 @@
#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>
+#include "../utils/stringutils.h"
/**
* The list model for key function list.
@@ -68,34 +69,36 @@ class KeyListModel : public gcn::ListModel
};
Setup_Keyboard::Setup_Keyboard():
- mKeyListModel(new KeyListModel()),
+ mKeyListModel(new KeyListModel),
mKeyList(new ListBox(mKeyListModel)),
mKeySetting(false)
{
keyboard.setSetupKeyboard(this);
setOpaque(false);
- setDimension(gcn::Rectangle(0, 0, 250, 200));
refreshKeys();
- mKeyList->setDimension(gcn::Rectangle(0, 0, 185, 140));
mKeyList->addActionListener(this);
- mKeyList->setSelected(-1);
ScrollArea *scrollArea = new ScrollArea(mKeyList);
- scrollArea->setDimension(gcn::Rectangle(10, 10, 200, 140));
- add(scrollArea);
+ scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
mAssignKeyButton = new Button(_("Assign"), "assign", this);
- mAssignKeyButton->setPosition(165, 155);
mAssignKeyButton->addActionListener(this);
mAssignKeyButton->setEnabled(false);
- add(mAssignKeyButton);
mMakeDefaultButton = new Button(_("Default"), "makeDefault", this);
- mMakeDefaultButton->setPosition(10, 155);
mMakeDefaultButton->addActionListener(this);
- add(mMakeDefaultButton);
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, scrollArea, 4, 6).setPadding(2);
+ place(0, 6, mMakeDefaultButton);
+ place(3, 6, mAssignKeyButton);
+
+ setDimension(gcn::Rectangle(0, 0, 325, 280));
}
Setup_Keyboard::~Setup_Keyboard()
@@ -135,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")
{
@@ -181,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 50fa76fb..dee12135 100644
--- a/src/gui/setup_keyboard.h
+++ b/src/gui/setup_keyboard.h
@@ -1,35 +1,34 @@
/*
- * The Mana World
- * Copyright 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.
*
- * The Mana World is free software; you can redistribute it and/or modify
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_GUI_SETUP_KEYBOARD_H
-#define _TMW_GUI_SETUP_KEYBOARD_H
+#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
new file mode 100644
index 00000000..96792436
--- /dev/null
+++ b/src/gui/setup_players.cpp
@@ -0,0 +1,388 @@
+/*
+ * The Mana World
+ * 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
+ */
+
+#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 "../utils/gettext.h"
+
+#define COLUMNS_NR 2 // name plus listbox
+#define NAME_COLUMN 0
+#define RELATION_CHOICE_COLUMN 1
+
+#define ROW_HEIGHT 12
+// The following column widths really shouldn't be hardcoded but should scale with the size of the widget... except
+// that, right now, the widget doesn't exactly scale either.
+#define NAME_COLUMN_WIDTH 230
+#define RELATION_CHOICE_COLUMN_WIDTH 80
+
+#define WIDGET_AT(row, column) (((row) * COLUMNS_NR) + column)
+
+static const char *table_titles[COLUMNS_NR] =
+{
+ N_("Name"),
+ N_("Relation")
+};
+
+static const char *RELATION_NAMES[PlayerRelation::RELATIONS_NR] =
+{
+ N_("Neutral"),
+ N_("Friend"),
+ N_("Disregarded"),
+ N_("Ignored")
+};
+
+class PlayerRelationListModel : public gcn::ListModel
+{
+public:
+ virtual ~PlayerRelationListModel() { }
+
+ virtual int getNumberOfElements()
+ {
+ return PlayerRelation::RELATIONS_NR;
+ }
+
+ virtual std::string getElementAt(int i)
+ {
+ if (i >= getNumberOfElements() || i < 0)
+ return "";
+ return gettext(RELATION_NAMES[i]);
+ }
+};
+
+class PlayerTableModel : public TableModel
+{
+public:
+ PlayerTableModel() :
+ mPlayers(NULL)
+ {
+ playerRelationsUpdated();
+ }
+
+ virtual ~PlayerTableModel()
+ {
+ freeWidgets();
+ if (mPlayers)
+ delete mPlayers;
+ }
+
+ virtual int getRows()
+ {
+ return mPlayers->size();
+ }
+
+ virtual int getColumns()
+ {
+ return COLUMNS_NR;
+ }
+
+ virtual int getRowHeight()
+ {
+ return ROW_HEIGHT;
+ }
+
+ virtual int getColumnWidth(int index)
+ {
+ if (index == NAME_COLUMN)
+ return NAME_COLUMN_WIDTH;
+ else
+ return RELATION_CHOICE_COLUMN_WIDTH;
+ }
+
+ virtual void playerRelationsUpdated()
+ {
+ signalBeforeUpdate();
+
+ freeWidgets();
+ std::vector<std::string> *player_names = player_relations.getPlayers();
+ if (mPlayers)
+ delete mPlayers;
+ mPlayers = player_names;
+
+ // set up widgets
+ for (unsigned int r = 0; r < player_names->size(); ++r)
+ {
+ 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 DropDown(playerRelation,
+ new ScrollArea,
+ new ListBox(playerRelation),
+ false);
+ choicebox->setSelected(player_relations.getRelation(name));
+ mWidgets.push_back(choicebox);
+ }
+
+ signalAfterUpdate();
+ }
+
+ virtual void updateModelInRow(int row)
+ {
+ gcn::DropDown *choicebox = dynamic_cast<gcn::DropDown *>(
+ getElementAt(row, RELATION_CHOICE_COLUMN));
+ player_relations.setRelation(getPlayerAt(row),
+ static_cast<PlayerRelation::relation>(
+ choicebox->getSelected()));
+ }
+
+
+ virtual gcn::Widget *getElementAt(int row, int column)
+ {
+ return mWidgets[WIDGET_AT(row, column)];
+ }
+
+ virtual void freeWidgets()
+ {
+ if (mPlayers)
+ delete mPlayers;
+ mPlayers = NULL;
+
+ for (std::vector<gcn::Widget *>::const_iterator it = mWidgets.begin();
+ it != mWidgets.end(); it++)
+ {
+ delete *it;
+ }
+
+ mWidgets.clear();
+ }
+
+ std::string getPlayerAt(int index)
+ {
+ return (*mPlayers)[index];
+ }
+
+protected:
+ std::vector<std::string> *mPlayers;
+ std::vector<gcn::Widget *> mWidgets;
+};
+
+/**
+ * Class for choosing one of the various `what to do when ignoring a player' options
+ */
+class IgnoreChoicesListModel : public gcn::ListModel
+{
+public:
+ virtual ~IgnoreChoicesListModel() { }
+
+ virtual int getNumberOfElements()
+ {
+ return player_relations.getPlayerIgnoreStrategies()->size();
+ }
+
+ virtual std::string getElementAt(int i)
+ {
+ if (i >= getNumberOfElements())
+ return _("???");
+
+ return (*player_relations.getPlayerIgnoreStrategies())[i]->mDescription;
+ }
+};
+
+#define ACTION_DELETE "delete"
+#define ACTION_TABLE "table"
+#define ACTION_STRATEGY "strategy"
+
+Setup_Players::Setup_Players():
+ mPlayerTableTitleModel(new StaticTableModel(1, COLUMNS_NR)),
+ mPlayerTableModel(new PlayerTableModel),
+ mPlayerTable(new GuiTable(mPlayerTableModel)),
+ mPlayerTitleTable(new GuiTable(mPlayerTableTitleModel)),
+ mPlayerScrollArea(new ScrollArea(mPlayerTable)),
+ mPersistIgnores(new CheckBox(_("Save player list"),
+ player_relations.getPersistIgnores())),
+ mDefaultTrading(new CheckBox(_("Allow trading"),
+ player_relations.getDefault() & PlayerRelation::TRADE)),
+ mDefaultWhisper(new CheckBox(_("Allow whispers"),
+ player_relations.getDefault() & PlayerRelation::WHISPER)),
+ mDeleteButton(new Button(_("Delete"), ACTION_DELETE, this))
+{
+ setOpaque(false);
+ mPlayerTable->setOpaque(false);
+
+ mPlayerTableTitleModel->fixColumnWidth(NAME_COLUMN, NAME_COLUMN_WIDTH);
+ mPlayerTableTitleModel->fixColumnWidth(RELATION_CHOICE_COLUMN,
+ RELATION_CHOICE_COLUMN_WIDTH);
+ 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,
+ new gcn::Label(gettext(table_titles[i])));
+ }
+
+ mPlayerTitleTable->setLinewiseSelection(true);
+
+ mPlayerScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mPlayerTable->setActionEventId(ACTION_TABLE);
+ mPlayerTable->setLinewiseSelection(true);
+ mPlayerTable->addActionListener(this);
+
+ gcn::Label *ignore_action_label = new gcn::Label(_("When ignoring:"));
+
+ mIgnoreActionChoicesBox->setActionEventId(ACTION_STRATEGY);
+ mIgnoreActionChoicesBox->addActionListener(this);
+
+ int ignore_strategy_index = 0; // safe default
+
+ if (player_relations.getPlayerIgnoreStrategy())
+ {
+ ignore_strategy_index = player_relations.getPlayerIgnoreStrategyIndex(
+ player_relations.getPlayerIgnoreStrategy()->mShortName);
+ if (ignore_strategy_index < 0)
+ ignore_strategy_index = 0;
+ }
+ mIgnoreActionChoicesBox->setSelected(ignore_strategy_index);
+ mIgnoreActionChoicesBox->adjustHeight();
+
+ reset();
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, mPlayerTitleTable, 4);
+ place(0, 1, mPlayerScrollArea, 4, 4).setPadding(2);
+ place(0, 5, mDeleteButton);
+ place(2, 5, ignore_action_label);
+ place(2, 6, mIgnoreActionChoicesBox, 2).setPadding(2);
+ place(2, 7, mPersistIgnores);
+ place(2, 8, mDefaultTrading);
+ place(2, 9, mDefaultWhisper);
+
+ player_relations.addListener(this);
+
+ setDimension(gcn::Rectangle(0, 0, 325, 280));
+}
+
+Setup_Players::~Setup_Players()
+{
+ player_relations.removeListener(this);
+}
+
+
+void Setup_Players::reset()
+{
+ // We now have to search through the list of ignore choices to find the
+ // current selection. We could use an index into the table of config
+ // options in player_relations instead of strategies to sidestep this.
+ int selection = 0;
+ for (unsigned int i = 0;
+ i < player_relations.getPlayerIgnoreStrategies()->size();
+ ++i)
+ if ((*player_relations.getPlayerIgnoreStrategies())[i] ==
+ player_relations.getPlayerIgnoreStrategy())
+ {
+
+ selection = i;
+ break;
+ }
+
+ mIgnoreActionChoicesBox->setSelected(selection);
+}
+
+void Setup_Players::apply()
+{
+ player_relations.setPersistIgnores(mPersistIgnores->isSelected());
+ player_relations.store();
+
+ unsigned int old_default_relations = player_relations.getDefault() &
+ ~(PlayerRelation::TRADE |
+ PlayerRelation::WHISPER);
+ player_relations.setDefault(old_default_relations
+ | (mDefaultTrading->isSelected() ?
+ PlayerRelation::TRADE : 0)
+ | (mDefaultWhisper->isSelected() ?
+ PlayerRelation::WHISPER : 0));
+}
+
+void Setup_Players::cancel()
+{
+}
+
+void Setup_Players::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == ACTION_TABLE)
+ {
+ // temporarily eliminate ourselves: we are fully aware of this change,
+ // so there is no need for asynchronous updates. (In fact, thouse
+ // might destroy the widet that triggered them, which would be rather
+ // embarrassing.)
+ player_relations.removeListener(this);
+
+ int row = mPlayerTable->getSelectedRow();
+ if (row >= 0)
+ mPlayerTableModel->updateModelInRow(row);
+
+ player_relations.addListener(this);
+
+ }
+ else if (event.getId() == ACTION_DELETE)
+ {
+ int player_index = mPlayerTable->getSelectedRow();
+
+ if (player_index < 0)
+ return;
+
+ std::string name = mPlayerTableModel->getPlayerAt(player_index);
+
+ player_relations.removePlayer(name);
+
+ }
+ else if (event.getId() == ACTION_STRATEGY)
+ {
+ PlayerIgnoreStrategy *s =
+ (*player_relations.getPlayerIgnoreStrategies())[
+ mIgnoreActionChoicesBox->getSelected()];
+
+ player_relations.setPlayerIgnoreStrategy(s);
+ }
+}
+
+void Setup_Players::updatedPlayer(const std::string &name)
+{
+ mPlayerTableModel->playerRelationsUpdated();
+ mDefaultTrading->setSelected(
+ player_relations.getDefault() & PlayerRelation::TRADE);
+ mDefaultWhisper->setSelected(
+ player_relations.getDefault() & PlayerRelation::WHISPER);
+}
diff --git a/src/gui/setup_players.h b/src/gui/setup_players.h
new file mode 100644
index 00000000..72d81f71
--- /dev/null
+++ b/src/gui/setup_players.h
@@ -0,0 +1,67 @@
+/*
+ * The Mana World
+ * 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 GUI_SETUP_PLAYERS_H
+#define GUI_SETUP_PLAYERS_H
+
+#include <guichan/actionlistener.hpp>
+
+#include "setuptab.h"
+
+#include "../player_relations.h"
+
+class GuiTable;
+class PlayerTableModel;
+class StaticTableModel;
+
+class Setup_Players : public SetupTab,
+ public gcn::ActionListener,
+ public PlayerRelationsListener
+{
+public:
+ Setup_Players();
+ virtual ~Setup_Players();
+
+ void apply();
+ void cancel();
+
+ void reset();
+
+ void action(const gcn::ActionEvent &event);
+
+ virtual void updatedPlayer(const std::string &name);
+
+private:
+ StaticTableModel *mPlayerTableTitleModel;
+ PlayerTableModel *mPlayerTableModel;
+ GuiTable *mPlayerTable;
+ GuiTable *mPlayerTitleTable;
+ gcn::ScrollArea *mPlayerScrollArea;
+
+ gcn::CheckBox *mPersistIgnores;
+ gcn::CheckBox *mDefaultTrading;
+ gcn::CheckBox *mDefaultWhisper;
+
+ gcn::Button *mDeleteButton;
+ gcn::DropDown *mIgnoreActionChoicesBox;
+};
+
+#endif
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index bac342a0..526c67ce 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -1,29 +1,27 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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,16 +32,21 @@
#include "listbox.h"
#include "ok_dialog.h"
#include "scrollarea.h"
+#include "setup_video.h"
#include "slider.h"
#include "textfield.h"
+#include "widgets/layouthelper.h"
+
#include "../configuration.h"
#include "../graphics.h"
+#include "../localplayer.h"
#include "../log.h"
#include "../main.h"
+#include "../particle.h"
#include "../utils/gettext.h"
-#include "../utils/tostring.h"
+#include "../utils/stringutils.h"
extern Graphics *graphics;
@@ -101,18 +104,25 @@ 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)),
mVisibleNamesEnabled(config.getValue("visiblenames", 1)),
+ mParticleEffectsEnabled(config.getValue("particleeffects", true)),
+ mNameEnabled(config.getValue("showownname", false)),
mOpacity(config.getValue("guialpha", 0.8)),
mFps((int) config.getValue("fpslimit", 0)),
+ mSpeechMode((int) config.getValue("speech", 3)),
mModeListModel(new ModeListModel),
mModeList(new ListBox(mModeListModel)),
mFsCheckBox(new CheckBox(_("Full screen"), mFullScreenEnabled)),
mOpenGLCheckBox(new CheckBox(_("OpenGL"), mOpenGLEnabled)),
mCustomCursorCheckBox(new CheckBox(_("Custom cursor"), mCustomCursorEnabled)),
mVisibleNamesCheckBox(new CheckBox(_("Visible names"), mVisibleNamesEnabled)),
+ mParticleEffectsCheckBox(new CheckBox(_("Particle effects"), mParticleEffectsEnabled)),
+ mNameCheckBox(new CheckBox(_("Show name"), mNameEnabled)),
+ mSpeechSlider(new Slider(0, 3)),
+ mSpeechLabel(new gcn::Label("")),
mAlphaSlider(new Slider(0.2, 1.0)),
mFpsCheckBox(new CheckBox(_("FPS Limit:"))),
mFpsSlider(new Slider(10, 200)),
@@ -125,46 +135,47 @@ Setup_Video::Setup_Video():
mScrollRadiusField(new TextField),
mOverlayDetail((int) config.getValue("OverlayDetail", 2)),
mOverlayDetailSlider(new Slider(0, 2)),
- mOverlayDetailField(new gcn::Label(""))
+ mOverlayDetailField(new gcn::Label("")),
+ mParticleDetail(3 - (int) config.getValue("particleEmitterSkip", 1)),
+ mParticleDetailSlider(new Slider(0, 3)),
+ mParticleDetailField(new gcn::Label(""))
{
setOpaque(false);
- setDimension(gcn::Rectangle(0, 0, 250, 200));
ScrollArea *scrollArea = new ScrollArea(mModeList);
- gcn::Label *alphaLabel = new gcn::Label(_("Gui opacity"));
+ scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- mModeList->setEnabled(false);
+ speechLabel = new gcn::Label(_("Overhead text"));
+ alphaLabel = new gcn::Label(_("Gui opacity"));
+ scrollRadiusLabel = new gcn::Label(_("Scroll radius"));
+ scrollLazinessLabel = new gcn::Label(_("Scroll laziness"));
+ overlayDetailLabel = new gcn::Label(_("Ambient FX"));
+ particleDetailLabel = new gcn::Label(_("Particle Detail"));
+
+ mModeList->setEnabled(true);
#ifndef USE_OPENGL
mOpenGLCheckBox->setEnabled(false);
#endif
- mModeList->setDimension(gcn::Rectangle(0, 0, 60, 50));
- scrollArea->setDimension(gcn::Rectangle(10, 10, 90, 50));
- mFsCheckBox->setPosition(110, 10);
- mOpenGLCheckBox->setPosition(110, 30);
- mCustomCursorCheckBox->setPosition(110, 50);
- mVisibleNamesCheckBox->setPosition(110, 70);
- mAlphaSlider->setDimension(gcn::Rectangle(10, 100, 100, 10));
- alphaLabel->setPosition(20 + mAlphaSlider->getWidth(),
- mAlphaSlider->getY());
- mFpsCheckBox->setPosition(90, 120);
- mFpsSlider->setDimension(gcn::Rectangle(10, 120, 75, 10));
- mFpsField->setPosition(100 + mFpsCheckBox->getWidth(), 120);
- mFpsField->setWidth(30);
-
mModeList->setSelected(-1);
mAlphaSlider->setValue(mOpacity);
+ mAlphaSlider->setWidth(90);
mFpsField->setText(toString(mFps));
mFpsField->setEnabled(mFps > 0);
+ mFpsField->setWidth(30);
mFpsSlider->setValue(mFps);
mFpsSlider->setEnabled(mFps > 0);
mFpsCheckBox->setSelected(mFps > 0);
+ mModeList->setActionEventId("videomode");
mCustomCursorCheckBox->setActionEventId("customcursor");
mVisibleNamesCheckBox->setActionEventId("visiblenames");
+ mParticleEffectsCheckBox->setActionEventId("particleeffects");
+ mNameCheckBox->setActionEventId("showownname");
mAlphaSlider->setActionEventId("guialpha");
mFpsCheckBox->setActionEventId("fpslimitcheckbox");
+ mSpeechSlider->setActionEventId("speech");
mFpsSlider->setActionEventId("fpslimitslider");
mScrollRadiusSlider->setActionEventId("scrollradiusslider");
mScrollRadiusField->setActionEventId("scrollradiusfield");
@@ -172,11 +183,17 @@ Setup_Video::Setup_Video():
mScrollLazinessField->setActionEventId("scrolllazinessfield");
mOverlayDetailSlider->setActionEventId("overlaydetailslider");
mOverlayDetailField->setActionEventId("overlaydetailfield");
+ mParticleDetailSlider->setActionEventId("particledetailslider");
+ mParticleDetailField->setActionEventId("particledetailfield");
+ mModeList->addActionListener(this);
mCustomCursorCheckBox->addActionListener(this);
mVisibleNamesCheckBox->addActionListener(this);
+ mParticleEffectsCheckBox->addActionListener(this);
+ mNameCheckBox->addActionListener(this);
mAlphaSlider->addActionListener(this);
mFpsCheckBox->addActionListener(this);
+ mSpeechSlider->addActionListener(this);
mFpsSlider->addActionListener(this);
mFpsField->addKeyListener(this);
mScrollRadiusSlider->addActionListener(this);
@@ -185,28 +202,32 @@ Setup_Video::Setup_Video():
mScrollLazinessField->addKeyListener(this);
mOverlayDetailSlider->addActionListener(this);
mOverlayDetailField->addKeyListener(this);
+ mParticleDetailSlider->addActionListener(this);
+ mParticleDetailField->addKeyListener(this);
- mScrollRadiusSlider->setDimension(gcn::Rectangle(10, 140, 75, 10));
- gcn::Label *scrollRadiusLabel = new gcn::Label(_("Scroll radius"));
- scrollRadiusLabel->setPosition(90, 140);
- mScrollRadiusField->setPosition(mFpsField->getX(), 140);
- mScrollRadiusField->setWidth(30);
mScrollRadiusField->setText(toString(mOriginalScrollRadius));
mScrollRadiusSlider->setValue(mOriginalScrollRadius);
- mScrollLazinessSlider->setDimension(gcn::Rectangle(10, 160, 75, 10));
- gcn::Label *scrollLazinessLabel = new gcn::Label(_("Scroll laziness"));
- scrollLazinessLabel->setPosition(90, 160);
- mScrollLazinessField->setPosition(mFpsField->getX(), 160);
- mScrollLazinessField->setWidth(30);
mScrollLazinessField->setText(toString(mOriginalScrollLaziness));
mScrollLazinessSlider->setValue(mOriginalScrollLaziness);
- mOverlayDetailSlider->setDimension(gcn::Rectangle(10, 180, 75, 10));
- gcn::Label *overlayDetailLabel = new gcn::Label(_("Ambient FX"));
- overlayDetailLabel->setPosition(90, 180);
- mOverlayDetailField->setPosition(180, 180);
- mOverlayDetailField->setWidth(30);
+ switch (mSpeechMode)
+ {
+ case 0:
+ mSpeechLabel->setCaption(_("No text"));
+ break;
+ case 1:
+ mSpeechLabel->setCaption(_("Text"));
+ break;
+ case 2:
+ mSpeechLabel->setCaption(_("Bubbles, no names"));
+ break;
+ case 3:
+ mSpeechLabel->setCaption(_("Bubbles with names"));
+ break;
+ }
+ mSpeechSlider->setValue(mSpeechMode);
+
switch (mOverlayDetail)
{
case 0:
@@ -221,37 +242,66 @@ Setup_Video::Setup_Video():
}
mOverlayDetailSlider->setValue(mOverlayDetail);
- add(scrollArea);
- add(mFsCheckBox);
- add(mOpenGLCheckBox);
- add(mCustomCursorCheckBox);
- add(mVisibleNamesCheckBox);
- add(mAlphaSlider);
- add(alphaLabel);
- add(mFpsCheckBox);
- add(mFpsSlider);
- add(mFpsField);
- add(mScrollRadiusSlider);
- add(scrollRadiusLabel);
- add(mScrollRadiusField);
- add(mScrollLazinessSlider);
- add(scrollLazinessLabel);
- add(mScrollLazinessField);
- add(mOverlayDetailSlider);
- add(overlayDetailLabel);
- add(mOverlayDetailField);
-}
-
-Setup_Video::~Setup_Video()
-{
- delete mModeListModel;
+ switch (mParticleDetail)
+ {
+ case 0:
+ mParticleDetailField->setCaption(_("low"));
+ break;
+ case 1:
+ mParticleDetailField->setCaption(_("medium"));
+ break;
+ case 2:
+ mParticleDetailField->setCaption(_("high"));
+ break;
+ case 3:
+ mParticleDetailField->setCaption(_("max"));
+ break;
+ }
+ mParticleDetailSlider->setValue(mParticleDetail);
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, scrollArea, 1, 6).setPadding(2);
+ place(1, 0, mFsCheckBox, 3);
+ place(1, 1, mOpenGLCheckBox, 3);
+ place(1, 2, mCustomCursorCheckBox, 3);
+ place(1, 3, mVisibleNamesCheckBox, 3);
+ place(1, 4, mNameCheckBox, 3);
+ place(1, 5, mParticleEffectsCheckBox, 3);
+
+ place(0, 6, mAlphaSlider);
+ place(0, 7, mFpsSlider);
+ place(0, 8, mScrollRadiusSlider);
+ place(0, 9, mScrollLazinessSlider);
+ place(0, 10, mSpeechSlider);
+ place(0, 11, mOverlayDetailSlider);
+ place(0, 12, mParticleDetailSlider);
+
+ place(1, 6, alphaLabel, 2);
+ place(1, 7, mFpsCheckBox).setPadding(3);
+ place(1, 8, scrollRadiusLabel);
+ place(1, 9, scrollLazinessLabel);
+ place(1, 10, speechLabel);
+ place(1, 11, overlayDetailLabel);
+ place(1, 12, particleDetailLabel);
+
+ place(2, 7, mFpsField).setPadding(1);
+ place(2, 8, mScrollRadiusField).setPadding(1);
+ place(2, 9, mScrollLazinessField).setPadding(1);
+ place(2, 10, mSpeechLabel, 2).setPadding(2);
+ place(2, 11, mOverlayDetailField, 2).setPadding(2);
+ place(2, 12, mParticleDetailField, 2).setPadding(2);
+
+ setDimension(gcn::Rectangle(0, 0, 325, 280));
}
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
@@ -260,9 +310,9 @@ void Setup_Video::apply()
* See http://libsdl.org/cgi/docwiki.cgi/SDL_SetVideoMode
*/
-#ifdef WIN32
+#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))
@@ -271,26 +321,26 @@ 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());
}
}
-#ifdef WIN32
+#if defined(WIN32) || defined(__APPLE__)
} else {
new OkDialog(_("Switching to full screen"),
_("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"),
@@ -301,17 +351,19 @@ 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);
mVisibleNamesEnabled = config.getValue("visiblenames", 1);
+ mParticleEffectsEnabled = config.getValue("particleeffects", true);
+ mNameEnabled = config.getValue("showownname", false);
+ mSpeechMode = (int) config.getValue("speech", 3);
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,
- const std::string &configName)
+int Setup_Video::updateSlider(gcn::Slider *slider, gcn::TextField *field,
+ const std::string &configName)
{
int value;
std::stringstream temp(field->getText());
@@ -336,37 +388,94 @@ void Setup_Video::cancel()
mOpenGLCheckBox->setSelected(mOpenGLEnabled);
mCustomCursorCheckBox->setSelected(mCustomCursorEnabled);
mVisibleNamesCheckBox->setSelected(mVisibleNamesEnabled);
+ mParticleEffectsCheckBox->setSelected(mParticleEffectsEnabled);
+ mSpeechSlider->setValue(mSpeechMode);
+ mNameCheckBox->setSelected(mNameEnabled);
mAlphaSlider->setValue(mOpacity);
mOverlayDetailSlider->setValue(mOverlayDetail);
+ mParticleDetailSlider->setValue(mParticleDetail);
mScrollRadiusField->setText(toString(mOriginalScrollRadius));
mScrollLazinessField->setText(toString(mOriginalScrollLaziness));
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("visiblenames", mVisibleNamesEnabled ? 1 : 0);
+ config.setValue("particleeffects", mParticleEffectsEnabled ? true : false);
+ config.setValue("speech", mSpeechMode);
+ 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() == "visiblenames")
{
config.setValue("visiblenames",
mVisibleNamesCheckBox->isSelected() ? 1 : 0);
}
+ 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() == "speech")
+ {
+ int val = (int) mSpeechSlider->getValue();
+ switch (val)
+ {
+ case 0:
+ mSpeechLabel->setCaption(_("No text"));
+ break;
+ case 1:
+ mSpeechLabel->setCaption(_("Text"));
+ break;
+ case 2:
+ mSpeechLabel->setCaption(_("Bubbles, no names"));
+ break;
+ case 3:
+ mSpeechLabel->setCaption(_("Bubbles with names"));
+ break;
+ }
+ mSpeechSlider->setValue(val);
+ config.setValue("speech", val);
+ }
+ 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")
{
mFps = (int) mFpsSlider->getValue();
@@ -401,6 +510,27 @@ void Setup_Video::action(const gcn::ActionEvent &event)
}
config.setValue("OverlayDetail", val);
}
+ else if (event.getId() == "particledetailslider")
+ {
+ int val = (int) mParticleDetailSlider->getValue();
+ switch (val)
+ {
+ case 0:
+ mParticleDetailField->setCaption(_("low"));
+ break;
+ case 1:
+ mParticleDetailField->setCaption(_("medium"));
+ break;
+ case 2:
+ mParticleDetailField->setCaption(_("high"));
+ break;
+ case 3:
+ mParticleDetailField->setCaption(_("max"));
+ break;
+ }
+ config.setValue("particleEmitterSkip", 3 - val);
+ Particle::emitterSkip = 4 - val;
+ }
else if (event.getId() == "fpslimitcheckbox")
{
if (mFpsCheckBox->isSelected())
@@ -418,8 +548,7 @@ void Setup_Video::action(const gcn::ActionEvent &event)
}
}
-void
-Setup_Video::keyPressed(gcn::KeyEvent &event)
+void Setup_Video::keyPressed(gcn::KeyEvent &event)
{
std::stringstream tempFps(mFpsField->getText());
diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h
index 17ca1241..44ecdfe5 100644
--- a/src/gui/setup_video.h
+++ b/src/gui/setup_video.h
@@ -1,40 +1,37 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_GUI_SETUP_VIDEO_H
-#define _TMW_GUI_SETUP_VIDEO_H
-
-#include "setuptab.h"
+#ifndef GUI_SETUP_VIDEO_H
+#define GUI_SETUP_VIDEO_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
{
public:
Setup_Video();
- ~Setup_Video();
void apply();
void cancel();
@@ -42,25 +39,43 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
void action(const gcn::ActionEvent &event);
/** Called when key is pressed */
- void
- keyPressed(gcn::KeyEvent &event);
+ void keyPressed(gcn::KeyEvent &event);
private:
+ void updateSliders(bool originalValues);
+
+ int updateSlider(gcn::Slider *slider, gcn::TextField *field,
+ const std::string &configName);
+
bool mFullScreenEnabled;
bool mOpenGLEnabled;
bool mCustomCursorEnabled;
bool mVisibleNamesEnabled;
+ bool mParticleEffectsEnabled;
+ bool mNameEnabled;
double mOpacity;
int mFps;
+ int mSpeechMode;
class ModeListModel *mModeListModel;
+ gcn::Label *speechLabel;
+ gcn::Label *alphaLabel;
+ gcn::Label *scrollRadiusLabel;
+ gcn::Label *scrollLazinessLabel;
+ gcn::Label *overlayDetailLabel;
+ gcn::Label *particleDetailLabel;
+
gcn::ListBox *mModeList;
gcn::CheckBox *mFsCheckBox;
gcn::CheckBox *mOpenGLCheckBox;
gcn::CheckBox *mCustomCursorCheckBox;
gcn::CheckBox *mVisibleNamesCheckBox;
+ gcn::CheckBox *mParticleEffectsCheckBox;
+ gcn::CheckBox *mNameCheckBox;
+ gcn::Slider *mSpeechSlider;
+ gcn::Label *mSpeechLabel;
gcn::Slider *mAlphaSlider;
gcn::CheckBox *mFpsCheckBox;
gcn::Slider *mFpsSlider;
@@ -78,12 +93,9 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
gcn::Slider *mOverlayDetailSlider;
gcn::Label *mOverlayDetailField;
- void
- updateSliders(bool originalValues);
-
- int
- updateSlider(gcn::Slider *slider, gcn::TextField *field,
- const std::string &configName);
+ int mParticleDetail;
+ gcn::Slider *mParticleDetailSlider;
+ gcn::Label *mParticleDetailField;
};
#endif
diff --git a/src/gui/setuptab.h b/src/gui/setuptab.h
index 6c276c35..3e0c51e2 100644
--- a/src/gui/setuptab.h
+++ b/src/gui/setuptab.h
@@ -1,34 +1,34 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_GUI_SETUPTAB_H
-#define _TMW_GUI_SETUPTAB_H
+#ifndef GUI_SETUPTAB_H
+#define GUI_SETUPTAB_H
#include "gccontainer.h"
class SetupTab : public GCContainer
{
public:
- virtual void apply() =0;
- virtual void cancel() =0;
+ virtual void apply() = 0;
+ virtual void cancel() = 0;
};
#endif
diff --git a/src/gui/shop.cpp b/src/gui/shop.cpp
index a521c75b..7b28cef4 100644
--- a/src/gui/shop.cpp
+++ b/src/gui/shop.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -43,7 +43,16 @@ void ShopItems::addItem(int id, int amount, int price)
mShopItems.push_back(new ShopItem(id, amount, price));
}
-ShopItem* ShopItems::at(int i)
+#ifdef EATHENA_SUPPORT
+void ShopItems::addItem(int inventoryIndex, int id, int amount, int price)
+{
+ ShopItem *item = new ShopItem(id, amount, price);
+ item->setInvIndex(inventoryIndex);
+ mShopItems.push_back(item);
+}
+#endif
+
+ShopItem* ShopItems::at(int i) const
{
return mShopItems.at(i);
}
diff --git a/src/gui/shop.h b/src/gui/shop.h
index 62b60cae..aa72bf2a 100644
--- a/src/gui/shop.h
+++ b/src/gui/shop.h
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -27,10 +27,10 @@
#include <guichan/listmodel.hpp>
-#include "../resources/image.h"
-
#include "../shopitem.h"
+class ShopItem;
+
class ShopItems : public gcn::ListModel
{
public:
@@ -40,10 +40,17 @@ class ShopItems : public gcn::ListModel
~ShopItems();
/**
- * Adds an item and its associated picture.
+ * Adds an item to the list.
*/
void addItem(int id, int amount, int price);
+#ifdef EATHENA_SUPPORT
+ /**
+ * Adds an item to the list (used by eAthena sell dialog).
+ */
+ void addItem(int inventoryIndex, int id, int amount, int price);
+#endif
+
/**
* Returns the number of items in the shop.
*/
@@ -57,7 +64,7 @@ class ShopItems : public gcn::ListModel
/**
* Returns the item number i in the shop.
*/
- ShopItem* at(int i);
+ ShopItem* at(int i) const;
/**
* Clear the vector.
diff --git a/src/gui/shoplistbox.cpp b/src/gui/shoplistbox.cpp
index bce6a48c..8aed3c77 100644
--- a/src/gui/shoplistbox.cpp
+++ b/src/gui/shoplistbox.cpp
@@ -1,37 +1,38 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 = (int)(mAlpha * 255.0f);
+
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 75f514ab..cde4786e 100644
--- a/src/gui/shoplistbox.h
+++ b/src/gui/shoplistbox.h
@@ -1,29 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SHOPLISTBOX_H
-#define _TMW_SHOPLISTBOX_H
+#ifndef SHOPLISTBOX_H
+#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..74609fa1
--- /dev/null
+++ b/src/gui/shortcutcontainer.cpp
@@ -0,0 +1,71 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 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 "shortcutcontainer.h"
+
+#include "../configuration.h"
+
+#include "../resources/image.h"
+
+#include "../utils/stringutils.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..7b09fb96
--- /dev/null
+++ b/src/gui/shortcutcontainer.h
@@ -0,0 +1,107 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 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 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/shortcutwindow.cpp b/src/gui/shortcutwindow.cpp
new file mode 100644
index 00000000..c704fc44
--- /dev/null
+++ b/src/gui/shortcutwindow.cpp
@@ -0,0 +1,83 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 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 "scrollarea.h"
+#include "shortcutcontainer.h"
+#include "shortcutwindow.h"
+
+#include "../configuration.h"
+
+static const int SCROLL_PADDING = 0;
+
+int ShortcutWindow::mInstances = 0;
+
+ShortcutWindow::ShortcutWindow(const char *title, ShortcutContainer *content)
+{
+ setWindowName(title);
+ // no title presented, title bar is padding so window can be moved.
+ gcn::Window::setTitleBarHeight(gcn::Window::getPadding());
+ setShowTitle(false);
+ setResizable(true);
+
+ mItems = content;
+
+ mInstances++;
+
+ const int border = SCROLL_PADDING * 2 + getPadding() * 2;
+ setMinWidth(mItems->getBoxWidth() + border);
+ setMinHeight(mItems->getBoxHeight() + border);
+ 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);
+ mScrollArea->setOpaque(false);
+
+ add(mScrollArea);
+
+ loadWindowState();
+}
+
+ShortcutWindow::~ShortcutWindow()
+{
+ delete mItems;
+}
+
+void ShortcutWindow::widgetResized(const gcn::Event &event)
+{
+ Window::widgetResized(event);
+
+ const gcn::Rectangle &area = getChildrenArea();
+
+ mScrollArea->setSize(
+ area.width - SCROLL_PADDING,
+ area.height - SCROLL_PADDING);
+}
diff --git a/src/gui/shortcutwindow.h b/src/gui/shortcutwindow.h
new file mode 100644
index 00000000..64592328
--- /dev/null
+++ b/src/gui/shortcutwindow.h
@@ -0,0 +1,65 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 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 SHORTCUTWINDOW_H
+#define SHORTCUTWINDOW_H
+
+#include "window.h"
+
+class ScrollArea;
+class ShortcutContainer;
+
+/**
+ * A window around the ItemShortcutContainer.
+ *
+ * \ingroup Interface
+ */
+class ShortcutWindow : public Window
+{
+ public:
+ /**
+ * Constructor.
+ */
+ ShortcutWindow(const char *title, ShortcutContainer *content);
+
+ /**
+ * Destructor.
+ */
+ ~ShortcutWindow();
+
+ /**
+ * Called whenever the widget changes size.
+ */
+ void widgetResized(const gcn::Event &event);
+
+ private:
+ ShortcutWindow();
+ ShortcutContainer *mItems;
+
+ ScrollArea *mScrollArea;
+
+ static int mInstances;
+};
+
+extern ShortcutWindow *itemShortcutWindow;
+extern ShortcutWindow *emoteShortcutWindow;
+
+#endif
diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp
index 6d747641..61bb9ce9 100644
--- a/src/gui/skill.cpp
+++ b/src/gui/skill.cpp
@@ -1,73 +1,161 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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/widgets/label.hpp>
-#include <guichan/widgets/container.hpp>
-#include <guichan/widgets/icon.hpp>
-#include "skill.h"
-
-#include "icon.h"
#include "button.h"
#include "listbox.h"
#include "scrollarea.h"
+#include "skill.h"
+#include "table.h"
#include "windowcontainer.h"
-#include "progressbar.h"
-#include "widgets/tabbedarea.h"
+#include "widgets/layout.h"
#include "../localplayer.h"
+#include "../log.h"
#include "../utils/dtor.h"
-#include "../utils/tostring.h"
#include "../utils/gettext.h"
+#include "../utils/strprintf.h"
+#include "../utils/xml.h"
+
+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();
+
+class SkillGuiTableModel : public StaticTableModel
+{
+public:
+ SkillGuiTableModel(SkillDialog *dialog) :
+ StaticTableModel(0, 3)
+ {
+ mEntriesNr = 0;
+ mDialog = dialog;
+ update();
+ }
+
+ virtual int getRows(void)
+ {
+ return mEntriesNr;
+ }
+
+ virtual int getColumnWidth(int index)
+ {
+ if (index == 0)
+ return 160;
+
+ return 35;
+ }
+
+ virtual int getRowHeight()
+ {
+ return 12;
+ }
+
+ virtual void update()
+ {
+ mEntriesNr = mDialog->getSkills().size();
+ resize();
+
+ for (int i = 0; i < mEntriesNr; i++)
+ {
+ SKILL *skill = mDialog->getSkills()[i];
+ SkillInfo const *info;
+ char tmp[128];
+
+ if (skill->id >= 0
+ && (unsigned int) skill->id < skill_db.size())
+ info = &skill_db[skill->id];
+ else
+ info = &fakeSkillInfo;
+
+ sprintf(tmp, "%c%s", info->modifiable? ' ' : '*', info->name.c_str());
+ gcn::Label *name_label = new gcn::Label(tmp);
+
+ sprintf(tmp, "Lv:%i", skill->lv);
+ gcn::Label *lv_label = new gcn::Label(tmp);
+
+ sprintf(tmp, "Sp:%i", skill->sp);
+ gcn::Label *sp_label = new gcn::Label(tmp);
+
+ set(i, 0, name_label);
+ set(i, 1, lv_label);
+ set(i, 2, sp_label);
+ }
+ }
+
+private:
+ SkillDialog *mDialog;
+ int mEntriesNr;
+};
+
SkillDialog::SkillDialog():
Window(_("Skills"))
{
+ initSkillinfo();
+ mTableModel = new SkillGuiTableModel(this);
+ 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() - 280, 30, 275, 425);
+ setDefaultSize(windowContainer->getWidth() - 260, 25, 255, 260);
- TabbedArea *panel = new TabbedArea();
- panel->setDimension(gcn::Rectangle(5, 5, 270, 420));
+ setMinHeight(50 + mTableModel->getHeight());
+ setMinWidth(200);
- Skill_Tab* tab;
+ 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);
+ mUseButton->setEnabled(false);
- // Add each type of skill tab to the panel
- tab = new Skill_Tab("Weapon");
- panel->addTab(_("Weapons"), tab);
- mTabs.push_back(tab);
+ skillScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- tab = new Skill_Tab("Magic");
- panel->addTab(_("Magic"), tab);
- mTabs.push_back(tab);
+ place(0, 0, skillScrollArea, 5).setPadding(3);
+ place(0, 1, mPointsLabel, 2);
+ place(3, 2, mIncButton);
+ place(4, 2, mUseButton);
- tab = new Skill_Tab("Craft");
- panel->addTab(_("Crafts"), tab);
- mTabs.push_back(tab);
-
- add(panel);
-
- update();
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
setLocationRelativeTo(getParent());
loadWindowState();
@@ -75,189 +163,135 @@ SkillDialog::SkillDialog():
SkillDialog::~SkillDialog()
{
- delete_all(mTabs);
+ delete mTable;
}
void SkillDialog::action(const gcn::ActionEvent &event)
{
- if (event.getId() == "skill")
+ if (event.getId() == "inc")
{
+ // Increment skill
+ int selectedSkill = mTable->getSelectedRow();
+ if (selectedSkill >= 0)
+ player_node->raiseSkill(mSkillList[selectedSkill]->id);
}
- else if (event.getId() == "close")
+ else if (event.getId() == "skill" && mTable->getSelectedRow() > -1)
{
- setVisible(false);
- }
-}
-
-void SkillDialog::draw(gcn::Graphics *g)
-{
- update();
+ SKILL *skill = mSkillList[mTable->getSelectedRow()];
+ SkillInfo const *info;
- Window::draw(g);
-}
+ if (skill->id >= 0 && (unsigned int) skill->id < skill_db.size())
+ info = &skill_db[skill->id];
+ else
+ info = &fakeSkillInfo;
-void SkillDialog::update()
-{
- for(std::list<Skill_Tab*>::const_iterator i = mTabs.begin();
- i != mTabs.end(); ++i)
- {
- (*i)->update();
+ mIncButton->setEnabled(player_node->mSkillPoint > 0 &&
+ info->modifiable);
}
+ else if (event.getId() == "close")
+ setVisible(false);
}
-Skill_Tab::Skill_Tab(const std::string &type): type(type)
+void SkillDialog::update()
{
- setOpaque(false);
- setDimension(gcn::Rectangle(0, 0, 270, 420));
- int skillNum = getSkillNum();
-
- mSkillIcons.resize(skillNum);
- mSkillNameLabels.resize(skillNum);
- mSkillLevelLabels.resize(skillNum);
- mSkillExpLabels.resize(skillNum);
- mSkillProgress.resize(skillNum);
-
- // Set the initial positions of the skill information
- for (int a=0; a < skillNum; a++)
- {
- mSkillIcons.at(a) = getIcon(a);
- mSkillIcons.at(a)->setPosition(1, a*32);
- add(mSkillIcons.at(a));
+ mPointsLabel->setCaption(strprintf(_("Skill points: %d"),
+ player_node->mSkillPoint));
- mSkillNameLabels.at(a) = new gcn::Label("");
- mSkillNameLabels.at(a)->setPosition(35, a*32 );
- add(mSkillNameLabels.at(a));
+ int selectedSkill = mTable->getSelectedRow();
- mSkillProgress.at(a) = new ProgressBar(0.0f, 200, 20, 150, 150, 150);
- mSkillProgress.at(a)->setPosition(35, a*32 + 13);
- add(mSkillProgress.at(a));
+ if (selectedSkill >= 0)
+ {
+ int skillId = mSkillList[selectedSkill]->id;
+ bool modifiable;
- mSkillExpLabels.at(a) = new gcn::Label("");
- mSkillExpLabels.at(a)->setPosition(45, a*32 + 16);
- add(mSkillExpLabels.at(a));
+ if (skillId >= 0 && (unsigned int) skillId < skill_db.size())
+ modifiable = skill_db[skillId].modifiable;
+ else
+ modifiable = false;
- mSkillLevelLabels.at(a) = new gcn::Label("");
- mSkillLevelLabels.at(a)->setPosition(165, a*32);
- add(mSkillLevelLabels.at(a));
+ mIncButton->setEnabled(modifiable
+ && player_node->mSkillPoint > 0);
}
+ else
+ mIncButton->setEnabled(false);
- update();
-
+ mTableModel->update();
+ setMinHeight(50 + mTableModel->getHeight());
}
-int Skill_Tab::getSkillNum()
+int SkillDialog::getNumberOfElements()
{
- int skillNum = 0;
+ return mSkillList.size();
+}
- if (type == "Weapon")
- {
- skillNum = CHAR_SKILL_WEAPON_NB;
- return skillNum;
- }
- else if (type == "Magic")
- {
- skillNum = CHAR_SKILL_MAGIC_NB;
- return skillNum;
- }
- else if (type == "Craft")
+bool SkillDialog::hasSkill(int id)
+{
+ for (unsigned int i = 0; i < mSkillList.size(); i++)
{
- skillNum = CHAR_SKILL_CRAFT_NB;
- return skillNum;
+ if (mSkillList[i]->id == id)
+ return true;
}
- else return skillNum;
+ return false;
}
-int Skill_Tab::getSkillBegin()
+void SkillDialog::addSkill(int id, int lvl, int mp)
{
- int skillBegin = 0;
+ SKILL *tmp = new SKILL;
+ tmp->id = id;
+ tmp->lv = lvl;
+ tmp->sp = mp;
+ mSkillList.push_back(tmp);
+}
- if (type == "Weapon")
- {
- skillBegin = CHAR_SKILL_WEAPON_BEGIN - CHAR_SKILL_BEGIN;
- return skillBegin;
- }
- else if (type == "Magic")
- {
- skillBegin = CHAR_SKILL_MAGIC_BEGIN - CHAR_SKILL_BEGIN;
- return skillBegin;
- }
- else if (type == "Craft")
+void SkillDialog::setSkill(int id, int lvl, int mp)
+{
+ for (unsigned int i = 0; i < mSkillList.size(); i++)
{
- skillBegin = CHAR_SKILL_CRAFT_BEGIN - CHAR_SKILL_BEGIN;
- return skillBegin;
+ if (mSkillList[i]->id == id)
+ {
+ mSkillList[i]->lv = lvl;
+ mSkillList[i]->sp = mp;
+ }
}
- else return skillBegin;
}
-Icon* Skill_Tab::getIcon(int index)
+void SkillDialog::cleanList()
{
- int skillBegin = getSkillBegin();
- std::string icon = LocalPlayer::getSkillInfo(index + skillBegin).icon;
- return new Icon(icon);
+ delete_all(mSkillList);
+ mSkillList.clear();
}
-void Skill_Tab::updateSkill(int index)
+static void initSkillinfo()
{
- int skillBegin = getSkillBegin();
+ SkillInfo emptySkillInfo = { "", false };
- int baseLevel = player_node->getAttributeBase(index +
- skillBegin +
- CHAR_SKILL_BEGIN);
+ XML::Document doc(SKILLS_FILE);
+ xmlNodePtr root = doc.rootNode();
- int effLevel = player_node->getAttributeEffective(index +
- skillBegin +
- CHAR_SKILL_BEGIN);
- if(baseLevel <= 0)
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "skills"))
{
- mSkillProgress.at(index)->setVisible(false);
- mSkillExpLabels.at(index)->setVisible(false);
- mSkillLevelLabels.at(index)->setVisible(false);
- mSkillNameLabels.at(index)->setVisible(false);
- mSkillIcons.at(index)->setVisible(false);
+ logger->log("Error loading skills file: %s", SKILLS_FILE);
+ skill_db.resize(2, emptySkillInfo);
+ skill_db[1].name = "Basic";
+ skill_db[1].modifiable = true;
+ return;
}
- else
+
+ for_each_xml_child_node(node, root)
{
- mSkillProgress.at(index)->setVisible(true);
- mSkillExpLabels.at(index)->setVisible(true);
- mSkillLevelLabels.at(index)->setVisible(true);
- mSkillNameLabels.at(index)->setVisible(true);
- mSkillIcons.at(index)->setVisible(true);
- std::string skillLevel("Lvl: " + toString(baseLevel));
- if (effLevel < baseLevel)
- {
- skillLevel.append(" - " + toString(baseLevel - effLevel));
- }
- else if (effLevel > baseLevel)
+ if (xmlStrEqual(node->name, BAD_CAST "skill"))
{
- skillLevel.append(" + " + toString(effLevel - baseLevel));
+ int index = atoi(XML::getProperty(node, "id", "-1").c_str());
+ std::string name = XML::getProperty(node, "name", "");
+ bool modifiable = !atoi(XML::getProperty(node, "fixed", "0").c_str());
+
+ if (index >= 0)
+ {
+ skill_db.resize(index + 1, emptySkillInfo);
+ skill_db[index].name = name;
+ skill_db[index].modifiable = modifiable;
+ }
}
- mSkillLevelLabels.at(index)->setCaption(skillLevel);
-
- std::pair<int, int> exp = player_node->getExperience(index + skillBegin);
- std::string sExp (toString(exp.first) + " / " + toString(exp.second));
-
-
- mSkillNameLabels.at(index)->setCaption(LocalPlayer::getSkillInfo(index + skillBegin).name);
- mSkillNameLabels.at(index)->adjustSize();
- mSkillLevelLabels.at(index)->adjustSize();
- mSkillExpLabels.at(index)->setCaption(sExp);
- mSkillExpLabels.at(index)->adjustSize();
- mSkillExpLabels.at(index)->setAlignment(gcn::Graphics::RIGHT);
-
- // More intense red as exp grows
- int color = 150 - (int)(150 * ((float) exp.first / exp.second));
- mSkillProgress.at(index)->setColor(244, color, color);
- mSkillProgress.at(index)->setProgress((float) exp.first / exp.second);
}
}
-void Skill_Tab::update()
-{
- int skillNum = getSkillNum();
-
- // Update the skill information for reach skill
- for (int a = 0; a < skillNum; a++)
- {
- updateSkill(a);
- }
-}
diff --git a/src/gui/skill.h b/src/gui/skill.h
index 3d010daa..0600d106 100644
--- a/src/gui/skill.h
+++ b/src/gui/skill.h
@@ -1,95 +1,40 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SKILL_H
-#define _TMW_SKILL_H
+#ifndef SKILL_H
+#define SKILL_H
#include <vector>
-#include <list>
-#include <guichan/listmodel.hpp>
#include <guichan/actionlistener.hpp>
#include "window.h"
-#include "gccontainer.h"
-#include "../guichanfwd.h"
-
-class ProgressBar;
-class Icon;
-
-class Skill_Tab : public GCContainer, public gcn::ActionListener
-{
- public:
- /**
- * The type of this skill tab
- */
- const std::string type;
-
- /**
- * Constructor
- */
- Skill_Tab(const std::string &type);
-
- /**
- * Update this tab
- */
- void update();
-
- /**
- * Called when receiving actions from widget.
- */
- void action(const gcn::ActionEvent &event) {}
-
- private:
- /**
- * Update the information of a skill at
- * the given index
- */
- void updateSkill(int index);
-
- /**
- * Gets the number of skills in this particular
- * type of tab.
- */
- int getSkillNum();
-
- /**
- * Get the first enumeration of this skill tab's
- * skill type.
- */
- int getSkillBegin();
-
- /**
- * Get the icon associated with the given index
- */
- Icon* getIcon(int index);
-
- std::vector<Icon *> mSkillIcons;
- std::vector<gcn::Label *> mSkillNameLabels;
- std::vector<gcn::Label *> mSkillLevelLabels;
- std::vector<gcn::Label *> mSkillExpLabels;
- std::vector<ProgressBar *> mSkillProgress;
+struct SKILL {
+ short id; /**< Index into "skill_db" array */
+ short lv, sp;
};
+class GuiTable;
+class SkillGuiTableModel;
/**
* The skill dialog.
@@ -109,31 +54,30 @@ class SkillDialog : public Window, public gcn::ActionListener
*/
~SkillDialog();
- /**
- * Called when receiving actions from widget.
- */
void action(const gcn::ActionEvent &event);
- /**
- * Update the tabs in this dialog
- */
void update();
- /**
- * Draw this window.
- */
- void draw(gcn::Graphics *g);
-
- private:
+ int getNumberOfElements();
+ bool hasSkill(int id);
+ void addSkill(int id, int lv, int sp);
+ void setSkill(int id, int lv, int sp);
+ void cleanList();
- std::list<Skill_Tab*> mTabs;
+ const std::vector<SKILL*>& getSkills() const { return mSkillList; }
+ private:
+ GuiTable *mTable;
+ ScrollArea *skillScrollArea;
+ SkillGuiTableModel *mTableModel;
+ gcn::Label *mPointsLabel;
+ gcn::Button *mIncButton;
+ gcn::Button *mUseButton;
+
+ std::vector<SKILL*> mSkillList;
};
-
-
-
extern SkillDialog *skillDialog;
#endif
diff --git a/src/gui/skilldialog.cpp b/src/gui/skilldialog.cpp
new file mode 100644
index 00000000..22d1db60
--- /dev/null
+++ b/src/gui/skilldialog.cpp
@@ -0,0 +1,263 @@
+/*
+ * 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/widgets/label.hpp>
+#include <guichan/widgets/container.hpp>
+#include <guichan/widgets/icon.hpp>
+
+#include "skilldialog.h"
+
+#include "icon.h"
+#include "button.h"
+#include "listbox.h"
+#include "scrollarea.h"
+#include "windowcontainer.h"
+#include "progressbar.h"
+
+#include "widgets/tabbedarea.h"
+
+#include "../localplayer.h"
+
+#include "../utils/dtor.h"
+#include "../utils/gettext.h"
+#include "../utils/stringutils.h"
+
+SkillDialog::SkillDialog():
+ Window(_("Skills"))
+{
+ setWindowName("Skills");
+ setCloseButton(true);
+ setDefaultSize(windowContainer->getWidth() - 280, 30, 275, 425);
+
+ TabbedArea *panel = new TabbedArea();
+ panel->setDimension(gcn::Rectangle(5, 5, 270, 420));
+
+ Skill_Tab* tab;
+
+ // Add each type of skill tab to the panel
+ tab = new Skill_Tab("Weapon");
+ panel->addTab(_("Weapons"), tab);
+ mTabs.push_back(tab);
+
+ tab = new Skill_Tab("Magic");
+ panel->addTab(_("Magic"), tab);
+ mTabs.push_back(tab);
+
+ tab = new Skill_Tab("Craft");
+ panel->addTab(_("Crafts"), tab);
+ mTabs.push_back(tab);
+
+ add(panel);
+
+ update();
+
+ setLocationRelativeTo(getParent());
+ loadWindowState();
+}
+
+SkillDialog::~SkillDialog()
+{
+ delete_all(mTabs);
+}
+
+void SkillDialog::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == "skill")
+ {
+ }
+ else if (event.getId() == "close")
+ {
+ setVisible(false);
+ }
+}
+
+void SkillDialog::draw(gcn::Graphics *g)
+{
+ update();
+
+ Window::draw(g);
+}
+
+void SkillDialog::update()
+{
+ for(std::list<Skill_Tab*>::const_iterator i = mTabs.begin();
+ i != mTabs.end(); ++i)
+ {
+ (*i)->update();
+ }
+}
+
+Skill_Tab::Skill_Tab(const std::string &type): type(type)
+{
+ setOpaque(false);
+ setDimension(gcn::Rectangle(0, 0, 270, 420));
+ int skillNum = getSkillNum();
+
+ mSkillIcons.resize(skillNum);
+ mSkillNameLabels.resize(skillNum);
+ mSkillLevelLabels.resize(skillNum);
+ mSkillExpLabels.resize(skillNum);
+ mSkillProgress.resize(skillNum);
+
+ // Set the initial positions of the skill information
+ for (int a=0; a < skillNum; a++)
+ {
+ mSkillIcons.at(a) = getIcon(a);
+ mSkillIcons.at(a)->setPosition(1, a*32);
+ add(mSkillIcons.at(a));
+
+ mSkillNameLabels.at(a) = new gcn::Label("");
+ mSkillNameLabels.at(a)->setPosition(35, a*32 );
+ add(mSkillNameLabels.at(a));
+
+ mSkillProgress.at(a) = new ProgressBar(0.0f, 200, 20, 150, 150, 150);
+ mSkillProgress.at(a)->setPosition(35, a*32 + 13);
+ add(mSkillProgress.at(a));
+
+ mSkillExpLabels.at(a) = new gcn::Label("");
+ mSkillExpLabels.at(a)->setPosition(45, a*32 + 16);
+ add(mSkillExpLabels.at(a));
+
+ mSkillLevelLabels.at(a) = new gcn::Label("");
+ mSkillLevelLabels.at(a)->setPosition(165, a*32);
+ add(mSkillLevelLabels.at(a));
+ }
+
+ update();
+
+}
+
+int Skill_Tab::getSkillNum()
+{
+ int skillNum = 0;
+
+ if (type == "Weapon")
+ {
+ skillNum = CHAR_SKILL_WEAPON_NB;
+ return skillNum;
+ }
+ else if (type == "Magic")
+ {
+ skillNum = CHAR_SKILL_MAGIC_NB;
+ return skillNum;
+ }
+ else if (type == "Craft")
+ {
+ skillNum = CHAR_SKILL_CRAFT_NB;
+ return skillNum;
+ }
+ else return skillNum;
+}
+
+int Skill_Tab::getSkillBegin()
+{
+ int skillBegin = 0;
+
+ if (type == "Weapon")
+ {
+ skillBegin = CHAR_SKILL_WEAPON_BEGIN - CHAR_SKILL_BEGIN;
+ return skillBegin;
+ }
+ else if (type == "Magic")
+ {
+ skillBegin = CHAR_SKILL_MAGIC_BEGIN - CHAR_SKILL_BEGIN;
+ return skillBegin;
+ }
+ else if (type == "Craft")
+ {
+ skillBegin = CHAR_SKILL_CRAFT_BEGIN - CHAR_SKILL_BEGIN;
+ return skillBegin;
+ }
+ else return skillBegin;
+}
+
+Icon* Skill_Tab::getIcon(int index)
+{
+ int skillBegin = getSkillBegin();
+ std::string icon = LocalPlayer::getSkillInfo(index + skillBegin).icon;
+ return new Icon(icon);
+}
+
+void Skill_Tab::updateSkill(int index)
+{
+ int skillBegin = getSkillBegin();
+
+ int baseLevel = player_node->getAttributeBase(index +
+ skillBegin +
+ CHAR_SKILL_BEGIN);
+
+ int effLevel = player_node->getAttributeEffective(index +
+ skillBegin +
+ CHAR_SKILL_BEGIN);
+ if(baseLevel <= 0)
+ {
+ mSkillProgress.at(index)->setVisible(false);
+ mSkillExpLabels.at(index)->setVisible(false);
+ mSkillLevelLabels.at(index)->setVisible(false);
+ mSkillNameLabels.at(index)->setVisible(false);
+ mSkillIcons.at(index)->setVisible(false);
+ }
+ else
+ {
+ mSkillProgress.at(index)->setVisible(true);
+ mSkillExpLabels.at(index)->setVisible(true);
+ mSkillLevelLabels.at(index)->setVisible(true);
+ mSkillNameLabels.at(index)->setVisible(true);
+ mSkillIcons.at(index)->setVisible(true);
+ std::string skillLevel("Lvl: " + toString(baseLevel));
+ if (effLevel < baseLevel)
+ {
+ skillLevel.append(" - " + toString(baseLevel - effLevel));
+ }
+ else if (effLevel > baseLevel)
+ {
+ skillLevel.append(" + " + toString(effLevel - baseLevel));
+ }
+ mSkillLevelLabels.at(index)->setCaption(skillLevel);
+
+ std::pair<int, int> exp = player_node->getExperience(index + skillBegin);
+ std::string sExp (toString(exp.first) + " / " + toString(exp.second));
+
+
+ mSkillNameLabels.at(index)->setCaption(LocalPlayer::getSkillInfo(index + skillBegin).name);
+ mSkillNameLabels.at(index)->adjustSize();
+ mSkillLevelLabels.at(index)->adjustSize();
+ mSkillExpLabels.at(index)->setCaption(sExp);
+ mSkillExpLabels.at(index)->adjustSize();
+ mSkillExpLabels.at(index)->setAlignment(gcn::Graphics::RIGHT);
+
+ // More intense red as exp grows
+ int color = 150 - (int)(150 * ((float) exp.first / exp.second));
+ mSkillProgress.at(index)->setColor(244, color, color);
+ mSkillProgress.at(index)->setProgress((float) exp.first / exp.second);
+ }
+}
+
+void Skill_Tab::update()
+{
+ int skillNum = getSkillNum();
+
+ // Update the skill information for reach skill
+ for (int a = 0; a < skillNum; a++)
+ {
+ updateSkill(a);
+ }
+}
diff --git a/src/gui/skilldialog.h b/src/gui/skilldialog.h
new file mode 100644
index 00000000..3d010daa
--- /dev/null
+++ b/src/gui/skilldialog.h
@@ -0,0 +1,139 @@
+/*
+ * 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 _TMW_SKILL_H
+#define _TMW_SKILL_H
+
+#include <vector>
+#include <list>
+
+#include <guichan/listmodel.hpp>
+#include <guichan/actionlistener.hpp>
+
+#include "window.h"
+#include "gccontainer.h"
+
+#include "../guichanfwd.h"
+
+class ProgressBar;
+class Icon;
+
+class Skill_Tab : public GCContainer, public gcn::ActionListener
+{
+ public:
+ /**
+ * The type of this skill tab
+ */
+ const std::string type;
+
+ /**
+ * Constructor
+ */
+ Skill_Tab(const std::string &type);
+
+ /**
+ * Update this tab
+ */
+ void update();
+
+ /**
+ * Called when receiving actions from widget.
+ */
+ void action(const gcn::ActionEvent &event) {}
+
+ private:
+ /**
+ * Update the information of a skill at
+ * the given index
+ */
+ void updateSkill(int index);
+
+ /**
+ * Gets the number of skills in this particular
+ * type of tab.
+ */
+ int getSkillNum();
+
+ /**
+ * Get the first enumeration of this skill tab's
+ * skill type.
+ */
+ int getSkillBegin();
+
+ /**
+ * Get the icon associated with the given index
+ */
+ Icon* getIcon(int index);
+
+ std::vector<Icon *> mSkillIcons;
+ std::vector<gcn::Label *> mSkillNameLabels;
+ std::vector<gcn::Label *> mSkillLevelLabels;
+ std::vector<gcn::Label *> mSkillExpLabels;
+ std::vector<ProgressBar *> mSkillProgress;
+};
+
+
+/**
+ * The skill dialog.
+ *
+ * \ingroup Interface
+ */
+class SkillDialog : public Window, public gcn::ActionListener
+{
+ public:
+ /**
+ * Constructor.
+ */
+ SkillDialog();
+
+ /**
+ * Destructor.
+ */
+ ~SkillDialog();
+
+ /**
+ * Called when receiving actions from widget.
+ */
+ void action(const gcn::ActionEvent &event);
+
+ /**
+ * Update the tabs in this dialog
+ */
+ void update();
+
+ /**
+ * Draw this window.
+ */
+ void draw(gcn::Graphics *g);
+
+ private:
+
+
+ std::list<Skill_Tab*> mTabs;
+
+};
+
+
+
+
+extern SkillDialog *skillDialog;
+
+#endif
diff --git a/src/gui/slider.cpp b/src/gui/slider.cpp
index afeecf17..9bfa840f 100644
--- a/src/gui/slider.cpp
+++ b/src/gui/slider.cpp
@@ -1,26 +1,27 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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 3b796425..56ea334a 100644
--- a/src/gui/slider.h
+++ b/src/gui/slider.h
@@ -1,32 +1,31 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SLIDER_H
-#define _TMW_SLIDER_H
+#ifndef SLIDER_H
+#define SLIDER_H
#include <guichan/widgets/slider.hpp>
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
index 843a973d..165d216f 100644
--- a/src/gui/speechbubble.cpp
+++ b/src/gui/speechbubble.cpp
@@ -1,68 +1,94 @@
/*
- * The Mana World
+ * Speech bubbles
* 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 "../resources/image.h"
-#include "../resources/resourcemanager.h"
+#include "../utils/gettext.h"
-SpeechBubble::SpeechBubble()
+SpeechBubble::SpeechBubble():
+ Window(_("Speech"), false, NULL, "graphics/gui/speechbubble.xml")
{
- mSpeechBox = new TextBox();
+ 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);
- // Height == Top Graphic (14px) + 1 Row of Text (15px) + Bottom Graphic (17px)
- setContentSize(135, 46);
- setTitleBarHeight(0);
- loadSkin("graphics/gui/speechbubble.xml");
-
mSpeechArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
mSpeechArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- mSpeechArea->setDimension(gcn::Rectangle(4, 15, 130, 28));
+ mSpeechArea->setDimension(gcn::Rectangle(4, boldFont->getHeight() + 3,
+ 130, 28));
mSpeechArea->setOpaque(false);
+ add(mCaption);
add(mSpeechArea);
setLocationRelativeTo(getParent());
+}
- // LEEOR / TODO: This causes an exception error.
- //moveToBottom(getParent());
-
- mSpeechBox->setTextWrapped( "" );
+void SpeechBubble::setCaption(const std::string &name, const gcn::Color &color)
+{
+ mCaption->setCaption(name);
+ mCaption->adjustSize();
+ mCaption->setForegroundColor(color);
}
-void SpeechBubble::setText(const std::string mText)
+void SpeechBubble::setText(std::string mText, bool showName)
{
- mSpeechBox->setTextWrapped( mText );
+ int width = mCaption->getWidth();
+ mSpeechBox->setTextWrapped(mText, 130 > width ? 130 : width);
+
+ const int fontHeight = getFont()->getHeight();
+ const int numRows = showName ? mSpeechBox->getNumberOfRows() + 1 :
+ mSpeechBox->getNumberOfRows();
+ int yPos = showName ? fontHeight + 3 : 3;
+ int height = (numRows * fontHeight);
+
+ if (width < mSpeechBox->getMinWidth())
+ width = mSpeechBox->getMinWidth();
- int numRows = mSpeechBox->getNumberOfRows();
+ if (numRows == 1)
+ {
+ yPos = (fontHeight / 4) + 3;
+ height = ((3 * fontHeight) / 2) + 1;
+ }
- // 31 == speechbubble Top + Bottom graphic pixel heights
- // 15 == height of each line of text (based on font heights)
- setContentSize(135, 31 + (numRows * 15) );
- mSpeechArea->setDimension(gcn::Rectangle(4, 15, 130, (31 + (numRows * 14)) - 18 ));
+ setContentSize(width + fontHeight, height + 6);
+ mSpeechArea->setDimension(gcn::Rectangle(4, yPos, width + 5, height));
}
unsigned int SpeechBubble::getNumRows()
diff --git a/src/gui/speechbubble.h b/src/gui/speechbubble.h
index 9fe61943..5d582b1d 100644
--- a/src/gui/speechbubble.h
+++ b/src/gui/speechbubble.h
@@ -1,44 +1,48 @@
/*
- * The Mana World
+ * Speech bubbles
* 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SPEECHBUBBLE_H__
-#define _TMW_SPEECHBUBBLE_H__
+#ifndef SPEECHBUBBLE_H
+#define SPEECHBUBBLE_H
-#include "textbox.h"
-#include "scrollarea.h"
#include "window.h"
+class ScrollArea;
+class TextBox;
+
class SpeechBubble : public Window
{
public:
SpeechBubble();
- void setText(const std::string mText);
+ void setCaption(const std::string &name,
+ const gcn::Color &color = 0x000000);
+ void setText(std::string mText, bool showName = true);
void setLocation(int x, int y);
unsigned int getNumRows();
private:
+ gcn::Label *mCaption;
TextBox *mSpeechBox;
ScrollArea *mSpeechArea;
};
-#endif // _TMW_SPEECHBUBBLE_H__
+#endif
diff --git a/src/gui/status.cpp b/src/gui/status.cpp
index 283a771b..3c48d045 100644
--- a/src/gui/status.cpp
+++ b/src/gui/status.cpp
@@ -1,226 +1,204 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 "../units.h"
+#include "../utils/gettext.h"
#include "../utils/strprintf.h"
-#include "../utils/tostring.h"
+#include "../utils/stringutils.h"
StatusWindow::StatusWindow(LocalPlayer *player):
Window(player->getName()),
- mPlayer(player)
+ mPlayer(player),
+ mCurrency(0)
{
setWindowName("Status");
- setResizable(true);
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("Level:");
- mMoneyLabel = new gcn::Label("Money:");
+ mLvlLabel = new gcn::Label(strprintf(_("Level: %d"), 0));
+ mJobLvlLabel = new gcn::Label(strprintf(_("Job: %d"), 0));
+ mGpLabel = new gcn::Label(strprintf(_("Money: %s"),
+ Units::formatCurrency(mCurrency).c_str()));
- mHpLabel = new gcn::Label("HP:");
+ mHpLabel = new gcn::Label(_("HP:"));
mHpBar = new ProgressBar(1.0f, 80, 15, 0, 171, 34);
- mHpValueLabel = new gcn::Label("");
-
- int y = 3;
- int x = 5;
-
- mLvlLabel->setPosition(x, y);
- x += mLvlLabel->getWidth() + 40;
- mMoneyLabel->setPosition(x, y);
- y += mLvlLabel->getHeight() + 5; // Next Row
- x = 5;
+ mXpLabel = new gcn::Label(_("Exp:"));
+ mXpBar = new ProgressBar(1.0f, 80, 15, 143, 192, 211);
- mHpLabel->setPosition(x, y);
- x += mHpLabel->getWidth() + 5;
- mHpBar->setPosition(x, y);
- x += mHpBar->getWidth() + 5;
- mHpValueLabel->setPosition(x, y);
+ mMpLabel = new gcn::Label(_("MP:"));
+ mMpBar = new ProgressBar(1.0f, 80, 15, 26, 102, 230);
- y += mHpLabel->getHeight() + 5; // Next Row
- x = 5;
-
- add(mLvlLabel);
- add(mMoneyLabel);
- add(mHpLabel);
- add(mHpValueLabel);
- add(mHpBar);
+ mJobLabel = new gcn::Label(_("Job:"));
+ mJobBar = new ProgressBar(1.0f, 80, 15, 220, 135, 203);
// ----------------------
// Stats Part
// ----------------------
// Static Labels
- gcn::Label *mStatsTitleLabel = new gcn::Label("Stats");
- gcn::Label *mStatsTotalLabel = new gcn::Label("Total");
+ 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:");
- mStatsAccuracyLabel = new gcn::Label("% Accuracy:");
- mStatsEvadeLabel = new gcn::Label("% Evade:");
- mStatsReflexLabel = new gcn::Label("% Reflex:");
-
- mStatsAttackPoints = new gcn::Label("");
- mStatsDefensePoints = new gcn::Label("");
- mStatsMagicAttackPoints = new gcn::Label("");
- mStatsMagicDefensePoints = new gcn::Label("");
- mStatsAccuracyPoints = new gcn::Label("% Accuracy:");
- mStatsEvadePoints = new gcn::Label("% Evade:");
- mStatsReflexPoints = new gcn::Label("% Reflex:");
-*/
+ 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;
+ mStatsDefensePoints = new gcn::Label;
+ mStatsMagicAttackPoints = new gcn::Label;
+ mStatsMagicDefensePoints = new gcn::Label;
+ mStatsAccuracyPoints = new gcn::Label;
+ mStatsEvadePoints = new gcn::Label;
+ mStatsReflexPoints = new gcn::Label;
+
// New labels
- for (int i = 0; i < 6; i++) {
- mStatsLabel[i] = new gcn::Label();
- mStatsDisplayLabel[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);
}
- mCharacterPointsLabel = new gcn::Label();
- mCorrectionPointsLabel = new gcn::Label();
+ mRemainingStatsPointsLabel = new gcn::Label;
// Set button events Id
- mStatsPlus[0] = new Button("+", "STR+", this);
- mStatsPlus[1] = new Button("+", "AGI+", this);
- mStatsPlus[2] = new Button("+", "DEX+", this);
- mStatsPlus[3] = new Button("+", "VIT+", this);
- mStatsPlus[4] = new Button("+", "INT+", this);
- mStatsPlus[5] = new Button("+", "WIL+", this);
-
- mStatsMinus[0] = new Button("-", "STR-", this);
- mStatsMinus[1] = new Button("-", "AGI-", this);
- mStatsMinus[2] = new Button("-", "DEX-", this);
- mStatsMinus[3] = new Button("-", "VIT-", this);
- mStatsMinus[4] = new Button("-", "INT-", this);
- mStatsMinus[5] = new Button("-", "WIL-", this);
-
-
-
- // Set position
- mStatsTitleLabel->setPosition(mHpLabel->getX(), mHpLabel->getY() + 23 );
- mStatsTotalLabel->setPosition(110, mStatsTitleLabel->getY() + 15);
- int totalLabelY = mStatsTotalLabel->getY();
+ mStatsButton[0] = new Button("+", "STR", this);
+ mStatsButton[1] = new Button("+", "AGI", this);
+ mStatsButton[2] = new Button("+", "VIT", this);
+ mStatsButton[3] = new Button("+", "INT", this);
+ mStatsButton[4] = new Button("+", "DEX", this);
+ mStatsButton[5] = new Button("+", "LUK", this);
+ // 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);
- mStatsMinus[i]->setPosition(85, totalLabelY + (i * 23) + 15);
- mStatsDisplayLabel[i]->setPosition(125,
- totalLabelY + (i * 23) + 15);
- mStatsPlus[i]->setPosition(185, 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);
- mCharacterPointsLabel->setPosition(5, mStatsDisplayLabel[5]->getY() + 25);
- mCorrectionPointsLabel->setPosition(5, mStatsDisplayLabel[5]->getY() + 35);
-/*
- 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, mStatsLabel[6]->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, mStatsLabel[6]->getY());
-*/
- // Assemble
- add(mStatsTitleLabel);
- add(mStatsTotalLabel);
- for(int i = 0; i < 6; i++)
- {
- add(mStatsLabel[i]);
- add(mStatsDisplayLabel[i]);
- add(mStatsPlus[i]);
- add(mStatsMinus[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(mCharacterPointsLabel);
- add(mCorrectionPointsLabel);
+ loadWindowState();
}
void StatusWindow::update()
{
// Status Part
// -----------
- mLvlLabel->setCaption( "Level: " +
- toString(mPlayer->getLevel()) +
- " (" +
- toString(mPlayer->getLevelProgress()) +
- "%)");
+ mLvlLabel->setCaption(strprintf(_("Level: %d"), mPlayer->getLevel()));
mLvlLabel->adjustSize();
- mMoneyLabel->setCaption("Money: " + toString(mPlayer->getMoney()) + " GP");
- mMoneyLabel->adjustSize();
+ mJobLvlLabel->setCaption(strprintf(_("Job: %d"), mPlayer->mJobLevel));
+ mJobLvlLabel->adjustSize();
- int hp = mPlayer->getHP();
- int maxHp = mPlayer->getMaxHP();
+ if (mCurrency != mPlayer->getMoney()) {
+ mCurrency = mPlayer->getMoney();
+ mGpLabel->setCaption(strprintf(_("Money: %s"),
+ Units::formatCurrency(mCurrency).c_str()));
+ mGpLabel->adjustSize();
+ }
+
+ mHpBar->setText(toString(mPlayer->getHp()) +
+ "/" + toString(mPlayer->getMaxHp()));
+
+ mMpBar->setText(toString(mPlayer->mMp) +
+ "/" + toString(mPlayer->mMaxMp));
- mHpValueLabel->setCaption(toString(hp) +
- " / " + toString(maxHp));
- mHpValueLabel->adjustSize();
+ mXpBar->setText(toString(mPlayer->getXp()) +
+ "/" + toString(mPlayer->mXpForNextLevel));
+
+ mJobBar->setText(toString(mPlayer->mJobXp) +
+ "/" + toString(mPlayer->mJobXpForNextLevel));
// HP Bar coloration
- if (hp < int(maxHp / 3))
+ if (mPlayer->getHp() < int(mPlayer->getMaxHp() / 3))
{
mHpBar->setColor(223, 32, 32); // Red
}
- else if (hp < int((maxHp / 3) * 2))
+ else if (mPlayer->getHp() < int((mPlayer->getMaxHp() / 3) * 2))
{
mHpBar->setColor(230, 171, 34); // Orange
}
@@ -229,43 +207,43 @@ void StatusWindow::update()
mHpBar->setColor(0, 171, 34); // Green
}
- mHpBar->setProgress((float) hp / maxHp);
+ mHpBar->setProgress((float) mPlayer->getHp() / (float) mPlayer->getMaxHp());
+ mMpBar->setProgress((float) mPlayer->mMp / (float) mPlayer->mMaxMp);
+
+ mXpBar->setProgress(
+ (float) mPlayer->getXp() / (float) mPlayer->mXpForNextLevel);
+ mJobBar->setProgress(
+ (float) mPlayer->mJobXp / (float) mPlayer->mJobXpForNextLevel);
// Stats Part
// ----------
- const std::string attrNames[6] = {
- "Strength",
- "Agility",
- "Dexterity",
- "Vitality",
- "Intelligence",
- "Willpower"
+ static const char *attrNames[6] = {
+ N_("Strength"),
+ N_("Agility"),
+ N_("Vitality"),
+ N_("Intelligence"),
+ N_("Dexterity"),
+ N_("Luck")
};
- int characterPoints = mPlayer->getCharacterPoints();
- int correctionPoints = mPlayer->getCorrectionPoints();
+ int statusPoints = mPlayer->mStatsPointsToAttribute;
+
// Update labels
for (int i = 0; i < 6; i++)
{
- mStatsLabel[i]->setCaption(attrNames[i]);
- mStatsDisplayLabel[i]->setCaption(
- strprintf("%d / %d",
- mPlayer->getAttributeEffective(CHAR_ATTR_BEGIN + i),
- mPlayer->getAttributeBase(CHAR_ATTR_BEGIN + i)));
+ mStatsLabel[i]->setCaption(gettext(attrNames[i]));
+ mStatsDisplayLabel[i]->setCaption(toString((int) mPlayer->mAttr[i]));
+ mPointsLabel[i]->setCaption(toString((int) mPlayer->mAttrUp[i]));
mStatsLabel[i]->adjustSize();
mStatsDisplayLabel[i]->adjustSize();
+ mPointsLabel[i]->adjustSize();
- mStatsPlus[i]->setEnabled(characterPoints);
- mStatsMinus[i]->setEnabled(correctionPoints);
+ mStatsButton[i]->setEnabled(mPlayer->mAttrUp[i] <= statusPoints);
}
- mCharacterPointsLabel->setCaption("Character Points: " +
- toString(characterPoints));
- mCharacterPointsLabel->adjustSize();
+ mRemainingStatsPointsLabel->setCaption(
+ strprintf(_("Remaining Status Points: %d"), statusPoints));
+ mRemainingStatsPointsLabel->adjustSize();
- mCorrectionPointsLabel->setCaption("Correction Points: " +
- toString(correctionPoints));
- mCorrectionPointsLabel->adjustSize();
-/*
// Derived Stats Points
// Attack TODO: Count equipped Weapons and items attack bonuses
@@ -299,11 +277,6 @@ void StatusWindow::update()
// Reflex %
mStatsReflexPoints->setCaption(toString(mPlayer->DEX / 4)); // + counter
mStatsReflexPoints->adjustSize();
-*/
- // Update Second column widgets position
- mMoneyLabel->setPosition(mLvlLabel->getX() + mLvlLabel->getWidth() + 20,
- mLvlLabel->getY());
-
}
void StatusWindow::draw(gcn::Graphics *g)
@@ -315,56 +288,33 @@ void StatusWindow::draw(gcn::Graphics *g)
void StatusWindow::action(const gcn::ActionEvent &event)
{
- const std::string &eventId = event.getId();
-
// Stats Part
- if (eventId == "STR+")
- {
- mPlayer->raiseAttribute(LocalPlayer::STR);
- }
- else if (eventId == "AGI+")
- {
- mPlayer->raiseAttribute(LocalPlayer::AGI);
- }
- else if (eventId == "DEX+")
+ if (event.getId().length() == 3)
{
- mPlayer->raiseAttribute(LocalPlayer::DEX);
- }
- else if (eventId == "VIT+")
- {
- mPlayer->raiseAttribute(LocalPlayer::VIT);
- }
- else if (eventId == "INT+")
- {
- mPlayer->raiseAttribute(LocalPlayer::INT);
- }
- else if (eventId == "WIL+")
- {
- mPlayer->raiseAttribute(LocalPlayer::WIL);
- }
-
- else if (eventId == "STR-")
- {
- mPlayer->lowerAttribute(LocalPlayer::STR);
- }
- else if (eventId == "AGI-")
- {
- mPlayer->lowerAttribute(LocalPlayer::AGI);
- }
- else if (eventId == "DEX-")
- {
- mPlayer->lowerAttribute(LocalPlayer::DEX);
- }
- else if (eventId == "VIT-")
- {
- mPlayer->lowerAttribute(LocalPlayer::VIT);
- }
- else if (eventId == "INT-")
- {
- mPlayer->lowerAttribute(LocalPlayer::INT);
- }
- else if (eventId == "WIL-")
- {
- mPlayer->lowerAttribute(LocalPlayer::WIL);
+ if (event.getId() == "STR")
+ {
+ player_node->raiseAttribute(LocalPlayer::STR);
+ }
+ if (event.getId() == "AGI")
+ {
+ player_node->raiseAttribute(LocalPlayer::AGI);
+ }
+ if (event.getId() == "VIT")
+ {
+ player_node->raiseAttribute(LocalPlayer::VIT);
+ }
+ if (event.getId() == "INT")
+ {
+ player_node->raiseAttribute(LocalPlayer::INT);
+ }
+ if (event.getId() == "DEX")
+ {
+ player_node->raiseAttribute(LocalPlayer::DEX);
+ }
+ if (event.getId() == "LUK")
+ {
+ player_node->raiseAttribute(LocalPlayer::LUK);
+ }
}
}
+
diff --git a/src/gui/status.h b/src/gui/status.h
index 262b89f6..9e4de3fd 100644
--- a/src/gui/status.h
+++ b/src/gui/status.h
@@ -1,39 +1,34 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_STATUS_H
-#define _TMW_STATUS_H
-
-#include <iosfwd>
+#ifndef STATUS_H
+#define STATUS_H
#include <guichan/actionlistener.hpp>
#include "window.h"
-#include "../guichanfwd.h"
-
class LocalPlayer;
class ProgressBar;
-
/**
* The player status dialog.
*
@@ -68,13 +63,16 @@ class StatusWindow : public Window, public gcn::ActionListener
/**
* Status Part
*/
- gcn::Label *mLvlLabel, *mMoneyLabel, *mHpLabel, *mHpValueLabel;
- ProgressBar *mHpBar;
+ gcn::Label *mLvlLabel, *mJobLvlLabel;
+ gcn::Label *mGpLabel;
+ int mCurrency;
+ gcn::Label *mHpLabel, *mMpLabel, *mXpLabel, *mJobLabel;
+ ProgressBar *mHpBar, *mMpBar;
+ ProgressBar *mXpBar, *mJobBar;
/**
* Derived Statistics captions
*/
-/*
gcn::Label *mStatsAttackLabel, *mStatsDefenseLabel;
gcn::Label *mStatsMagicAttackLabel, *mStatsMagicDefenseLabel;
gcn::Label *mStatsAccuracyLabel, *mStatsEvadeLabel;
@@ -84,20 +82,19 @@ class StatusWindow : public Window, public gcn::ActionListener
gcn::Label *mStatsMagicAttackPoints, *mStatsMagicDefensePoints;
gcn::Label *mStatsAccuracyPoints, *mStatsEvadePoints;
gcn::Label *mStatsReflexPoints;
-*/
+
/**
* Stats captions.
*/
gcn::Label *mStatsLabel[6];
+ gcn::Label *mPointsLabel[6];
gcn::Label *mStatsDisplayLabel[6];
- gcn::Label *mCharacterPointsLabel;
- gcn::Label *mCorrectionPointsLabel;
+ gcn::Label *mRemainingStatsPointsLabel;
/**
* Stats buttons.
*/
- gcn::Button *mStatsPlus[6];
- gcn::Button *mStatsMinus[6];
+ gcn::Button *mStatsButton[6];
};
extern StatusWindow *statusWindow;
diff --git a/src/gui/statuswindow.cpp b/src/gui/statuswindow.cpp
new file mode 100644
index 00000000..bcac0a90
--- /dev/null
+++ b/src/gui/statuswindow.cpp
@@ -0,0 +1,370 @@
+/*
+ * 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 "statuswindow.h"
+
+#include <guichan/widgets/label.hpp>
+
+#include "button.h"
+#include "progressbar.h"
+#include "windowcontainer.h"
+
+#include "../localplayer.h"
+
+#include "../utils/strprintf.h"
+#include "../utils/stringutils.h"
+
+StatusWindow::StatusWindow(LocalPlayer *player):
+ Window(player->getName()),
+ mPlayer(player)
+{
+ setWindowName("Status");
+ setResizable(true);
+ setCloseButton(true);
+ setDefaultSize((windowContainer->getWidth() - 365) / 2,
+ (windowContainer->getHeight() - 255) / 2, 365, 275);
+ loadWindowState();
+
+ // ----------------------
+ // Status Part
+ // ----------------------
+
+ mLvlLabel = new gcn::Label("Level:");
+ mMoneyLabel = new gcn::Label("Money:");
+
+ mHpLabel = new gcn::Label("HP:");
+ mHpBar = new ProgressBar(1.0f, 80, 15, 0, 171, 34);
+ mHpValueLabel = new gcn::Label("");
+
+ int y = 3;
+ int x = 5;
+
+ mLvlLabel->setPosition(x, y);
+ x += mLvlLabel->getWidth() + 40;
+ mMoneyLabel->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);
+
+ y += mHpLabel->getHeight() + 5; // Next Row
+ x = 5;
+
+ add(mLvlLabel);
+ add(mMoneyLabel);
+ add(mHpLabel);
+ add(mHpValueLabel);
+ add(mHpBar);
+
+ // ----------------------
+ // Stats Part
+ // ----------------------
+
+ // Static Labels
+ gcn::Label *mStatsTitleLabel = new gcn::Label("Stats");
+ gcn::Label *mStatsTotalLabel = new gcn::Label("Total");
+
+ // Derived Stats
+/*
+ mStatsAttackLabel = new gcn::Label("Attack:");
+ mStatsDefenseLabel= new gcn::Label("Defense:");
+ mStatsMagicAttackLabel = new gcn::Label("M.Attack:");
+ mStatsMagicDefenseLabel = new gcn::Label("M.Defense:");
+ mStatsAccuracyLabel = new gcn::Label("% Accuracy:");
+ mStatsEvadeLabel = new gcn::Label("% Evade:");
+ mStatsReflexLabel = new gcn::Label("% Reflex:");
+
+ mStatsAttackPoints = new gcn::Label("");
+ mStatsDefensePoints = new gcn::Label("");
+ mStatsMagicAttackPoints = new gcn::Label("");
+ mStatsMagicDefensePoints = new gcn::Label("");
+ mStatsAccuracyPoints = new gcn::Label("% Accuracy:");
+ mStatsEvadePoints = new gcn::Label("% Evade:");
+ mStatsReflexPoints = new gcn::Label("% Reflex:");
+*/
+ // New labels
+ for (int i = 0; i < 6; i++) {
+ mStatsLabel[i] = new gcn::Label();
+ mStatsDisplayLabel[i] = new gcn::Label();
+ }
+ mCharacterPointsLabel = new gcn::Label();
+ mCorrectionPointsLabel = new gcn::Label();
+
+ // Set button events Id
+ mStatsPlus[0] = new Button("+", "STR+", this);
+ mStatsPlus[1] = new Button("+", "AGI+", this);
+ mStatsPlus[2] = new Button("+", "DEX+", this);
+ mStatsPlus[3] = new Button("+", "VIT+", this);
+ mStatsPlus[4] = new Button("+", "INT+", this);
+ mStatsPlus[5] = new Button("+", "WIL+", this);
+
+ mStatsMinus[0] = new Button("-", "STR-", this);
+ mStatsMinus[1] = new Button("-", "AGI-", this);
+ mStatsMinus[2] = new Button("-", "DEX-", this);
+ mStatsMinus[3] = new Button("-", "VIT-", this);
+ mStatsMinus[4] = new Button("-", "INT-", this);
+ mStatsMinus[5] = new Button("-", "WIL-", this);
+
+
+
+ // Set position
+ mStatsTitleLabel->setPosition(mHpLabel->getX(), mHpLabel->getY() + 23 );
+ mStatsTotalLabel->setPosition(110, mStatsTitleLabel->getY() + 15);
+ int totalLabelY = mStatsTotalLabel->getY();
+
+ for (int i = 0; i < 6; i++)
+ {
+ mStatsLabel[i]->setPosition(5,
+ mStatsTotalLabel->getY() + (i * 23) + 15);
+ mStatsMinus[i]->setPosition(85, totalLabelY + (i * 23) + 15);
+ mStatsDisplayLabel[i]->setPosition(125,
+ totalLabelY + (i * 23) + 15);
+ mStatsPlus[i]->setPosition(185, totalLabelY + (i * 23) + 15);
+ }
+
+ mCharacterPointsLabel->setPosition(5, mStatsDisplayLabel[5]->getY() + 25);
+ mCorrectionPointsLabel->setPosition(5, mStatsDisplayLabel[5]->getY() + 35);
+/*
+ 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, mStatsLabel[6]->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, mStatsLabel[6]->getY());
+*/
+ // Assemble
+ add(mStatsTitleLabel);
+ add(mStatsTotalLabel);
+ for(int i = 0; i < 6; i++)
+ {
+ add(mStatsLabel[i]);
+ add(mStatsDisplayLabel[i]);
+ add(mStatsPlus[i]);
+ add(mStatsMinus[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(mCharacterPointsLabel);
+ add(mCorrectionPointsLabel);
+}
+
+void StatusWindow::update()
+{
+ // Status Part
+ // -----------
+ mLvlLabel->setCaption( "Level: " +
+ toString(mPlayer->getLevel()) +
+ " (" +
+ toString(mPlayer->getLevelProgress()) +
+ "%)");
+ mLvlLabel->adjustSize();
+
+ mMoneyLabel->setCaption("Money: " + toString(mPlayer->getMoney()) + " GP");
+ mMoneyLabel->adjustSize();
+
+ int hp = mPlayer->getHp();
+ int maxHp = mPlayer->getMaxHp();
+
+ mHpValueLabel->setCaption(toString(hp) +
+ " / " + toString(maxHp));
+ mHpValueLabel->adjustSize();
+
+ // HP Bar coloration
+ if (hp < int(maxHp / 3))
+ {
+ mHpBar->setColor(223, 32, 32); // Red
+ }
+ else if (hp < int((maxHp / 3) * 2))
+ {
+ mHpBar->setColor(230, 171, 34); // Orange
+ }
+ else
+ {
+ mHpBar->setColor(0, 171, 34); // Green
+ }
+
+ mHpBar->setProgress((float) hp / maxHp);
+
+ // Stats Part
+ // ----------
+ const std::string attrNames[6] = {
+ "Strength",
+ "Agility",
+ "Dexterity",
+ "Vitality",
+ "Intelligence",
+ "Willpower"
+ };
+ int characterPoints = mPlayer->getCharacterPoints();
+ int correctionPoints = mPlayer->getCorrectionPoints();
+ // Update labels
+ for (int i = 0; i < 6; i++)
+ {
+ mStatsLabel[i]->setCaption(attrNames[i]);
+ mStatsDisplayLabel[i]->setCaption(
+ strprintf("%d / %d",
+ mPlayer->getAttributeEffective(CHAR_ATTR_BEGIN + i),
+ mPlayer->getAttributeBase(CHAR_ATTR_BEGIN + i)));
+
+ mStatsLabel[i]->adjustSize();
+ mStatsDisplayLabel[i]->adjustSize();
+
+ mStatsPlus[i]->setEnabled(characterPoints);
+ mStatsMinus[i]->setEnabled(correctionPoints);
+ }
+ mCharacterPointsLabel->setCaption("Character Points: " +
+ toString(characterPoints));
+ mCharacterPointsLabel->adjustSize();
+
+ mCorrectionPointsLabel->setCaption("Correction Points: " +
+ toString(correctionPoints));
+ mCorrectionPointsLabel->adjustSize();
+/*
+ // Derived Stats Points
+
+ // Attack TODO: Count equipped Weapons and items attack bonuses
+ mStatsAttackPoints->setCaption(
+ toString(mPlayer->ATK + mPlayer->ATK_BONUS));
+ mStatsAttackPoints->adjustSize();
+
+ // Defense TODO: Count equipped Armors and items defense bonuses
+ mStatsDefensePoints->setCaption(
+ toString(mPlayer->DEF + mPlayer->DEF_BONUS));
+ mStatsDefensePoints->adjustSize();
+
+ // Magic Attack TODO: Count equipped items M.Attack bonuses
+ mStatsMagicAttackPoints->setCaption(
+ toString(mPlayer->MATK + mPlayer->MATK_BONUS));
+ mStatsMagicAttackPoints->adjustSize();
+
+ // Magic Defense TODO: Count equipped items M.Defense bonuses
+ mStatsMagicDefensePoints->setCaption(
+ toString(mPlayer->MDEF + mPlayer->MDEF_BONUS));
+ mStatsMagicDefensePoints->adjustSize();
+
+ // Accuracy %
+ mStatsAccuracyPoints->setCaption(toString(mPlayer->HIT));
+ mStatsAccuracyPoints->adjustSize();
+
+ // Evasion %
+ mStatsEvadePoints->setCaption(toString(mPlayer->FLEE));
+ mStatsEvadePoints->adjustSize();
+
+ // Reflex %
+ mStatsReflexPoints->setCaption(toString(mPlayer->DEX / 4)); // + counter
+ mStatsReflexPoints->adjustSize();
+*/
+ // Update Second column widgets position
+ mMoneyLabel->setPosition(mLvlLabel->getX() + mLvlLabel->getWidth() + 20,
+ mLvlLabel->getY());
+
+}
+
+void StatusWindow::draw(gcn::Graphics *g)
+{
+ update();
+
+ Window::draw(g);
+}
+
+void StatusWindow::action(const gcn::ActionEvent &event)
+{
+ const std::string &eventId = event.getId();
+
+ // Stats Part
+ if (eventId == "STR+")
+ {
+ mPlayer->raiseAttribute(LocalPlayer::STR);
+ }
+ else if (eventId == "AGI+")
+ {
+ mPlayer->raiseAttribute(LocalPlayer::AGI);
+ }
+ else if (eventId == "DEX+")
+ {
+ mPlayer->raiseAttribute(LocalPlayer::DEX);
+ }
+ else if (eventId == "VIT+")
+ {
+ mPlayer->raiseAttribute(LocalPlayer::VIT);
+ }
+ else if (eventId == "INT+")
+ {
+ mPlayer->raiseAttribute(LocalPlayer::INT);
+ }
+ else if (eventId == "WIL+")
+ {
+ mPlayer->raiseAttribute(LocalPlayer::WIL);
+ }
+
+ else if (eventId == "STR-")
+ {
+ mPlayer->lowerAttribute(LocalPlayer::STR);
+ }
+ else if (eventId == "AGI-")
+ {
+ mPlayer->lowerAttribute(LocalPlayer::AGI);
+ }
+ else if (eventId == "DEX-")
+ {
+ mPlayer->lowerAttribute(LocalPlayer::DEX);
+ }
+ else if (eventId == "VIT-")
+ {
+ mPlayer->lowerAttribute(LocalPlayer::VIT);
+ }
+ else if (eventId == "INT-")
+ {
+ mPlayer->lowerAttribute(LocalPlayer::INT);
+ }
+ else if (eventId == "WIL-")
+ {
+ mPlayer->lowerAttribute(LocalPlayer::WIL);
+ }
+}
diff --git a/src/gui/statuswindow.h b/src/gui/statuswindow.h
new file mode 100644
index 00000000..262b89f6
--- /dev/null
+++ b/src/gui/statuswindow.h
@@ -0,0 +1,105 @@
+/*
+ * 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 _TMW_STATUS_H
+#define _TMW_STATUS_H
+
+#include <iosfwd>
+
+#include <guichan/actionlistener.hpp>
+
+#include "window.h"
+
+#include "../guichanfwd.h"
+
+class LocalPlayer;
+class ProgressBar;
+
+
+/**
+ * The player status dialog.
+ *
+ * \ingroup Interface
+ */
+class StatusWindow : public Window, public gcn::ActionListener
+{
+ public:
+ /**
+ * Constructor.
+ */
+ StatusWindow(LocalPlayer *player);
+
+ /**
+ * Called when receiving actions from widget.
+ */
+ void action(const gcn::ActionEvent &event);
+
+ /**
+ * Draw this window
+ */
+ void draw(gcn::Graphics *graphics);
+
+ /**
+ * Updates this dialog with values from PLAYER_INFO *char_info
+ */
+ void update();
+
+ private:
+ LocalPlayer *mPlayer;
+
+ /**
+ * Status Part
+ */
+ gcn::Label *mLvlLabel, *mMoneyLabel, *mHpLabel, *mHpValueLabel;
+ ProgressBar *mHpBar;
+
+ /**
+ * Derived Statistics captions
+ */
+/*
+ gcn::Label *mStatsAttackLabel, *mStatsDefenseLabel;
+ gcn::Label *mStatsMagicAttackLabel, *mStatsMagicDefenseLabel;
+ gcn::Label *mStatsAccuracyLabel, *mStatsEvadeLabel;
+ gcn::Label *mStatsReflexLabel;
+
+ gcn::Label *mStatsAttackPoints, *mStatsDefensePoints;
+ gcn::Label *mStatsMagicAttackPoints, *mStatsMagicDefensePoints;
+ gcn::Label *mStatsAccuracyPoints, *mStatsEvadePoints;
+ gcn::Label *mStatsReflexPoints;
+*/
+ /**
+ * Stats captions.
+ */
+ gcn::Label *mStatsLabel[6];
+ gcn::Label *mStatsDisplayLabel[6];
+ gcn::Label *mCharacterPointsLabel;
+ gcn::Label *mCorrectionPointsLabel;
+
+ /**
+ * Stats buttons.
+ */
+ gcn::Button *mStatsPlus[6];
+ gcn::Button *mStatsMinus[6];
+};
+
+extern StatusWindow *statusWindow;
+
+#endif
diff --git a/src/gui/table.cpp b/src/gui/table.cpp
new file mode 100644
index 00000000..1fd088ce
--- /dev/null
+++ b/src/gui/table.cpp
@@ -0,0 +1,561 @@
+/*
+ * The Mana World
+ * 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
+ */
+
+#include <guichan/actionlistener.hpp>
+#include <guichan/graphics.hpp>
+#include <guichan/key.hpp>
+
+#include "color.h"
+#include "table.h"
+
+#include "../configuration.h"
+
+#include "../utils/dtor.h"
+
+float GuiTable::mAlpha = config.getValue("guialpha", 0.8);
+
+class GuiTableActionListener : public gcn::ActionListener
+{
+public:
+ GuiTableActionListener(GuiTable *_table, gcn::Widget *_widget, int _row, int _column);
+
+ virtual ~GuiTableActionListener();
+
+ virtual void action(const gcn::ActionEvent& actionEvent);
+
+protected:
+ GuiTable *mTable;
+ int mRow;
+ int mColumn;
+ gcn::Widget *mWidget;
+};
+
+
+GuiTableActionListener::GuiTableActionListener(GuiTable *table, gcn::Widget *widget, int row, int column) :
+ mTable(table),
+ mRow(row),
+ mColumn(column),
+ mWidget(widget)
+{
+ if (widget)
+ {
+ widget->addActionListener(this);
+ widget->_setParent(table);
+ }
+}
+
+GuiTableActionListener::~GuiTableActionListener()
+{
+ if (mWidget)
+ {
+ mWidget->removeActionListener(this);
+ mWidget->_setParent(NULL);
+ }
+}
+
+void GuiTableActionListener::action(const gcn::ActionEvent& actionEvent)
+{
+ mTable->setSelected(mRow, mColumn);
+ mTable->distributeActionEvent();
+}
+
+
+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);
+}
+
+GuiTable::~GuiTable()
+{
+ delete mModel;
+}
+
+TableModel *GuiTable::getModel() const
+{
+ return mModel;
+}
+
+void GuiTable::setModel(TableModel *new_model)
+{
+ if (mModel)
+ {
+ uninstallActionListeners();
+ mModel->removeListener(this);
+ }
+
+ mModel = new_model;
+ installActionListeners();
+
+ if (new_model)
+ {
+ new_model->installListener(this);
+ recomputeDimensions();
+ }
+}
+
+void GuiTable::recomputeDimensions()
+{
+ int rows_nr = mModel->getRows();
+ int columns_nr = mModel->getColumns();
+ int width = 0;
+ int height = 0;
+
+ if (mSelectedRow >= rows_nr)
+ mSelectedRow = rows_nr - 1;
+
+ if (mSelectedColumn >= columns_nr)
+ mSelectedColumn = columns_nr - 1;
+
+ for (int i = 0; i < columns_nr; i++)
+ width += getColumnWidth(i);
+
+ height = getRowHeight() * rows_nr;
+
+ setWidth(width);
+ setHeight(height);
+}
+
+void GuiTable::setSelected(int row, int column)
+{
+ mSelectedColumn = column;
+ mSelectedRow = row;
+}
+
+int GuiTable::getSelectedRow()
+{
+ return mSelectedRow;
+}
+
+int GuiTable::getSelectedColumn()
+{
+ return mSelectedColumn;
+}
+
+void GuiTable::setLinewiseSelection(bool linewise)
+{
+ mLinewiseMode = linewise;
+}
+
+int GuiTable::getRowHeight()
+{
+ if (mModel)
+ return mModel->getRowHeight() + 1; // border
+ else
+ return 0;
+}
+
+int GuiTable::getColumnWidth(int i)
+{
+ if (mModel)
+ return mModel->getColumnWidth(i) + 1; // border
+ else
+ return 0;
+}
+
+void GuiTable::setSelectedRow(int selected)
+{
+ 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(mActionListeners);
+ mActionListeners.clear();
+}
+
+void GuiTable::installActionListeners()
+{
+ if (!mModel)
+ return;
+
+ int rows = mModel->getRows();
+ int columns = mModel->getColumns();
+
+ for (int row = 0; row < rows; ++row)
+ for (int column = 0; column < columns; ++column)
+ {
+ gcn::Widget *widget = mModel->getElementAt(row, column);
+ mActionListeners.push_back(new GuiTableActionListener(this, widget,
+ row, column));
+ }
+
+ _setFocusHandler(_getFocusHandler()); // propagate focus handler to widgets
+}
+
+// -- widget ops
+void GuiTable::draw(gcn::Graphics* graphics)
+{
+ 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 = (int)(mAlpha * 255.0f);
+ 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());
+
+ if (first_row < 0)
+ first_row = 0;
+
+ int rows_nr = 1 + (getHeight() / getRowHeight()); // May overestimate by one.
+
+ int max_rows_nr = mModel->getRows() - first_row; // clip if neccessary:
+ if (max_rows_nr < rows_nr)
+ rows_nr = max_rows_nr;
+
+ // Now determine the first and last column
+ // Take the easy way out; these are usually bounded and all visible.
+ int first_column = 0;
+ int last_column = mModel->getColumns() - 1;
+
+ // Set up everything for drawing
+ int height = getRowHeight();
+ int y_offset = first_row * height;
+
+ for (int r = first_row; r < first_row + rows_nr; ++r)
+ {
+ int x_offset = 0;
+
+ for (int c = first_column; c <= last_column; ++c)
+ {
+ gcn::Widget *widget = mModel->getElementAt(r, c);
+ int width = getColumnWidth(c);
+ if (widget)
+ {
+ gcn::Rectangle bounds(x_offset, y_offset, width, height);
+
+ 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 = (int)(mAlpha * 127.0f);
+
+ graphics->setColor(gcn::Color(red, green, blue, alpha));
+ graphics->fillRectangle(bounds);
+ }
+
+ graphics->pushClipArea(bounds);
+ widget->draw(graphics);
+ graphics->popClipArea();
+ }
+
+ x_offset += width;
+ }
+
+ 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 = (int)(mAlpha * 127.0f);
+
+ graphics->setColor(gcn::Color(red, green, blue, alpha));
+ graphics->fillRectangle(gcn::Rectangle(0, y_offset,
+ x_offset, height));
+ }
+
+ y_offset += height;
+ }
+
+ if (mTopWidget)
+ {
+ gcn::Rectangle bounds = mTopWidget->getDimension();
+ graphics->pushClipArea(bounds);
+ mTopWidget->draw(graphics);
+ graphics->popClipArea();
+ }
+}
+
+void GuiTable::moveToTop(gcn::Widget *widget)
+{
+ gcn::Widget::moveToTop(widget);
+ mTopWidget = widget;
+}
+
+void GuiTable::moveToBottom(gcn::Widget *widget)
+{
+ gcn::Widget::moveToBottom(widget);
+ if (widget == mTopWidget)
+ mTopWidget = NULL;
+}
+
+gcn::Rectangle GuiTable::getChildrenArea()
+{
+ return gcn::Rectangle(0, 0, getWidth(), getHeight());
+}
+
+// -- 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)
+ {
+ int row = getRowForY(mouseEvent.getY());
+ int column = getColumnForX(mouseEvent.getX());
+
+ if (row > -1 && column > -1 &&
+ row < mModel->getRows() && column < mModel->getColumns())
+ {
+ mSelectedColumn = column;
+ mSelectedRow = row;
+ }
+
+ distributeActionEvent();
+ }
+}
+
+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)
+{
+}
+
+// -- TableModelListener notifications
+void GuiTable::modelUpdated(bool completed)
+{
+ if (completed)
+ {
+ recomputeDimensions();
+ installActionListeners();
+ }
+ else
+ { // before the update?
+ mTopWidget = NULL; // No longer valid in general
+ uninstallActionListeners();
+ }
+}
+
+gcn::Widget *GuiTable::getWidgetAt(int x, int y)
+{
+ int row = getRowForY(y);
+ int column = getColumnForX(x);
+
+ if (mTopWidget && mTopWidget->getDimension().isPointInRect(x, y))
+ return mTopWidget;
+
+ 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
+ return NULL;
+}
+
+int GuiTable::getRowForY(int y)
+{
+ int row = y / getRowHeight();
+
+ if (row < 0 || row >= mModel->getRows())
+ return -1;
+ else
+ return row;
+}
+
+int GuiTable::getColumnForX(int x)
+{
+ int column;
+ int delta = 0;
+
+ for (column = 0; column < mModel->getColumns(); column++)
+ {
+ delta += getColumnWidth(column);
+ if (x <= delta)
+ break;
+ }
+
+ if (column < 0 || column >= mModel->getColumns())
+ return -1;
+ else
+ return column;
+}
+
+void GuiTable::_setFocusHandler(gcn::FocusHandler* focusHandler)
+{
+ gcn::Widget::_setFocusHandler(focusHandler);
+
+ if (mModel) {
+ for (int r = 0; r < mModel->getRows(); ++r) {
+ for (int c = 0; c < mModel->getColumns(); ++c) {
+ gcn::Widget *w = mModel->getElementAt(r, c);
+ if (w)
+ w->_setFocusHandler(focusHandler);
+ }
+ }
+ }
+}
diff --git a/src/gui/table.h b/src/gui/table.h
new file mode 100644
index 00000000..d73cf340
--- /dev/null
+++ b/src/gui/table.h
@@ -0,0 +1,187 @@
+/*
+ * The Mana World
+ * 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 TABLE_H
+#define TABLE_H
+
+#include <vector>
+
+#include <guichan/keylistener.hpp>
+#include <guichan/mouselistener.hpp>
+#include <guichan/widget.hpp>
+
+#include "table_model.h"
+
+class GuiTableActionListener;
+
+/**
+ * A table, with rows and columns made out of sub-widgets. Largely inspired by
+ * (and can be thought of as a generalisation of) the guichan listbox
+ * implementation.
+ *
+ * Normally you want this within a ScrollArea.
+ *
+ * \ingroup GUI
+ */
+class GuiTable : public gcn::Widget,
+ public gcn::MouseListener,
+ public gcn::KeyListener,
+ public TableModelListener
+{
+ // so that the action listener can call distributeActionEvent
+ friend class GuiTableActionListener;
+
+public:
+ GuiTable(TableModel * initial_model = NULL, gcn::Color background = 0xffffff,
+ bool opacity = true);
+
+ virtual ~GuiTable();
+
+ /**
+ * Retrieves the active table model
+ */
+ TableModel *getModel() const;
+
+ /**
+ * Sets the table model
+ *
+ * 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.
+ */
+ void setModel(TableModel *m);
+
+ const TableModel* getModel() {return mModel;}
+
+ void setSelected(int row, int column);
+
+ int getSelectedRow();
+
+ int getSelectedColumn();
+
+ 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.
+ *
+ * Note that column information is tracked even in linewise selection mode;
+ * this mode therefore only affects visualisation.
+ *
+ * Disabled by default.
+ *
+ * \param linewise: Whether to enable linewise selection mode
+ */
+ void setLinewiseSelection(bool linewise);
+
+ // Inherited from Widget
+ virtual void draw(gcn::Graphics* graphics);
+
+ virtual gcn::Widget *getWidgetAt(int x, int y);
+
+ virtual void moveToTop(gcn::Widget *child);
+
+ virtual void moveToBottom(gcn::Widget *child);
+
+ virtual void _setFocusHandler(gcn::FocusHandler* focusHandler);
+
+ // 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);
+
+ virtual void mouseWheelMovedUp(gcn::MouseEvent& mouseEvent);
+
+ virtual void mouseWheelMovedDown(gcn::MouseEvent& mouseEvent);
+
+ virtual void mouseDragged(gcn::MouseEvent& mouseEvent);
+
+ // Constraints inherited from TableModelListener
+ virtual void modelUpdated(bool);
+
+protected:
+ /** Frees all action listeners on inner widgets. */
+ virtual void uninstallActionListeners();
+ /** Installs all action listeners on inner widgets. */
+ virtual void installActionListeners();
+
+ virtual int getRowHeight();
+ virtual int getColumnWidth(int i);
+
+private:
+ int getRowForY(int y); // -1 on error
+ 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;
+
+ int mSelectedRow;
+ int mSelectedColumn;
+
+ /** Number of frames to skip upwards when drawing the selected widget. */
+ int mPopFramesNr;
+
+ /** If someone moves a fresh widget to the top, we must display it. */
+ gcn::Widget *mTopWidget;
+
+ /** Vector for compactness; used as a list in practice. */
+ std::vector<GuiTableActionListener *> mActionListeners;
+};
+
+
+#endif /* !defined(TABLE_H) */
diff --git a/src/gui/table_model.cpp b/src/gui/table_model.cpp
new file mode 100644
index 00000000..4fa13bae
--- /dev/null
+++ b/src/gui/table_model.cpp
@@ -0,0 +1,161 @@
+/*
+ * The Mana World
+ * 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
+ */
+
+#include <guichan/widget.hpp>
+
+#include "table_model.h"
+
+#include "../utils/dtor.h"
+
+void TableModel::installListener(TableModelListener *listener)
+{
+ listeners.insert(listener);
+}
+
+void TableModel::removeListener(TableModelListener *listener)
+{
+ listeners.erase(listener);
+}
+
+void TableModel::signalBeforeUpdate()
+{
+ for (std::set<TableModelListener *>::const_iterator it = listeners.begin(); it != listeners.end(); it++)
+ (*it)->modelUpdated(false);
+}
+
+void TableModel::signalAfterUpdate()
+{
+ for (std::set<TableModelListener *>::const_iterator it = listeners.begin(); it != listeners.end(); it++)
+ (*it)->modelUpdated(true);
+}
+
+
+#define WIDGET_AT(row, column) (((row) * mColumns) + (column))
+#define DYN_SIZE(h) ((h) >= 0) // determines whether this size is tagged for auto-detection
+
+StaticTableModel::StaticTableModel(int row, int column) :
+ mRows(row),
+ mColumns(column),
+ mHeight(1)
+{
+ mTableModel.resize(row * column, NULL);
+ mWidths.resize(column, 1);
+}
+
+StaticTableModel::~StaticTableModel()
+{
+ delete_all(mTableModel);
+}
+
+void StaticTableModel::resize()
+{
+ mRows = getRows();
+ mColumns = getColumns();
+ mTableModel.resize(mRows * mColumns, NULL);
+}
+
+void StaticTableModel::set(int row, int column, gcn::Widget *widget)
+{
+ if (row >= mRows || row < 0
+ || column >= mColumns || column < 0)
+ // raise exn?
+ return;
+
+ if (DYN_SIZE(mHeight)
+ && widget->getHeight() > mHeight)
+ mHeight = widget->getHeight();
+
+ if (DYN_SIZE(mWidths[column])
+ && widget->getWidth() > mWidths[column])
+ mWidths[column] = widget->getWidth();
+
+ signalBeforeUpdate();
+
+ if (mTableModel[WIDGET_AT(row, column)])
+ delete mTableModel[WIDGET_AT(row, column)];
+
+ mTableModel[WIDGET_AT(row, column)] = widget;
+
+ signalAfterUpdate();
+}
+
+gcn::Widget *StaticTableModel::getElementAt(int row, int column)
+{
+ return mTableModel[WIDGET_AT(row, column)];
+}
+
+void StaticTableModel::fixColumnWidth(int column, int width)
+{
+ if (width < 0
+ || column < 0 || column >= mColumns)
+ return;
+
+ mWidths[column] = -width; // Negate to tag as fixed
+}
+
+void StaticTableModel::fixRowHeight(int height)
+{
+ if (height < 0)
+ return;
+
+ mHeight = -height;
+}
+
+int StaticTableModel::getRowHeight()
+{
+ return abs(mHeight);
+}
+
+int StaticTableModel::getColumnWidth(int column)
+{
+ if (column < 0 || column >= mColumns)
+ return 0;
+
+ return abs(mWidths[column]);
+}
+
+int StaticTableModel::getRows()
+{
+ return mRows;
+}
+
+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
new file mode 100644
index 00000000..9ca36120
--- /dev/null
+++ b/src/gui/table_model.h
@@ -0,0 +1,144 @@
+/*
+ * The Mana World
+ * 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 TABLE_MODEL_H
+#define TABLE_MODEL_H
+
+#include <set>
+#include <vector>
+
+class TableModelListener
+{
+public:
+ /**
+ * Must be invoked by the TableModel whenever a global change is about to
+ * occur or has occurred (e.g., when a row or column is being removed or
+ * added).
+ *
+ * This method is triggered twice, once before and once after the update.
+ *
+ * \param completed whether we are signalling the end of the update
+ */
+ virtual void modelUpdated(bool completed) = 0;
+};
+
+/**
+ * A model for a regular table of widgets.
+ */
+class TableModel
+{
+public:
+ virtual ~TableModel() { }
+
+ /**
+ * Determines the number of rows (lines) in the table
+ */
+ virtual int getRows() = 0;
+
+ /**
+ * Determines the number of columns in each row
+ */
+ virtual int getColumns() = 0;
+
+ /**
+ * Determines the height for each row
+ */
+ virtual int getRowHeight() = 0;
+
+ /**
+ * Determines the width of each individual column
+ */
+ virtual int getColumnWidth(int index) = 0;
+
+ /**
+ * Retrieves the widget stored at the specified location within the table.
+ */
+ virtual gcn::Widget *getElementAt(int row, int column) = 0;
+
+ virtual void installListener(TableModelListener *listener);
+
+ virtual void removeListener(TableModelListener *listener);
+
+protected:
+ /**
+ * Tells all listeners that the table is about to see an update
+ */
+ virtual void signalBeforeUpdate();
+
+ /**
+ * Tells all listeners that the table has seen an update
+ */
+ virtual void signalAfterUpdate();
+
+private:
+ std::set<TableModelListener *> listeners;
+};
+
+
+class StaticTableModel : public TableModel
+{
+public:
+ StaticTableModel(int width, int height);
+ virtual ~StaticTableModel();
+
+ /**
+ * Inserts a widget into the table model.
+ * The model is resized to accomodate the widget's width and height,
+ * unless column width / row height have been fixed.
+ */
+ virtual void set(int row, int column, gcn::Widget *widget);
+
+ /**
+ * Fixes the column width for a given column; this overrides dynamic width
+ * inference.
+ *
+ * Semantics are undefined for width 0.
+ */
+ virtual void fixColumnWidth(int column, int width);
+
+ /**
+ * Fixes the row height; this overrides dynamic height inference.
+ *
+ * Semantics are undefined for width 0.
+ */
+ virtual void fixRowHeight(int height);
+
+ /**
+ * Resizes the table model
+ */
+ virtual void resize();
+
+ 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);
+
+protected:
+ int mRows, mColumns;
+ int mHeight;
+ std::vector<gcn::Widget *> mTableModel;
+ std::vector<int> mWidths;
+};
+
+#endif /* !defined(TABLE_MODEL_H) */
diff --git a/src/gui/textbox.cpp b/src/gui/textbox.cpp
index 619265ec..2a86d549 100644
--- a/src/gui/textbox.cpp
+++ b/src/gui/textbox.cpp
@@ -1,39 +1,39 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 2060e377..10a81fc0 100644
--- a/src/gui/textbox.h
+++ b/src/gui/textbox.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __TMW_TEXTBOX_H__
-#define __TMW_TEXTBOX_H__
+#ifndef TEXTBOX_H
+#define TEXTBOX_H
#include <guichan/widgets/textbox.hpp>
@@ -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 49c0c91d..99a95a2e 100644
--- a/src/gui/textfield.cpp
+++ b/src/gui/textfield.cpp
@@ -1,32 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <algorithm>
-
#include <guichan/font.hpp>
-#include "textfield.h"
-
#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 b808fad2..73824615 100644
--- a/src/gui/textfield.h
+++ b/src/gui/textfield.h
@@ -1,30 +1,37 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __TMW_TEXTFIELD_H__
-#define __TMW_TEXTFIELD_H__
+#ifndef TEXTFIELD_H
+#define TEXTFIELD_H
#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 0592c485..98214a79 100644
--- a/src/gui/trade.cpp
+++ b/src/gui/trade.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -24,8 +24,6 @@
#include <guichan/font.hpp>
#include <guichan/widgets/label.hpp>
-#include "trade.h"
-
#include "button.h"
#include "chat.h"
#include "inventorywindow.h"
@@ -33,42 +31,68 @@
#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 "../units.h"
+#ifdef TMWSERV_SUPPORT
#include "../net/gameserver/player.h"
-
-#include "../resources/iteminfo.h"
+#else
+#include "../net/messageout.h"
+#include "../net/ea/protocol.h"
+#endif
#include "../utils/gettext.h"
+#include "../utils/stringutils.h"
#include "../utils/strprintf.h"
+#ifdef TMWSERV_SUPPORT
TradeWindow::TradeWindow():
- Window("Trade: You"),
- mMyInventory(new Inventory),
- mPartnerInventory(new Inventory),
- mStatus(PREPARING)
+#else
+TradeWindow::TradeWindow(Network *network):
+#endif
+ Window(_("Trade: You")),
+#ifdef EATHENA_SUPPORT
+ mNetwork(network),
+#endif
+ mMyInventory(new Inventory(INVENTORY_SIZE)),
+ mPartnerInventory(new Inventory(INVENTORY_SIZE))
+#ifdef TMWSERV_SUPPORT
+ , mStatus(PREPARING)
+#endif
{
setWindowName("Trade");
setResizable(true);
setDefaultSize(115, 197, 332, 209);
Button *mAddButton = new Button(_("Add"), "add", this);
+#ifdef EATHENA_SUPPORT
+ mOkButton = new Button(_("Ok"), "ok", this);
+#endif
Button *mCancelButton = new Button(_("Cancel"), "cancel", this);
mTradeButton = new Button(_("Propose trade"), "trade", this);
mTradeButton->setWidth(8 + std::max(
mTradeButton->getFont()->getWidth(_("Propose trade")),
mTradeButton->getFont()->getWidth(_("Confirm trade"))));
- mMyItemContainer = new ItemContainer(mMyInventory, 4, 3);
+#ifdef TMWSERV_SUPPORT
+ mMyItemContainer = new ItemContainer(mMyInventory.get(), 4, 3, 0);
+#else
+ mMyItemContainer = new ItemContainer(mMyInventory.get(), 4, 3, 2);
+#endif
mMyItemContainer->addSelectionListener(this);
ScrollArea *mMyScroll = new ScrollArea(mMyItemContainer);
- mPartnerItemContainer = new ItemContainer(mPartnerInventory, 4, 3);
+#ifdef TMWSERV_SUPPORT
+ mPartnerItemContainer = new ItemContainer(mPartnerInventory.get(), 4, 3, 0);
+#else
+ mPartnerItemContainer = new ItemContainer(mPartnerInventory.get(), 4, 3, 2);
+#endif
mPartnerItemContainer->addSelectionListener(this);
ScrollArea *mPartnerScroll = new ScrollArea(mPartnerItemContainer);
@@ -78,10 +102,6 @@ TradeWindow::TradeWindow():
mMoneyField->setWidth(40);
Button *mMoneyChange = new Button(_("Change"), "money", this);
- mItemNameLabel = new gcn::Label(strprintf(_("Name: %s"), ""));
- mItemDescriptionLabel = new gcn::Label(
- strprintf(_("Description: %s"), ""));
-
place(1, 0, mMoneyLabel);
place(0, 1, mMyScroll).setPadding(3);
place(1, 1, mPartnerScroll).setPadding(3);
@@ -91,11 +111,12 @@ TradeWindow::TradeWindow():
place(1, 0, mMoneyField);
place(2, 0, mMoneyChange).setHAlign(LayoutCell::LEFT);
place = getPlacer(0, 2);
- place(0, 0, mItemNameLabel, 4);
- place(0, 1, mItemDescriptionLabel, 4);
- place(0, 2, mAddButton);
- place(2, 2, mTradeButton);
- place(3, 2, mCancelButton);
+ place(0, 0, mAddButton);
+#ifdef EATHENA_SUPPORT
+ place(1, 0, mOkButton);
+#endif
+ place(2, 0, mTradeButton);
+ place(3, 0, mCancelButton);
Layout &layout = getLayout();
layout.extend(0, 2, 2, 1);
layout.setRowHeight(1, Layout::AUTO_SET);
@@ -108,69 +129,151 @@ TradeWindow::TradeWindow():
TradeWindow::~TradeWindow()
{
- delete mMyInventory;
- delete mPartnerInventory;
}
void TradeWindow::setMoney(int amount)
{
- mMoneyLabel->setCaption(strprintf(_("You get %d GP."), amount));
+ mMoneyLabel->setCaption(strprintf(_("You get %s."),
+ Units::formatCurrency(amount).c_str()));
+ mMoneyLabel->adjustSize();
+#ifdef TMWSERV_SUPPORT
setStatus(PREPARING);
+#endif
}
+#ifdef TMWSERV_SUPPORT
void TradeWindow::addItem(int id, bool own, int quantity)
{
(own ? mMyInventory : mPartnerInventory)->addItem(id, quantity);
setStatus(PREPARING);
}
+#endif
+
+#ifdef EATHENA_SUPPORT
+void TradeWindow::addItem(int id, bool own, int quantity, bool equipment)
+{
+ if (own)
+ {
+ mMyInventory->addItem(id, quantity, equipment);
+ }
+ else
+ {
+ mPartnerInventory->addItem(id, quantity, equipment);
+ }
+}
+
+void TradeWindow::changeQuantity(int index, bool own, int quantity)
+{
+ if (own)
+ mMyInventory->getItem(index)->setQuantity(quantity);
+ else
+ mPartnerInventory->getItem(index)->setQuantity(quantity);
+}
+
+void TradeWindow::increaseQuantity(int index, bool own, int quantity)
+{
+ if (own)
+ mMyInventory->getItem(index)->increaseQuantity(quantity);
+ else
+ mPartnerInventory->getItem(index)->increaseQuantity(quantity);
+}
+#endif
void TradeWindow::reset()
{
mMyInventory->clear();
mPartnerInventory->clear();
- mMoneyLabel->setCaption(strprintf(_("You get %d GP."), 0));
+#ifdef EATHENA_SUPPORT
+ mTradeButton->setEnabled(false);
+ mOkButton->setEnabled(true);
+ mOkOther = false;
+ mOkMe = false;
+#endif
+ mMoneyLabel->setCaption(strprintf(_("You get %s."), ""));
mMoneyField->setEnabled(true);
mMoneyField->setText("");
+#ifdef TMWSERV_SUPPORT
setStatus(PREPARING);
+#endif
}
+#ifdef TMWSERV_SUPPORT
+
void TradeWindow::receivedOk()
{
setStatus(ACCEPTING);
}
+#else
+
+void TradeWindow::setTradeButton(bool enabled)
+{
+ mTradeButton->setEnabled(enabled);
+}
+
+void TradeWindow::receivedOk(bool own)
+{
+ if (own)
+ {
+ mOkMe = true;
+ if (mOkOther)
+ {
+ mTradeButton->setEnabled(true);
+ mOkButton->setEnabled(false);
+ }
+ else
+ {
+ mTradeButton->setEnabled(false);
+ mOkButton->setEnabled(false);
+ }
+ }
+ else
+ {
+ mOkOther = true;
+ if (mOkMe)
+ {
+ mTradeButton->setEnabled(true);
+ mOkButton->setEnabled(false);
+ }
+ else
+ {
+ mTradeButton->setEnabled(false);
+ mOkButton->setEnabled(true);
+ }
+ }
+}
+
+#endif
+
void TradeWindow::tradeItem(Item *item, int quantity)
{
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::tradeItem(item->getInvIndex(), quantity);
addItem(item->getId(), true, quantity);
item->increaseQuantity(-quantity);
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_TRADE_ITEM_ADD_REQUEST);
+ outMsg.writeInt16(item->getInvIndex());
+ outMsg.writeInt32(quantity);
+#endif
}
void TradeWindow::valueChanged(const gcn::SelectionEvent &event)
{
- Item *item;
+ const Item *item;
/* If an item is selected in one container, make sure no item is selected
* in the other container.
*/
if (event.getSource() == mMyItemContainer &&
- (item = mMyItemContainer->getItem()))
- {
+ (item = mMyItemContainer->getSelectedItem()))
mPartnerItemContainer->selectNone();
- }
- else if ((item = mPartnerItemContainer->getItem()))
- {
+ 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() : ""));
- mItemDescriptionLabel->setCaption(strprintf(_("Description: %s"),
- info ? info->getDescription().c_str() : ""));
}
+#ifdef TMWSERV_SUPPORT
void TradeWindow::setStatus(Status s)
{
if (s == mStatus) return;
@@ -180,44 +283,86 @@ void TradeWindow::setStatus(Status s)
(s == PREPARING ? _("Propose trade") : _("Confirm trade"));
mTradeButton->setEnabled(s != PROPOSING);
}
+#endif
void TradeWindow::action(const gcn::ActionEvent &event)
{
- Item *item = inventoryWindow->getItem();
+ Item *item = inventoryWindow->getSelectedItem();
if (event.getId() == "add")
{
if (!item)
return;
+ if (mMyInventory->getFreeSlot() < 1)
+ return;
+
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);
}
+#ifdef TMWSERV_SUPPORT
setStatus(PREPARING);
+#endif
}
else if (event.getId() == "cancel")
{
setVisible(false);
reset();
player_node->setTrading(false);
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::acceptTrade(false);
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_TRADE_CANCEL_REQUEST);
+#endif
+ }
+#ifdef EATHENA_SUPPORT
+ else if (event.getId() == "ok")
+ {
+ std::stringstream tempMoney(mMoneyField->getText());
+ int tempInt;
+ if (tempMoney >> tempInt)
+ {
+ mMoneyField->setText(toString(tempInt));
+
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_TRADE_ITEM_ADD_REQUEST);
+ outMsg.writeInt16(0);
+ outMsg.writeInt32(tempInt);
+ }
+ else
+ {
+ mMoneyField->setText("");
+ }
+ mMoneyField->setEnabled(false);
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_TRADE_ADD_COMPLETE);
}
+#endif
else if (event.getId() == "trade")
{
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::acceptTrade(true);
setStatus(PROPOSING);
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_TRADE_OK);
+#endif
}
+#ifdef TMWSERV_SUPPORT
else if (event.getId() == "money")
{
int v = atoi(mMoneyField->getText().c_str());
@@ -225,4 +370,5 @@ void TradeWindow::action(const gcn::ActionEvent &event)
mMoneyField->setText(strprintf("%d", v));
setStatus(PREPARING);
}
+#endif
}
diff --git a/src/gui/trade.h b/src/gui/trade.h
index c51e0fdd..bde0481c 100644
--- a/src/gui/trade.h
+++ b/src/gui/trade.h
@@ -1,26 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_TRADE_H
-#define _TMW_TRADE_H
+#ifndef TRADE_H
+#define TRADE_H
+
+#include <memory>
#include <guichan/actionlistener.hpp>
#include <guichan/selectionlistener.hpp>
@@ -32,6 +34,9 @@
class Inventory;
class Item;
class ItemContainer;
+#ifdef EATHENA_SUPPORT
+class Network;
+#endif
class ScrollArea;
/**
@@ -45,7 +50,11 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener
/**
* Constructor.
*/
+#ifdef TMWSERV_SUPPORT
TradeWindow();
+#else
+ TradeWindow(Network *network);
+#endif
/**
* Destructor.
@@ -67,16 +76,41 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener
*/
void reset();
+#ifdef EATHENA_SUPPORT
+ /**
+ * Add an item to the trade window.
+ */
+ void addItem(int id, bool own, int quantity, bool equipment);
+
+ /**
+ * Change quantity of an item.
+ */
+ void changeQuantity(int index, bool own, int quantity);
+
+ /**
+ * Increase quantity of an item.
+ */
+ void increaseQuantity(int index, bool own, int quantity);
+
+ /**
+ * Set trade Button disabled
+ */
+ void setTradeButton(bool enabled);
+#endif
+
/**
* Player received ok message from server
*/
+#ifdef TMWSERV_SUPPORT
void receivedOk();
+#else
+ void receivedOk(bool own);
+#endif
/**
* Send trade packet.
*/
- void
- tradeItem(Item *item, int quantity);
+ void tradeItem(Item *item, int quantity);
/**
* Updates the labels and makes sure only one item is selected in
@@ -90,6 +124,7 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener
void action(const gcn::ActionEvent &event);
private:
+#ifdef TMWSERV_SUPPORT
enum Status
{
PREPARING, /**< Players are adding items. */
@@ -101,20 +136,31 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener
* Sets the current status of the trade.
*/
void setStatus(Status);
+#endif
+
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+#endif
- Inventory *mMyInventory;
- Inventory *mPartnerInventory;
+ typedef const std::auto_ptr<Inventory> InventoryPtr;
+ InventoryPtr mMyInventory;
+ InventoryPtr mPartnerInventory;
ItemContainer *mMyItemContainer;
ItemContainer *mPartnerItemContainer;
- gcn::Label *mItemNameLabel;
- gcn::Label *mItemDescriptionLabel;
gcn::Label *mMoneyLabel;
gcn::Button *mTradeButton;
+#ifdef EATHENA_SUPPORT
+ gcn::Button *mOkButton;
+#endif
gcn::TextField *mMoneyField;
+#ifdef TMWSERV_SUPPORT
Status mStatus;
+#else
+ bool mOkOther, mOkMe;
+#endif
};
extern TradeWindow *tradeWindow;
diff --git a/src/gui/truetypefont.cpp b/src/gui/truetypefont.cpp
index 1132c3b5..7c72e2f5 100644
--- a/src/gui/truetypefont.cpp
+++ b/src/gui/truetypefont.cpp
@@ -1,30 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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"
@@ -45,8 +43,7 @@ class TextChunk
bool operator==(const TextChunk &chunk) const
{
- return (
- chunk.text == text && chunk.color == color);
+ return (chunk.text == text && chunk.color == color);
}
void generate(TTF_Font *font)
@@ -75,14 +72,11 @@ class TextChunk
gcn::Color color;
};
-
-// Word surfaces cache
-static std::list<TextChunk> cache;
typedef std::list<TextChunk>::iterator CacheIterator;
static int fontCounter;
-TrueTypeFont::TrueTypeFont(const std::string& filename, int size)
+TrueTypeFont::TrueTypeFont(const std::string &filename, int size)
{
if (fontCounter == 0 && TTF_Init() == -1)
{
@@ -93,7 +87,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()));
@@ -112,13 +106,11 @@ TrueTypeFont::~TrueTypeFont()
}
void TrueTypeFont::drawString(gcn::Graphics *graphics,
- const std::string &text,
- int x, int y)
+ const std::string &text,
+ int x, int y)
{
if (text.empty())
- {
return;
- }
Graphics *g = dynamic_cast<Graphics *>(graphics);
@@ -139,12 +131,12 @@ void TrueTypeFont::drawString(gcn::Graphics *graphics,
bool found = false;
- for (CacheIterator i = cache.begin(); i != cache.end(); i++)
+ for (CacheIterator i = mCache.begin(); i != mCache.end(); ++i)
{
if (chunk == (*i))
{
// Raise priority: move it to front
- cache.splice(cache.begin(), cache, i);
+ mCache.splice(mCache.begin(), mCache, i);
found = true;
break;
}
@@ -153,19 +145,19 @@ void TrueTypeFont::drawString(gcn::Graphics *graphics,
// Surface not found
if (!found)
{
- if (cache.size() >= CACHE_SIZE)
+ if (mCache.size() >= CACHE_SIZE)
{
- cache.pop_back();
+ mCache.pop_back();
}
- cache.push_front(chunk);
- cache.front().generate(mFont);
+ mCache.push_front(chunk);
+ mCache.front().generate(mFont);
}
- cache.front().img->setAlpha(alpha);
- g->drawImage(cache.front().img, x, y);
+ mCache.front().img->setAlpha(alpha);
+ g->drawImage(mCache.front().img, x, y);
}
-int TrueTypeFont::getWidth(const std::string& text) const
+int TrueTypeFont::getWidth(const std::string &text) const
{
int w, h;
TTF_SizeUTF8(mFont, text.c_str(), &w, &h);
diff --git a/src/gui/truetypefont.h b/src/gui/truetypefont.h
index 3b39329e..71b45fd1 100644
--- a/src/gui/truetypefont.h
+++ b/src/gui/truetypefont.h
@@ -1,37 +1,39 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_TRUETYPEFONT_H
-#define _TMW_TRUETYPEFONT_H
+#ifndef TRUETYPEFONT_H
+#define TRUETYPEFONT_H
+#include <list>
#include <string>
#include <guichan/font.hpp>
-#include <guichan/graphics.hpp>
-#ifdef __APPLE__
-#include <SDL_ttf/SDL_ttf.h>
-#else
+#ifndef __APPLE__
#include <SDL/SDL_ttf.h>
+#else
+#include <SDL_ttf.h>
#endif
+class TextChunk;
+
/**
* A wrapper around SDL_ttf for allowing the use of TrueType fonts.
*
@@ -46,7 +48,7 @@ class TrueTypeFont : public gcn::Font
* @param filename Font filename.
* @param size Font size.
*/
- TrueTypeFont(const std::string& filename, int size);
+ TrueTypeFont(const std::string &filename, int size);
/**
* Destructor.
@@ -60,10 +62,15 @@ class TrueTypeFont : public gcn::Font
/**
* @see Font::drawString
*/
- void drawString(gcn::Graphics* graphics, const std::string& text, int x, int y);
+ void drawString(gcn::Graphics *graphics,
+ const std::string &text,
+ int x, int y);
private:
TTF_Font *mFont;
+
+ // Word surfaces cache
+ std::list<TextChunk> mCache;
};
#endif
diff --git a/src/gui/unregisterdialog.h b/src/gui/unregisterdialog.h
index 4056d251..1e3cc88f 100644
--- a/src/gui/unregisterdialog.h
+++ b/src/gui/unregisterdialog.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_UNREGISTERDIALOG_H
-#define _TMW_UNREGISTERDIALOG_H
+#ifndef UNREGISTERDIALOG_H
+#define UNREGISTERDIALOG_H
#include <iosfwd>
#include <guichan/actionlistener.hpp>
diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp
index 997a9b82..ca41dbda 100644
--- a/src/gui/updatewindow.cpp
+++ b/src/gui/updatewindow.cpp
@@ -1,26 +1,24 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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,22 +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 "../utils/tostring.h"
-
#include "../resources/resourcemanager.h"
+#include "../utils/gettext.h"
+#include "../utils/stringutils.h"
+
/**
* Calculates the Alder-32 checksum for the given file.
*/
@@ -67,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());
@@ -89,7 +90,7 @@ loadTextFile(const std::string &fileName)
UpdaterWindow::UpdaterWindow(const std::string &updateHost,
const std::string &updatesDir):
- Window("Updating..."),
+ Window(_("Updating...")),
mThread(NULL),
mDownloadStatus(UPDATE_NEWS),
mUpdateHost(updateHost),
@@ -106,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();
+ mBrowserBox = new BrowserBox;
mScrollArea = new ScrollArea(mBrowserBox);
- mLabel = new gcn::Label("Connecting...");
- mProgressBar = new ProgressBar(0.0, w - 10, 20, 37, 70, 200);
- mCancelButton = new Button("Cancel", "cancel", this);
- mPlayButton = new Button("Play", "play", this);
+ mLabel = new gcn::Label(_("Connecting..."));
+ 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);
@@ -209,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");
@@ -228,8 +224,9 @@ int UpdaterWindow::updateProgress(void *ptr,
float progress = dn / dt;
UpdaterWindow *uw = reinterpret_cast<UpdaterWindow *>(ptr);
- if (progress < 0) progress = 0.0f;
- if (progress > 1) progress = 1.0f;
+ if (progress != progress) progress = 0.0f; // check for NaN
+ if (progress < 0.0f) progress = 0.0f; // no idea how this could ever happen, but why not check for it anyway.
+ if (progress > 1.0f) progress = 1.0f;
uw->setLabel(
uw->mCurrentFile + " (" + toString((int) (progress * 100)) + "%)");
@@ -244,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;
@@ -328,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;
}
@@ -412,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;
@@ -452,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());
@@ -521,7 +517,7 @@ void UpdaterWindow::logic()
break;
case UPDATE_COMPLETE:
enable();
- setLabel("Completed");
+ setLabel(_("Completed"));
break;
case UPDATE_IDLE:
break;
diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h
index a7dfe2cb..ace398b4 100644
--- a/src/gui/updatewindow.h
+++ b/src/gui/updatewindow.h
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -23,12 +23,13 @@
#define _UPDATERWINDOW_H
#include <guichan/actionlistener.hpp>
+
#include <string>
#include <vector>
#include "window.h"
-#include "../guichanfwd.h"
+#include "../utils/mutex.h"
#include "../utils/mutex.h"
diff --git a/src/gui/vbox.cpp b/src/gui/vbox.cpp
deleted file mode 100644
index 2ec1112d..00000000
--- a/src/gui/vbox.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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 "vbox.h"
-
-void VBox::draw(gcn::Graphics *graphics)
-{
- if (mWidgets.empty())
- {
- return;
- }
-
- int childWidth = getWidth();
- int childHeight = getHeight() / mWidgets.size();
- int i = 0;
-
- for (WidgetIterator w = mWidgets.begin(); w != mWidgets.end(); w++)
- {
- (*w)->setPosition(0, childHeight * i - padding);
- (*w)->setSize(childWidth, childHeight);
- i++;
- }
-
- gcn::Container::draw(graphics);
-}
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index a746fb03..cbd1f3f7 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -1,62 +1,61 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "viewport.h"
-
-#include <guichan/sdl/sdlinput.hpp>
-
-#include "gui.h"
+#include "ministatus.h"
#include "popupmenu.h"
+#include "viewport.h"
-#include "../simpleanimation.h"
#include "../beingmanager.h"
#include "../configuration.h"
#include "../flooritemmanager.h"
+#include "../game.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>
+#include "../utils/stringutils.h"
extern volatile int tick_time;
-extern int get_elapsed_time(int start_time);
Viewport::Viewport():
mMap(0),
- mViewX(0.0f),
- mViewY(0.0f),
+ mPixelViewX(0.0f),
+ mPixelViewY(0.0f),
+ mTileViewX(0),
+ mTileViewY(0),
mShowDebugPath(false),
mVisibleNames(false),
mPlayerFollowMouse(false),
+#ifdef TMWSERV_SUPPORT
mLocalWalkTime(-1)
+#else
+ mWalkTime(0)
+#endif
{
setOpaque(false);
addMouseListener(this);
@@ -71,52 +70,7 @@ Viewport::Viewport():
config.addListener("ScrollRadius", this);
config.addListener("visiblenames", 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(const std::string &filename,
- int width, int height,
- bool outRange, Being::TargetCursorSize size)
-{
- assert(size >= Being::TC_SMALL);
- assert(size < Being::NUM_TC);
-
- 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;
- }
+ mPopupMenu = new PopupMenu;
}
Viewport::~Viewport()
@@ -124,14 +78,6 @@ Viewport::~Viewport()
delete mPopupMenu;
config.removeListener("visiblenames", this);
-
- 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)
@@ -139,6 +85,8 @@ void Viewport::setMap(Map *map)
mMap = map;
}
+extern MiniStatusWindow *miniStatusWindow;
+
void Viewport::draw(gcn::Graphics *gcnGraphics)
{
static int lastTick = tick_time;
@@ -148,6 +96,10 @@ void 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)
{
@@ -155,12 +107,22 @@ void Viewport::draw(gcn::Graphics *gcnGraphics)
}
// Calculate viewpoint
+#ifdef TMWSERV_SUPPORT
int midTileX = (graphics->getWidth() + mScrollCenterOffsetX) / 2;
int midTileY = (graphics->getHeight() + mScrollCenterOffsetX) / 2;
const Vector &playerPos = player_node->getPosition();
const int player_x = (int) playerPos.x - midTileX;
const int player_y = (int) playerPos.y - midTileY;
+#else
+ int midTileX = (graphics->getWidth() + mScrollCenterOffsetX) / 32 / 2;
+ int midTileY = (graphics->getHeight() + mScrollCenterOffsetY) / 32 / 2;
+
+ int player_x = (player_node->mX - midTileX) * 32 +
+ player_node->getXOffset();
+ int player_y = (player_node->mY - midTileY) * 32 +
+ player_node->getYOffset();
+#endif
if (mScrollLaziness < 1)
mScrollLaziness = 1; // Avoids division by zero
@@ -168,34 +130,34 @@ void Viewport::draw(gcn::Graphics *gcnGraphics)
// Apply lazy scrolling
while (lastTick < tick_time)
{
- if (player_x > mViewX + mScrollRadius)
+ if (player_x > mPixelViewX + mScrollRadius)
{
- mViewX += (player_x - mViewX - mScrollRadius) / mScrollLaziness;
+ mPixelViewX += (player_x - mPixelViewX - mScrollRadius) / mScrollLaziness;
}
- if (player_x < mViewX - mScrollRadius)
+ if (player_x < mPixelViewX - mScrollRadius)
{
- mViewX += (player_x - mViewX + mScrollRadius) / mScrollLaziness;
+ mPixelViewX += (player_x - mPixelViewX + mScrollRadius) / mScrollLaziness;
}
- if (player_y > mViewY + mScrollRadius)
+ if (player_y > mPixelViewY + mScrollRadius)
{
- mViewY += (player_y - mViewY - mScrollRadius) / mScrollLaziness;
+ mPixelViewY += (player_y - mPixelViewY - mScrollRadius) / mScrollLaziness;
}
- if (player_y < mViewY - mScrollRadius)
+ if (player_y < mPixelViewY - mScrollRadius)
{
- mViewY += (player_y - mViewY + mScrollRadius) / mScrollLaziness;
+ mPixelViewY += (player_y - mPixelViewY + mScrollRadius) / mScrollLaziness;
}
lastTick++;
}
// Auto center when player is off screen
- if ( player_x - mViewX > graphics->getWidth() / 2
- || mViewX - player_x > graphics->getWidth() / 2
- || mViewY - player_y > graphics->getHeight() / 2
- || player_y - mViewY > graphics->getHeight() / 2
+ if ( player_x - mPixelViewX > graphics->getWidth() / 2
+ || mPixelViewX - player_x > graphics->getWidth() / 2
+ || mPixelViewY - player_y > graphics->getHeight() / 2
+ || player_y - mPixelViewY > graphics->getHeight() / 2
)
{
- mViewX = player_x;
- mViewY = player_y;
+ mPixelViewX = player_x;
+ mPixelViewY = player_y;
};
// Don't move camera so that the end of the map is on screen
@@ -205,49 +167,62 @@ void Viewport::draw(gcn::Graphics *gcnGraphics)
mMap->getHeight() * mMap->getTileHeight() - graphics->getHeight();
if (mMap)
{
- if (mViewX < 0) {
- mViewX = 0;
+ if (mPixelViewX < 0) {
+ mPixelViewX = 0;
}
- if (mViewY < 0) {
- mViewY = 0;
+ if (mPixelViewY < 0) {
+ mPixelViewY = 0;
}
- if (mViewX > viewXmax) {
- mViewX = viewXmax;
+ if (mPixelViewX > viewXmax) {
+ mPixelViewX = viewXmax;
}
- if (mViewY > viewYmax) {
- mViewY = viewYmax;
+ if (mPixelViewY > viewYmax) {
+ mPixelViewY = viewYmax;
}
}
+ mTileViewX = (int) (mPixelViewX + 16) / 32;
+ mTileViewY = (int) (mPixelViewY + 16) / 32;
+
// Draw tiles and sprites
if (mMap)
{
- mMap->draw(graphics, (int) mViewX, (int) mViewY);
- drawTargetCursor(graphics); // TODO: Draw the cursor with the sprite
- drawTargetName(graphics);
+ mMap->draw(graphics, (int) mPixelViewX, (int) mPixelViewY);
+
if (mShowDebugPath) {
- mMap->drawCollision(graphics, (int) mViewX, (int) mViewY);
+ mMap->drawCollision(graphics,
+ (int) mPixelViewX,
+ (int) mPixelViewY);
#if 0
drawDebugPath(graphics);
#endif
}
}
+ if (player_node->mUpdateName)
+ {
+ player_node->mUpdateName = false;
+ player_node->setName(player_node->getName());
+ }
+
+
+ // Draw text
+ if (textManager)
+ {
+ textManager->draw(graphics, (int) mPixelViewX, (int) mPixelViewY);
+ }
+
// Draw player names, speech, and emotion sprite as needed
Beings &beings = beingManager->getAll();
for (BeingIterator i = beings.begin(); i != beings.end(); i++)
{
- (*i)->drawSpeech(graphics, -(int) mViewX, -(int) mViewY);
- if (mVisibleNames)
- (*i)->drawName(graphics, -(int) mViewX, -(int) mViewY);
- else if ((*i) == mSelectedBeing)
- (*i)->drawName(graphics, -(int) mViewX, -(int) mViewY);
- (*i)->drawEmotion(graphics, -(int) mViewX, -(int) mViewY);
-
- if (mShowDebugPath && !(*i)->getPath().empty())
- drawPath(graphics, (*i)->getPath());
+ (*i)->drawSpeech(-(int) mPixelViewX, -(int) mPixelViewY);
+ (*i)->drawEmotion(graphics, -(int) mPixelViewX, -(int) mPixelViewY);
}
+ if (miniStatusWindow)
+ miniStatusWindow->drawIcons(graphics);
+
// Draw contained widgets
WindowContainer::draw(gcnGraphics);
}
@@ -263,67 +238,19 @@ void Viewport::logic()
Uint8 button = SDL_GetMouseState(&mouseX, &mouseY);
if (mPlayerFollowMouse && button & SDL_BUTTON(1) &&
+#ifdef TMWSERV_SUPPORT
get_elapsed_time(mLocalWalkTime) >= walkingMouseDelay)
{
mLocalWalkTime = tick_time;
- player_node->setDestination(mouseX + (int) mViewX,
- mouseY + (int) mViewY);
- }
-
- for (int i = Being::TC_SMALL; i < Being::NUM_TC; i++)
+ player_node->setDestination(mouseX + (int) mPixelViewX,
+ mouseY + (int) mPixelViewY);
+#else
+ mWalkTime != player_node->mWalkTime)
{
- 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
- const Vector &dist =
- target->getPosition() - player_node->getPosition();
- const int rangeX = abs((int) dist.x);
- const int rangeY = abs((int) dist.y);
- const 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() -
- targetCursor->getWidth() / 2 - (int) mViewX;
- int posY = target->getPixelY() - 16 -
- targetCursor->getHeight() / 2 - (int) mViewY;
-
- graphics->drawImage(targetCursor, posX, posY);
- }
-}
-
-void Viewport::drawTargetName(Graphics *graphics)
-{
- // Draw target marker if needed
- Being *target = player_node->getTarget();
- if (target && target->getType() == Being::MONSTER)
- {
- graphics->setFont(speechFont);
- graphics->setColor(gcn::Color(255, 32, 32));
-
- const MonsterInfo &mi = static_cast<Monster*>(target)->getInfo();
- int posX = target->getPixelX() - (int) mViewX;
- int posY = target->getPixelY() + 16 - target->getHeight() - (int) mViewY;
-
- graphics->drawText(mi.getName(), posX, posY, gcn::Graphics::CENTER);
+ player_node->setDestination(mouseX / 32 + mTileViewX,
+ mouseY / 32 + mTileViewY);
+ mWalkTime = player_node->mWalkTime;
+#endif
}
}
@@ -333,8 +260,8 @@ void Viewport::drawDebugPath(Graphics *graphics)
int mouseX, mouseY;
SDL_GetMouseState(&mouseX, &mouseY);
- const int mouseTileX = (mouseX + (int) mViewX) / 32;
- const int mouseTileY = (mouseY + (int) mViewY) / 32;
+ const int mouseTileX = (mouseX + (int) mPixelViewX) / 32;
+ const int mouseTileY = (mouseY + (int) mPixelViewY) / 32;
const Vector &playerPos = player_node->getPosition();
Path debugPath = mMap->findPath(
@@ -350,8 +277,8 @@ void Viewport::drawPath(Graphics *graphics, const Path &path)
graphics->setColor(gcn::Color(255, 0, 0));
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
{
- int squareX = i->x * 32 - (int) mViewX + 12;
- int squareY = i->y * 32 - (int) mViewY + 12;
+ 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(
@@ -366,10 +293,14 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
if (!mMap || !player_node || player_node->mAction == Being::DEAD)
return;
+ // Check if we are busy
+ if (current_npc)
+ return;
+
mPlayerFollowMouse = false;
- const int pixelx = event.getX() + (int) mViewX;
- const int pixely = event.getY() + (int) mViewY;
+ const int pixelx = event.getX() + (int) mPixelViewX;
+ const int pixely = event.getY() + (int) mPixelViewY;
const int tilex = pixelx / mMap->getTileWidth();
const int tiley = pixely / mMap->getTileHeight();
@@ -380,12 +311,13 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
FloorItem *floorItem;
if ((being = beingManager->findBeingByPixel(pixelx, pixely)) &&
- being != player_node)
+ 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;
@@ -403,24 +335,63 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
if (event.getButton() == gcn::MouseEvent::LEFT)
{
FloorItem *item;
+#ifdef EATHENA_SUPPORT
+ Being *being;
+ // Interact with some being
+// if ((being = beingManager->findBeing(tilex, tiley)))
+ if ((being = beingManager->findBeingByPixel(pixelx, pixely)))
+ {
+ switch (being->getType())
+ {
+ case Being::NPC:
+ dynamic_cast<NPC*>(being)->talk();
+ break;
+
+ case Being::MONSTER:
+ case Being::PLAYER:
+ if (being->mAction == Being::DEAD)
+ break;
+
+ if (player_node->withinAttackRange(being) || keyboard.isKeyActive(keyboard.KEY_ATTACK))
+ {
+ player_node->setGotoTarget(being);
+ player_node->attack(being, !keyboard.isKeyActive(keyboard.KEY_TARGET));
+ }
+ else
+ {
+ player_node->setDestination(tilex, tiley);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
// Pick up some item
+ else
+#endif
if ((item = floorItemManager->findByCoordinates(tilex, tiley)))
{
- player_node->pickUp(item);
+ player_node->pickUp(item);
}
// Just walk around
else
{
+#ifdef TMWSERV_SUPPORT
// FIXME: REALLY UGLY!
Uint8 *keys = SDL_GetKeyState(NULL);
if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]) &&
get_elapsed_time(mLocalWalkTime) >= walkingMouseDelay)
{
mLocalWalkTime = tick_time;
- player_node->setDestination(event.getX() + (int) mViewX,
- event.getY() + (int) mViewY);
+ player_node->setDestination(event.getX() + (int) mPixelViewX,
+ event.getY() + (int) mPixelViewY);
}
+#else
+ player_node->stopAttack();
+ player_node->setDestination(tilex, tiley);
+#endif
mPlayerFollowMouse = true;
}
}
@@ -443,13 +414,22 @@ void Viewport::mouseDragged(gcn::MouseEvent &event)
if (!mMap || !player_node)
return;
+#ifdef TMWSERV_SUPPORT
if (mPlayerFollowMouse
&& get_elapsed_time(mLocalWalkTime) >= walkingMouseDelay)
{
mLocalWalkTime = tick_time;
- player_node->setDestination(event.getX() + (int) mViewX,
- event.getY() + (int) mViewY);
+ player_node->setDestination(event.getX() + (int) mPixelViewX,
+ event.getY() + (int) mPixelViewY);
}
+#else
+ if (mPlayerFollowMouse && mWalkTime == player_node->mWalkTime)
+ {
+ int destX = event.getX() / 32 + mTileViewX;
+ int destY = event.getY() / 32 + mTileViewY;
+ player_node->setDestination(destX, destY);
+ }
+#endif
}
void Viewport::mouseReleased(gcn::MouseEvent &event)
@@ -478,9 +458,8 @@ void Viewport::mouseMoved(gcn::MouseEvent &event)
if (!mMap || !player_node)
return;
- const int tilex = (event.getX() + (int) mViewX) / 32;
- const int tiley = (event.getY() + (int) mViewY) / 32;
+ const int tilex = (event.getX() + (int) mPixelViewX) / 32;
+ const int tiley = (event.getY() + (int) mPixelViewY) / 32;
mSelectedBeing = beingManager->findBeing(tilex, tiley);
}
-
diff --git a/src/gui/viewport.h b/src/gui/viewport.h
index dd17fa24..a097a4ac 100644
--- a/src/gui/viewport.h
+++ b/src/gui/viewport.h
@@ -1,41 +1,41 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_VIEWPORT_H_
-#define _TMW_VIEWPORT_H_
+#ifndef VIEWPORT_H
+#define VIEWPORT_H
#include <guichan/mouselistener.hpp>
#include "windowcontainer.h"
#include "../configlistener.h"
-#include "../being.h"
+#include "../position.h"
-class Map;
+class Being;
class FloorItem;
+class Graphics;
class ImageSet;
class Item;
+class Map;
class PopupMenu;
-class Graphics;
-class SimpleAnimation;
/** Delay between two mouse calls when dragging mouse and move the player */
const int walkingMouseDelay = 500;
@@ -65,101 +65,71 @@ 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);
/**
* Handles mouse move on map.
*/
- void
- mouseMoved(gcn::MouseEvent &event);
+ void mouseMoved(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 pixels.
*/
- int
- getCameraX() const { return (int) mViewX; }
+ int getCameraX() const { return (int) mPixelViewX; }
/**
* Returns camera y offset in pixels.
*/
- int
- getCameraY() const { return (int) mViewY; }
+ int getCameraY() const { return (int) mPixelViewY; }
/**
* Changes viewpoint by relative pixel coordinates.
*/
- void
- scrollBy(float x, float y) { mViewX += x; mViewY += y; }
+ void scrollBy(float x, float y) { mPixelViewX += x; mPixelViewY += y; }
private:
/**
- * Helper function for loading target cursors.
- */
- void loadTargetCursor(const 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);
-
- /**
* Finds a path from the player to the mouse, and draws it. This is for
* debug purposes.
*/
@@ -170,35 +140,31 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
*/
void drawPath(Graphics *graphics, const Path &path);
-
Map *mMap; /**< The current map. */
int mScrollRadius;
int mScrollLaziness;
int mScrollCenterOffsetX;
int mScrollCenterOffsetY;
- float mViewX; /**< Current viewpoint in pixels. */
- float mViewY; /**< Current viewpoint in pixels. */
+ float mPixelViewX; /**< Current viewpoint in pixels. */
+ float mPixelViewY; /**< Current viewpoint in pixels. */
+ int mTileViewX; /**< Current viewpoint in tiles. */
+ int mTileViewY; /**< Current viewpoint in tiles. */
bool mShowDebugPath; /**< Show a path from player to pointer. */
bool mVisibleNames; /**< Show target names. */
- /** 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;
+#ifdef TMWSERV_SUPPORT
int mLocalWalkTime; /**< Timestamp before the next walk can be sent. */
+#else
+ int mWalkTime;
+#endif
PopupMenu *mPopupMenu; /**< Popup menu. */
Being *mSelectedBeing; /**< Current selected being. */
+
};
+extern Viewport *viewport; /**< The viewport */
+
#endif
diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp
index d4c2bc4b..92837603 100644
--- a/src/gui/widgets/dropdown.cpp
+++ b/src/gui/widgets/dropdown.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -23,6 +23,11 @@
#include "dropdown.h"
+#include "../color.h"
+#include "../listbox.h"
+#include "../scrollarea.h"
+
+#include "../../configuration.h"
#include "../../graphics.h"
#include "../../resources/image.h"
@@ -33,12 +38,12 @@
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):
- gcn::DropDown::DropDown(listModel,
- scrollArea, listBox)
+DropDown::DropDown(gcn::ListModel *listModel, gcn::ScrollArea *scrollArea,
+ gcn::ListBox *listBox, bool opacity):
+ gcn::DropDown::DropDown(listModel, scrollArea, listBox),
+ mOpaque(opacity)
{
setFrameSize(2);
@@ -58,6 +63,11 @@ DropDown::DropDown(gcn::ListModel *listModel,
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};
@@ -70,6 +80,7 @@ DropDown::DropDown(gcn::ListModel *listModel,
gridx[x], gridy[y],
gridx[x + 1] - gridx[x] + 1,
gridy[y + 1] - gridy[y] + 1);
+ skin.grid[a]->setAlpha(mAlpha);
a++;
}
}
@@ -108,19 +119,44 @@ void DropDown::draw(gcn::Graphics* graphics)
h = getHeight();
}
- int alpha = getBaseColor().a;
+ 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 = (int)(mAlpha * 255.0f);
gcn::Color faceColor = getBaseColor();
faceColor.a = alpha;
- gcn::Color highlightColor = faceColor + 0x303030;
+ 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->setColor(getBackgroundColor());
- graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), h));
-
- graphics->setColor(getForegroundColor());
graphics->setFont(getFont());
if (mListBox->getListModel() && mListBox->getSelected() >= 0)
@@ -140,7 +176,7 @@ void DropDown::draw(gcn::Graphics* graphics)
{
drawChildren(graphics);
- // Draw two lines separating the ListBox with se selected
+ // Draw two lines separating the ListBox with selected
// element view.
graphics->setColor(highlightColor);
graphics->drawLine(0, h, getWidth(), h);
@@ -163,5 +199,5 @@ void DropDown::drawButton(gcn::Graphics *graphics)
int height = mDroppedDown ? mFoldedUpHeight : getHeight();
static_cast<Graphics*>(graphics)->
- drawImage(buttons[mDroppedDown][mPushed], getWidth() - height, 1);
+ drawImage(buttons[mDroppedDown][mPushed], getWidth() - height + 2, 1);
}
diff --git a/src/gui/widgets/dropdown.h b/src/gui/widgets/dropdown.h
index 58a18a15..1e6dc821 100644
--- a/src/gui/widgets/dropdown.h
+++ b/src/gui/widgets/dropdown.h
@@ -1,32 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; 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 <iosfwd>
-
#include <guichan/widgets/dropdown.hpp>
-#include "../scrollarea.h"
-#include "../listbox.h"
class Image;
class ImageRect;
@@ -53,7 +49,8 @@ class DropDown : public gcn::DropDown
*/
DropDown(gcn::ListModel *listModel = NULL,
gcn::ScrollArea *scrollArea = NULL,
- gcn::ListBox *listBox = NULL);
+ gcn::ListBox *listBox = NULL,
+ bool opacity = true);
/**
* Destructor.
@@ -64,6 +61,22 @@ class DropDown : public gcn::DropDown
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:
/**
@@ -77,6 +90,9 @@ class DropDown : public gcn::DropDown
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/layout.cpp b/src/gui/widgets/layout.cpp
index bcc54cf7..4ffdda36 100644
--- a/src/gui/widgets/layout.cpp
+++ b/src/gui/widgets/layout.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/gui/widgets/layout.h b/src/gui/widgets/layout.h
index d631c154..20a4222d 100644
--- a/src/gui/widgets/layout.h
+++ b/src/gui/widgets/layout.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_WIDGET_LAYOUT_H__
-#define _TMW_WIDGET_LAYOUT_H__
+#ifndef WIDGET_LAYOUT_H
+#define WIDGET_LAYOUT_H
#include <vector>
@@ -317,4 +317,4 @@ class Layout: public LayoutCell
bool mComputed;
};
-#endif
+#endif // WIDGET_LAYOUT_H
diff --git a/src/gui/widgets/layouthelper.cpp b/src/gui/widgets/layouthelper.cpp
new file mode 100644
index 00000000..410de98a
--- /dev/null
+++ b/src/gui/widgets/layouthelper.cpp
@@ -0,0 +1,63 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009 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 "layouthelper.h"
+
+LayoutHelper::LayoutHelper(gcn::Container *container):
+ mContainer(container)
+{
+ mContainer->addWidgetListener(this);
+}
+
+LayoutHelper::~LayoutHelper()
+{
+ mContainer->removeWidgetListener(this);
+}
+
+Layout &LayoutHelper::getLayout()
+{
+ return mLayout;
+}
+
+LayoutCell &LayoutHelper::place(int x, int y, gcn::Widget *wg, int w, int h)
+{
+ mContainer->add(wg);
+ return mLayout.place(wg, x, y, w, h);
+}
+
+ContainerPlacer LayoutHelper::getPlacer(int x, int y)
+{
+ return ContainerPlacer(mContainer, &mLayout.at(x, y));
+}
+
+void LayoutHelper::reflowLayout(int w, int h)
+{
+ mLayout.reflow(w, h);
+ mContainer->setSize(w, h);
+}
+
+void LayoutHelper::widgetResized(const gcn::Event &event)
+{
+ const gcn::Rectangle area = mContainer->getChildrenArea();
+ int w = area.width;
+ int h = area.height;
+ mLayout.reflow(w, h);
+}
diff --git a/src/gui/widgets/layouthelper.h b/src/gui/widgets/layouthelper.h
new file mode 100644
index 00000000..afa92a18
--- /dev/null
+++ b/src/gui/widgets/layouthelper.h
@@ -0,0 +1,84 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009 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 LAYOUTHELPER_H
+#define LAYOUTHELPER_H
+
+#include "layout.h"
+
+#include <guichan/widgetlistener.hpp>
+
+/**
+ * A helper class for adding a layout to a Guichan container widget. The layout
+ * will register itself as a widget listener and relayout the widgets in the
+ * container dynamically on resize.
+ */
+class LayoutHelper : public gcn::WidgetListener
+{
+ public:
+ /**
+ * Constructor.
+ */
+ LayoutHelper(gcn::Container *container);
+
+ /**
+ * Destructor.
+ */
+ ~LayoutHelper();
+
+ /**
+ * Gets the layout handler.
+ */
+ Layout &getLayout();
+
+ /**
+ * Computes the position of the widgets according to the current
+ * layout. Resizes the managed container so that the layout fits.
+ *
+ * @note This function is meant to be called with fixed-size
+ * containers.
+ *
+ * @param w if non-zero, force the container to this width.
+ * @param h if non-zero, force the container to this height.
+ */
+ void reflowLayout(int w = 0, int h = 0);
+
+ /**
+ * Adds a widget to the container and sets it at given cell.
+ */
+ LayoutCell &place(int x, int y, gcn::Widget *, int w = 1, int h = 1);
+
+ /**
+ * Returns a proxy for adding widgets in an inner table of the layout.
+ */
+ ContainerPlacer getPlacer(int x, int y);
+
+ /**
+ * Called whenever the managed container changes size.
+ */
+ void widgetResized(const gcn::Event &event);
+
+ private:
+ Layout mLayout; /**< Layout handler */
+ gcn::Container *mContainer; /**< Managed container */
+};
+
+#endif // LAYOUTHELPER_H
diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp
index c3b537db..fa264e37 100644
--- a/src/gui/widgets/resizegrip.cpp
+++ b/src/gui/widgets/resizegrip.cpp
@@ -1,28 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 f57eda94..620c133f 100644
--- a/src/gui/widgets/resizegrip.h
+++ b/src/gui/widgets/resizegrip.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_RESIZEGRIP_H
-#define _TMW_RESIZEGRIP_H
+#ifndef RESIZEGRIP_H
+#define RESIZEGRIP_H
#include <guichan/widget.hpp>
@@ -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 b09bc5b3..21402c89 100644
--- a/src/gui/widgets/tab.cpp
+++ b/src/gui/widgets/tab.cpp
@@ -1,31 +1,30 @@
/*
* The Mana World
- * Copyright 2008 The Mana World 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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"
@@ -34,6 +33,7 @@
#include "../../utils/dtor.h"
int Tab::mInstances = 0;
+float Tab::mAlpha = config.getValue("guialpha", 0.8);
enum{
TAB_STANDARD, // 0
@@ -51,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];
@@ -100,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++;
}
}
@@ -116,7 +117,7 @@ void Tab::draw(gcn::Graphics *graphics)
// check which type of tab to draw
if (mTabbedArea)
{
- if(mTabbedArea->isTabSelected(this))
+ if (mTabbedArea->isTabSelected(this))
{
mode = TAB_SELECTED;
// if tab is selected, it doesnt need to highlight activity
@@ -130,6 +131,15 @@ void Tab::draw(gcn::Graphics *graphics)
}
}
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ 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
static_cast<Graphics*>(graphics)->
diff --git a/src/gui/widgets/tab.h b/src/gui/widgets/tab.h
index 65cc3fa0..3af4e2bf 100644
--- a/src/gui/widgets/tab.h
+++ b/src/gui/widgets/tab.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2008 The Mana World 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_TAB_H
-#define _TMW_TAB_H
+#ifndef TAB_H
+#define TAB_H
#include <guichan/widgets/tab.hpp>
@@ -58,6 +58,7 @@ class Tab : public gcn::Tab
static ImageRect tabImg[4]; /**< Tab state graphics */
static int mInstances; /**< Number of tab instances */
+ static float mAlpha;
bool mHighlighted;
};
diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp
index 205fdc99..ce11fe69 100644
--- a/src/gui/widgets/tabbedarea.cpp
+++ b/src/gui/widgets/tabbedarea.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2008 The Mana World 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -75,7 +75,7 @@ gcn::Widget* TabbedArea::getWidget(const std::string &name)
void TabbedArea::addTab(const std::string &caption, gcn::Widget *widget)
{
- Tab* tab = new Tab();
+ Tab* tab = new Tab;
tab->setCaption(caption);
mTabsToDelete.push_back(tab);
@@ -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/widgets/tabbedarea.h b/src/gui/widgets/tabbedarea.h
index 2199264b..01d70380 100644
--- a/src/gui/widgets/tabbedarea.h
+++ b/src/gui/widgets/tabbedarea.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2008 The Mana World 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_TABBEDAREA_H
-#define _TMW_TABBEDAREA_H
+#ifndef TABBEDAREA_H
+#define TABBEDAREA_H
#include <guichan/widget.hpp>
#include <guichan/widgets/tabbedarea.hpp>
diff --git a/src/gui/window.cpp b/src/gui/window.cpp
index 64607243..58439316 100644
--- a/src/gui/window.cpp
+++ b/src/gui/window.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -24,13 +24,9 @@
#include <climits>
#include <guichan/exception.hpp>
-#include <guichan/widgets/icon.hpp>
-
-#include <libxml/tree.h>
-
-#include "window.h"
#include "gui.h"
+#include "window.h"
#include "windowcontainer.h"
#include "widgets/layout.h"
@@ -38,7 +34,6 @@
#include "../configlistener.h"
#include "../configuration.h"
-#include "../graphics.h"
#include "../log.h"
#include "../resources/image.h"
@@ -50,55 +45,53 @@ ConfigListener *Window::windowConfigListener = 0;
WindowContainer *Window::windowContainer = 0;
int Window::instances = 0;
int Window::mouseResize = 0;
+//ImageRect Window::border;
Image *Window::closeImage = NULL;
-bool mLoaded = false;
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)));
- }
- */
-
void optionChanged(const std::string &)
{
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),
mLayout(NULL),
+ mWindowName("window"),
+ mShowTitle(true),
mModal(modal),
mCloseButton(false),
mSticky(false),
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");
}
- loadSkin("graphics/gui/gui.xml");
+ // Loads the skin
+ loadSkin(mSkin);
+
+ setGuiAlpha();
- //if (instances == 0)
- //{
- //WindowConfigListener = new WindowConfigListener();
+ if (instances == 0)
+ {
+ windowConfigListener = new WindowConfigListener;
// Send GUI alpha changed for initialization
- //windowConfigListener->optionChanged("guialpha");
- //config.addListener("guialpha", windowConfigListener);
- //}
+ windowConfigListener->optionChanged("guialpha");
+ config.addListener("guialpha", windowConfigListener);
+ }
instances++;
@@ -106,8 +99,6 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
setPadding(3);
setTitleBarHeight(20);
- setGuiAlpha();
-
// Add this window to the window container
windowContainer->add(this);
@@ -125,16 +116,18 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
Window::~Window()
{
- logger->log("UNLOAD: Window::~Window(\"%s\")", getCaption().c_str());
+ logger->log("Window::~Window(\"%s\")", getCaption().c_str());
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());
}
@@ -151,22 +144,21 @@ 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
closeImage->decRef();
}
-
- // Clean up Border images.
- for( int i = 0; i < 9; i++ )
- {
- delete border[i];
- border[i] = NULL;
- }
}
void Window::setWindowContainer(WindowContainer *wc)
@@ -176,17 +168,12 @@ void Window::setWindowContainer(WindowContainer *wc)
void Window::draw(gcn::Graphics *graphics)
{
- if (mAlphaChanged)
- setGuiAlpha();
-
Graphics *g = static_cast<Graphics*>(graphics);
- //g->drawImageRect(0, 0, getWidth(), getHeight(), border);
-
- g->drawImageRect(0, 0, getWidth(), getHeight(), border[0], border[2], border[6], border[8], border[1], border[5], border[7], border[3], border[4]);
+ g->drawImageRect(0, 0, getWidth(), getHeight(), border);
// Draw title
- if (getTitleBarHeight())
+ if (mShowTitle)
{
g->setColor(gcn::Color(0, 0, 0));
g->setFont(getFont());
@@ -201,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);
}
@@ -248,7 +244,7 @@ void Window::setResizable(bool r)
if (r)
{
- mGrip = new ResizeGrip();
+ mGrip = new ResizeGrip;
mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
add(mGrip);
@@ -263,17 +259,16 @@ void Window::setResizable(bool r)
void Window::widgetResized(const gcn::Event &event)
{
+ const gcn::Rectangle area = getChildrenArea();
+
if (mGrip)
- {
- const gcn::Rectangle area = getChildrenArea();
mGrip->setPosition(getWidth() - mGrip->getWidth() - area.x,
getHeight() - mGrip->getHeight() - area.y);
- }
if (mLayout)
{
- int w = getWidth() - 2 * getPadding();
- int h = getHeight() - getPadding() - getTitleBarHeight();
+ int w = area.width;
+ int h = area.height;
mLayout->reflow(w, h);
}
}
@@ -527,39 +522,13 @@ int Window::getResizeHandles(gcn::MouseEvent &event)
return resizeHandles;
}
-Layout &Window::getLayout()
-{
- if (!mLayout) mLayout = new Layout;
- return *mLayout;
-}
-
-LayoutCell &Window::place(int x, int y, gcn::Widget *wg, int w, int h)
-{
- add(wg);
- return getLayout().place(wg, x, y, w, h);
-}
-
-ContainerPlacer Window::getPlacer(int x, int y)
-{
- return ContainerPlacer(this, &getLayout().at(x, y));
-}
-
-void Window::reflowLayout(int w, int h)
-{
- assert(mLayout);
- mLayout->reflow(w, h);
- delete mLayout;
- mLayout = NULL;
- setContentSize(w, h);
-}
-
void Window::setGuiAlpha()
{
//logger->log("Window::setGuiAlpha: Alpha Value %f", config.getValue("guialpha", 0.8));
- for(int i = 0; i < 9; i++)
+ for (int i = 0; i < 9; i++)
{
//logger->log("Window::setGuiAlpha: Border Image (%i)", i);
- border[i]->setAlpha(config.getValue("guialpha", 0.8));
+ border.grid[i]->setAlpha(config.getValue("guialpha", 0.8));
}
mAlphaChanged = false;
@@ -567,13 +536,15 @@ void Window::setGuiAlpha()
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'.", Window::getId().c_str());
+ logger->log("Loading Window ID '%s'.", windowId.c_str());
- if (fileName == "")
+ if (fileName.empty())
logger->error("Window::loadSkin(): Invalid File Name.");
// TODO:
@@ -591,7 +562,7 @@ void Window::loadSkin(const std::string &fileName)
std::string skinSetImage;
skinSetImage = XML::getProperty(rootNode, "image", "");
Image *dBorders = NULL;
- if(skinSetImage != "")
+ 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");
@@ -611,7 +582,7 @@ void Window::loadSkin(const std::string &fileName)
widgetType = XML::getProperty(widgetNode, "type", "unknown");
if (widgetType == "Window")
{
- // Itarate through <part>'s
+ // 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.
@@ -625,90 +596,90 @@ void Window::loadSkin(const std::string &fileName)
std::string partType;
partType = XML::getProperty(partNode, "type", "unknown");
// TOP ROW
- if(partType == "top-left-corner")
+ 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[0] = dBorders->getSubImage(xPos, yPos, width, height);
+ border.grid[0] = dBorders->getSubImage(xPos, yPos, width, height);
}
- else if(partType == "top-edge")
+ 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[1] = dBorders->getSubImage(xPos, yPos, width, height);
+ border.grid[1] = dBorders->getSubImage(xPos, yPos, width, height);
}
- else if(partType == "top-right-corner")
+ 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[2] = dBorders->getSubImage(xPos, yPos, width, height);
+ border.grid[2] = dBorders->getSubImage(xPos, yPos, width, height);
}
// MIDDLE ROW
- else if(partType == "left-edge")
+ 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[3] = dBorders->getSubImage(xPos, yPos, width, height);
+ border.grid[3] = dBorders->getSubImage(xPos, yPos, width, height);
}
- else if(partType == "bg-quad")
+ 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[4] = dBorders->getSubImage(xPos, yPos, width, height);
+ border.grid[4] = dBorders->getSubImage(xPos, yPos, width, height);
}
- else if(partType == "right-edge")
+ 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[5] = dBorders->getSubImage(xPos, yPos, width, height);
+ border.grid[5] = dBorders->getSubImage(xPos, yPos, width, height);
}
// BOTTOM ROW
- else if(partType == "bottom-left-corner")
+ 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[6] = dBorders->getSubImage(xPos, yPos, width, height);
+ border.grid[6] = dBorders->getSubImage(xPos, yPos, width, height);
}
- else if(partType == "bottom-edge")
+ 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[7] = dBorders->getSubImage(xPos, yPos, width, height);
+ border.grid[7] = dBorders->getSubImage(xPos, yPos, width, height);
}
- else if(partType == "bottom-right-corner")
+ 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[8] = dBorders->getSubImage(xPos, yPos, width, height);
+ border.grid[8] = dBorders->getSubImage(xPos, yPos, width, height);
}
// Part is of an uknown type.
@@ -731,3 +702,29 @@ void Window::loadSkin(const std::string &fileName)
// 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;
+ return *mLayout;
+}
+
+LayoutCell &Window::place(int x, int y, gcn::Widget *wg, int w, int h)
+{
+ add(wg);
+ return getLayout().place(wg, x, y, w, h);
+}
+
+ContainerPlacer Window::getPlacer(int x, int y)
+{
+ return ContainerPlacer(this, &getLayout().at(x, y));
+}
+
+void Window::reflowLayout(int w, int h)
+{
+ assert(mLayout);
+ mLayout->reflow(w, h);
+ delete mLayout;
+ mLayout = NULL;
+ setContentSize(w, h);
+}
diff --git a/src/gui/window.h b/src/gui/window.h
index 50a206f0..3806342a 100644
--- a/src/gui/window.h
+++ b/src/gui/window.h
@@ -1,30 +1,32 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_WINDOW_H__
-#define _TMW_WINDOW_H__
+#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);
@@ -247,11 +275,6 @@ class Window : public gcn::Window, gcn::WidgetListener
*/
ContainerPlacer getPlacer(int x, int y);
- /**
- * Loads a window skin
- */
- void loadSkin(const std::string &fileName);
-
protected:
/** The window container windows add themselves to. */
static WindowContainer *windowContainer;
@@ -274,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 */
@@ -282,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 */
@@ -290,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.
@@ -298,10 +325,7 @@ class Window : public gcn::Window, gcn::WidgetListener
static int mouseResize; /**< Active resize handles */
static int instances; /**< Number of Window instances */
-
- void setGuiAlpha();
- static bool mAlphaChanged;
- Image *border[9];
+ ImageRect border; /**< The window border and background */
static Image *closeImage; /**< Close Button Image */
/**
diff --git a/src/gui/windowcontainer.cpp b/src/gui/windowcontainer.cpp
index d8535f73..2846b1c1 100644
--- a/src/gui/windowcontainer.cpp
+++ b/src/gui/windowcontainer.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/gui/windowcontainer.h b/src/gui/windowcontainer.h
index 88a13d31..62704d1b 100644
--- a/src/gui/windowcontainer.h
+++ b/src/gui/windowcontainer.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_WINDOWCONTAINER_H_
-#define _TMW_WINDOWCONTAINER_H_
+#ifndef WINDOWCONTAINER_H
+#define WINDOWCONTAINER_H
#include <guichan/widgets/container.hpp>
@@ -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 4fb7ea3e..4863421c 100644
--- a/src/guichanfwd.h
+++ b/src/guichanfwd.h
@@ -1,28 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_GUICHANFWD_H
-#define _TMW_GUICHANFWD_H
+#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 65780345..557b3553 100644
--- a/src/imageparticle.cpp
+++ b/src/imageparticle.cpp
@@ -1,27 +1,26 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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/imageparticle.h b/src/imageparticle.h
index c18b30b8..317b17ea 100644
--- a/src/imageparticle.h
+++ b/src/imageparticle.h
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/inventory.cpp b/src/inventory.cpp
index 85461f90..cdd7b61c 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -1,47 +1,52 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "inventory.h"
-
#include <algorithm>
+#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
+ {
+#ifdef TMWSERV_SUPPORT
return item && item->getId() && item->getQuantity();
+#else
+ return item && item->getId() != -1 && item->getQuantity() > 0;
+#endif
}
};
-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;
@@ -49,53 +54,70 @@ Inventory::~Inventory()
Item* Inventory::getItem(int index) const
{
- if (index < 0 || index >= INVENTORY_SIZE)
+#ifdef TMWSERV_SUPPORT
+ if (index < 0 || index >= mSize)
+#else
+ if (index < 0 || index >= mSize || !mItems[index] || mItems[index]->getQuantity() <= 0)
+#endif
return 0;
return mItems[index];
}
+Item* Inventory::findItem(int itemId) const
+{
+ for (int i = 0; i < mSize; i++)
+ if (mItems[i] && mItems[i]->getId() == itemId)
+ return mItems[i];
+
+ return NULL;
+}
-void Inventory::addItem(int id, int quantity)
+void Inventory::addItem(int id, int quantity, bool equipment)
{
- setItem(getFreeSlot(), id, quantity);
+ setItem(getFreeSlot(), id, quantity, equipment);
}
-void Inventory::setItem(int index, int id, int quantity)
+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;
}
- if (!mItems[index] && id > 0) {
- mItems[index] = new Item(id, quantity);
- mItems[index]->setInvIndex(index);
- } else if (id > 0) {
+ if (!mItems[index] && id > 0)
+ {
+ Item *item = new Item(id, quantity, equipment);
+ item->setInvIndex(index);
+ mItems[index] = item;
+ }
+ else if (id > 0)
+ {
mItems[index]->setId(id);
mItems[index]->setQuantity(quantity);
- } else if (mItems[index]) {
- removeItemIndex(index);
+ mItems[index]->setEquipment(equipment);
+ }
+ else if (mItems[index])
+ {
+ removeItemAt(index);
}
}
void Inventory::clear()
{
- for (int i = 0; i < INVENTORY_SIZE; i++) {
- removeItemIndex(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) {
- removeItemIndex(i);
- }
- }
+ for (int i = 0; i < mSize; i++)
+ if (mItems[i] && mItems[i]->getId() == id)
+ removeItemAt(i);
}
-void Inventory::removeItemIndex(int index)
+void Inventory::removeItemAt(int index)
{
delete mItems[index];
mItems[index] = 0;
@@ -103,34 +125,34 @@ void Inventory::removeItemIndex(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, mItems + INVENTORY_SIZE,
+#ifdef TMWSERV_SUPPORT
+ Item **i = std::find_if(mItems, mItems + mSize,
+#else
+ Item **i = std::find_if(mItems + 2, mItems + mSize,
+#endif
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 90d9c7a2..d2a81edf 100644
--- a/src/inventory.h
+++ b/src/inventory.h
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -24,15 +24,13 @@
class Item;
-#define INVENTORY_SIZE 50
-
class Inventory
{
public:
/**
* Constructor.
*/
- Inventory();
+ Inventory(int size);
/**
* Destructor.
@@ -40,19 +38,32 @@ 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;
/**
+ * Searches for the specified item by it's id.
+ *
+ * @param itemId The id of the item to be searched.
+ * @return Item found on success, NULL on failure.
+ */
+ Item* findItem(int itemId) const;
+
+ /**
* Adds a new item in a free slot.
*/
- void addItem(int id, int quantity);
+ void addItem(int id, int quantity, bool equipment = false);
/**
* Sets the item at the given position.
*/
- void setItem(int index, int id, int quantity);
+ void setItem(int index, int id, int quantity, bool equipment = false);
/**
* Remove a item from the inventory.
@@ -60,9 +71,9 @@ class Inventory
void removeItem(int id);
/**
- * Remove a item from the inventory, specified by the index.
+ * Remove the item at the specified index from the inventory.
*/
- void removeItemIndex(int index);
+ void removeItemAt(int index);
/**
* Checks if the given item is in the inventory
@@ -92,6 +103,7 @@ class Inventory
static const int NO_SLOT_INDEX = -1; /**< Slot has no index. */
protected:
Item **mItems; /**< The holder of items */
+ int mSize; /**< The max number of inventory items */
};
#endif
diff --git a/src/item.cpp b/src/item.cpp
index 374d5051..042c3800 100644
--- a/src/item.cpp
+++ b/src/item.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -24,9 +24,17 @@
#include "resources/image.h"
#include "resources/resourcemanager.h"
-Item::Item(int id, int quantity) :
+Item::Item(int id, int quantity, bool equipment
+#ifdef EATHENA_SUPPORT
+ , bool equipped
+#endif
+ ):
mImage(0),
- mQuantity(quantity)
+ mQuantity(quantity),
+ mEquipment(equipment)
+#ifdef EATHENA_SUPPORT
+ , mEquipped(equipped)
+#endif
{
setId(id);
}
@@ -41,8 +49,10 @@ void Item::setId(int id)
{
mId = id;
+#ifdef TMWSERV_SUPPORT
// Types 0 and 1 are not equippable items.
mEquipment = id && getInfo().getType() >= 2;
+#endif
// Load the associated image
if (mImage)
@@ -55,4 +65,3 @@ void Item::setId(int id)
if (!mImage)
mImage = resman->getImage("graphics/gui/unknown-item.png");
}
-
diff --git a/src/item.h b/src/item.h
index 37db52a4..1fd1ee88 100644
--- a/src/item.h
+++ b/src/item.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _ITEM_H_
-#define _ITEM_H_
+#ifndef ITEM_H
+#define ITEM_H
#include "resources/itemdb.h"
@@ -35,7 +35,11 @@ class Item
/**
* Constructor.
*/
- Item(int id = 0, int quantity = 0);
+ Item(int id = -1, int quantity = 0, bool equipment = false
+#ifdef EATHENA_SUPPORT
+ , bool equipped = false
+#endif
+ );
/**
* Destructor.
@@ -50,8 +54,7 @@ class Item
/**
* Returns the item id.
*/
- int
- getId() const { return mId; }
+ int getId() const { return mId; }
/**
* Returns the item image.
@@ -61,50 +64,63 @@ 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; }
/**
* Returns whether this item is considered equipment.
*/
- bool
- isEquipment() const { return mEquipment; }
+ bool isEquipment() const { return mEquipment; }
+
+#ifdef EATHENA_SUPPORT
+ /**
+ * Sets whether this item is equipped.
+ */
+ void setEquipped(bool equipped) { mEquipped = equipped; }
+
+ /**
+ * Returns whether this item is equipped.
+ */
+ bool isEquipped() const { return mEquipped; }
+#endif
/**
* 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. */
Image *mImage; /**< Item image. */
int mQuantity; /**< Number of items. */
bool mEquipment; /**< Item is equipment. */
+#ifdef EATHENA_SUPPORT
+ bool mEquipped; /**< Item is equipped. */
+#endif
int mInvIndex; /**< Inventory index. */
};
diff --git a/src/itemshortcut.cpp b/src/itemshortcut.cpp
index bea14864..2dea8c56 100644
--- a/src/itemshortcut.cpp
+++ b/src/itemshortcut.cpp
@@ -1,31 +1,31 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 "configuration.h"
-#include "utils/tostring.h"
+#include "utils/stringutils.h"
ItemShortcut::ItemShortcut *itemShortcut;
@@ -33,9 +33,8 @@ ItemShortcut::ItemShortcut():
mItemSelected(-1)
{
for (int i = 0; i < SHORTCUT_ITEMS; i++)
- {
mItems[i] = -1;
- }
+
load();
}
@@ -51,9 +50,7 @@ void ItemShortcut::load()
int itemId = (int) config.getValue("shortcut" + toString(i), -1);
if (itemId != -1)
- {
mItems[i] = itemId;
- }
}
}
@@ -70,21 +67,26 @@ void ItemShortcut::useItem(int index)
{
if (mItems[index])
{
- Item *item = player_node->searchForItem(mItems[index]);
+ Item *item = player_node->getInventory()->findItem(mItems[index]);
if (item && item->getQuantity())
{
- // TODO: Fix this (index vs. pointer mismatch)
- /*
- if (item->isEquipment()) {
- if (item->isEquipped()) {
+ if (item->isEquipment())
+ {
+#ifdef EATHENA_SUPPORT
+ if (item->isEquipped())
player_node->unequipItem(item);
- } else {
+ else
+#endif
player_node->equipItem(item);
- }
- } else {
+ }
+ else
+ {
+#ifdef TMWSERV_SUPPORT
+ player_node->useItem(item->getInvIndex());
+#else
player_node->useItem(item);
+#endif
}
- */
}
}
}
diff --git a/src/itemshortcut.h b/src/itemshortcut.h
index a0c52468..95e17f44 100644
--- a/src/itemshortcut.h
+++ b/src/itemshortcut.h
@@ -1,28 +1,28 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ITEMSHORTCUT_H__
-#define _TMW_ITEMSHORTCUT_H__
+#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 b05e9b5f..b72c9103 100644
--- a/src/joystick.cpp
+++ b/src/joystick.cpp
@@ -1,27 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "joystick.h"
-
#include "configuration.h"
+#include "joystick.h"
#include "log.h"
#include <cassert>
diff --git a/src/joystick.h b/src/joystick.h
index ee029915..4c5390c2 100644
--- a/src/joystick.h
+++ b/src/joystick.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_JOYSTICK_H
-#define _TMW_JOYSTICK_H
+#ifndef JOYSTICK_H
+#define JOYSTICK_H
#include <SDL.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,
@@ -96,4 +100,4 @@ class Joystick
void doCalibration();
};
-#endif // _TMW_JOYSTICK_H
+#endif // JOYSTICK_H
diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp
index 3e4e52c4..73c0fe0a 100644
--- a/src/keyboardconfig.cpp
+++ b/src/keyboardconfig.cpp
@@ -1,71 +1,103 @@
/*
- * The Mana World
- * Copyright 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.
*
- * The Mana World is free software; you can redistribute it and/or modify
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 <guichan/sdl/sdlinput.hpp>
-
+#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"},
- {"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")},
+ {"keyIgnoreInput1", SDLK_LSUPER, _("Ignore input 1")},
+ {"keyIgnoreInput2", SDLK_RSUPER, _("Ignore input 2")}
};
void KeyboardConfig::init()
@@ -111,11 +143,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;
}
@@ -133,7 +174,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;
}
@@ -141,9 +182,22 @@ 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];
+ return mActiveKeys[mKey[index].value];
}
void KeyboardConfig::refreshActiveKeys()
diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h
index 729bad5a..f7750b30 100644
--- a/src/keyboardconfig.h
+++ b/src/keyboardconfig.h
@@ -1,33 +1,30 @@
/*
- * The Mana World
- * Copyright 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.
*
- * The Mana World is free software; you can redistribute it and/or modify
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_KEYBOARDCONFIG_H
-#define _TMW_KEYBOARDCONFIG_H
+#ifndef KEYBOARDCONFIG_H
+#define KEYBOARDCONFIG_H
+#include <SDL_types.h>
#include <string>
-#include "gui/setup_keyboard.h"
-
-#include <guichan/sdl/sdlinput.hpp>
-
/**
* Each key represents a key function. Such as 'Move up', 'Attack' etc.
*/
@@ -39,6 +36,8 @@ struct KeyFunction
int value; /** The actual value that is used. */
};
+class Setup_Keyboard;
+
class KeyboardConfig
{
public:
@@ -102,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)
@@ -142,20 +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_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,27 @@ 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_IGNORE_INPUT_1,
+ KEY_IGNORE_INPUT_2,
KEY_TOTAL
};
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index ffb4aac9..21ee3a22 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -1,57 +1,77 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 "guild.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 "log.h"
+#include "statuseffect.h"
+#include "text.h"
+
+#include "gui/gui.h"
+#include "gui/ministatus.h"
+
+#ifdef TMWSERV_SUPPORT
#include "effectmanager.h"
+#include "guild.h"
#include "net/gameserver/player.h"
#include "net/chatserver/guild.h"
#include "net/chatserver/party.h"
+#endif
-#include "gui/gui.h"
-
+#ifdef EATHENA_SUPPORT
#include "net/messageout.h"
-#include "net/protocol.h"
+#include "net/ea/protocol.h"
+#endif
+
+#include "resources/animation.h"
+#include "resources/imageset.h"
+#include "resources/resourcemanager.h"
-#include "utils/tostring.h"
#include "utils/gettext.h"
+#include "utils/stringutils.h"
+#ifdef TMWSERV_SUPPORT
const short walkingKeyboardDelay = 100;
+#endif
LocalPlayer *player_node = NULL;
+static const int NAME_X_OFFSET = 15;
+static const int NAME_Y_OFFSET = 30;
+
+#ifdef TMWSERV_SUPPORT
LocalPlayer::LocalPlayer():
Player(65535, 0, NULL),
- mInventory(new Inventory),
mEquipment(new Equipment),
mAttributeBase(NB_CHARACTER_ATTRIBUTES, -1),
mAttributeEffective(NB_CHARACTER_ATTRIBUTES, -1),
@@ -59,32 +79,114 @@ LocalPlayer::LocalPlayer():
mExpNext(CHAR_SKILL_NB, -1),
mCharacterPoints(-1),
mCorrectionPoints(-1),
- mLevel(1), mLevelProgress(0),
+ mLevelProgress(0),
+#else
+LocalPlayer::LocalPlayer(Uint32 id, Uint16 job, Map *map):
+ Player(id, job, map),
+ mCharId(0),
+ mJobXp(0),
+ mJobLevel(0),
+ mXpForNextLevel(0), mJobXpForNextLevel(0),
+ mMp(0), mMaxMp(0),
+ mAttackRange(0),
+ ATK(0), MATK(0), DEF(0), MDEF(0), HIT(0), FLEE(0),
+ ATK_BONUS(0), MATK_BONUS(0), DEF_BONUS(0), MDEF_BONUS(0), FLEE_BONUS(0),
+ mStatPoint(0), mSkillPoint(0),
+ mStatsPointsToAttribute(0),
+ mEquipment(new Equipment),
+ mNetwork(0),
+ mXp(0),
+ mInStorage(false),
+ mTargetTime(-1),
+ mLastTarget(-1),
+#endif
+ mLevel(1),
mMoney(0),
mTotalWeight(1), mMaxWeight(1),
- mHP(1), mMaxHP(1),
+ mHp(1), mMaxHp(1),
mTarget(NULL), mPickUpTarget(NULL),
mTrading(false), mGoingToTarget(false),
mLastAction(-1),
mWalkingDir(0),
mDestX(0), mDestY(0),
+#ifdef TMWSERV_SUPPORT
mLocalWalkTime(-1),
- mExpMessageTime(0)
+#endif
+ mInventory(new Inventory(INVENTORY_SIZE))
+#ifdef EATHENA_SUPPORT
+ , mStorage(new Inventory(STORAGE_SIZE))
+#else
+ , mExpMessageTime(0)
+#endif
{
+ // 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;
+#ifdef EATHENA_SUPPORT
+ delete mStorage;
+#endif
+
+ for (int i = Being::TC_SMALL; i < Being::NUM_TC; i++)
+ {
+ delete mTargetCursor[0][i];
+ delete mTargetCursor[1][i];
+ mTargetCursorImages[0][i]->decRef();
+ mTargetCursorImages[1][i]->decRef();
+ }
}
void LocalPlayer::logic()
{
+#ifdef EATHENA_SUPPORT
+ switch (mAction) {
+ case STAND:
+ break;
+
+ case SIT:
+ break;
+
+ case DEAD:
+ break;
+
+ case HURT:
+ break;
+
+ case WALK:
+ mFrame = (get_elapsed_time(mWalkTime) * 6) / getWalkSpeed();
+ if (mFrame >= 6)
+ nextStep();
+ break;
+
+ case ATTACK:
+ int frames = 4;
+ if (mEquippedWeapon &&
+ mEquippedWeapon->getAttackType() == ACTION_ATTACK_BOW)
+ frames = 5;
+
+ mFrame = (get_elapsed_time(mWalkTime) * frames) / mAttackSpeed;
+
+ if (mFrame >= frames)
+ nextStep();
+
+ break;
+ }
+#endif
+
// Actions are allowed once per second
- if (get_elapsed_time(mLastAction) >= 1000) {
+ if (get_elapsed_time(mLastAction) >= 1000)
mLastAction = -1;
- }
+#ifdef TMWSERV_SUPPORT
// Show XP messages
if (!mExpMessages.empty())
{
@@ -93,7 +195,7 @@ void LocalPlayer::logic()
const Vector &pos = getPosition();
particleEngine->addTextRiseFadeOutEffect(mExpMessages.front(),
0, 128, 255,
- speechFont,
+ gui->getFont(),
(int) pos.x + 16,
(int) pos.y - 16);
mExpMessages.pop_front();
@@ -101,10 +203,63 @@ void LocalPlayer::logic()
}
mExpMessageTime--;
}
+#else
+ // 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)
+ {
+ // Find whether target is in range
+ const int rangeX = abs(mTarget->mX - mX);
+ const int rangeY = abs(mTarget->mY - mY);
+ const int attackRange = getAttackRange();
+ const int inRange = rangeX > attackRange || rangeY > attackRange ? 1 : 0;
+
+ mTarget->setTargetAnimation(
+ mTargetCursor[inRange][mTarget->getTargetCursorSize()]);
+
+ if (mTarget->mAction == DEAD)
+ stopAttack();
+
+ if (mKeepAttacking && mTarget)
+ attack(mTarget, true);
+ }
+#endif
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()
{
// TODO: Fix picking up when reaching target (this method is obsolete)
@@ -112,21 +267,19 @@ void LocalPlayer::nextStep()
if (mPath.empty())
{
if (mPickUpTarget)
- {
pickUp(mPickUpTarget);
- }
if (mWalkingDir)
- {
walk(mWalkingDir);
- }
}
// TODO: Fix automatically walking within range of target, when wanted
if (mGoingToTarget && mTarget && withinAttackRange(mTarget))
{
mAction = Being::STAND;
- //attack(mTarget, true);
+#ifdef EATHENA_SUPPORT
+ attack(mTarget, true);
+#endif
mGoingToTarget = false;
mPath.clear();
return;
@@ -136,8 +289,13 @@ void LocalPlayer::nextStep()
mGoingToTarget = false;
mPath.clear();
}
+
+#ifdef EATHENA_SUPPORT
+ Player::nextStep();
+#endif
}
+#ifdef TMWSERV_SUPPORT
bool LocalPlayer::checkInviteRights(const std::string &guildName)
{
Guild *guild = getGuild(guildName);
@@ -181,34 +339,35 @@ void LocalPlayer::setInvItem(int index, int id, int amount)
mInventory->setItem(index, id, amount);
}
+#endif
+
void LocalPlayer::moveInvItem(Item *item, int newIndex)
{
// special case, the old and new cannot copy over each other.
if (item->getInvIndex() == newIndex)
return;
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::moveItem(
item->getInvIndex(), newIndex, item->getQuantity());
-}
-
-Item* LocalPlayer::searchForItem(int itemId)
-{
- for (int i = 0; i < INVENTORY_SIZE; i++)
- {
- if (Item *item = mInventory->getItem(i)) {
- if (item->getId() == itemId) {
- return item;
- }
- }
- }
- return NULL;
+#endif
+ // TODO: eAthena support
}
void LocalPlayer::equipItem(Item *item)
{
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::equip(item->getInvIndex());
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PLAYER_EQUIP);
+ outMsg.writeInt16(item->getInvIndex());
+ outMsg.writeInt16(0);
+#endif
}
+#ifdef TMWSERV_SUPPORT
+
void LocalPlayer::unequipItem(int slot)
{
Net::GameServer::Player::unequip(slot);
@@ -222,11 +381,46 @@ void LocalPlayer::useItem(int slot)
Net::GameServer::Player::useItem(slot);
}
+#else
+
+void LocalPlayer::unequipItem(Item *item)
+{
+ if (!item)
+ return;
+
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PLAYER_UNEQUIP);
+ outMsg.writeInt16(item->getInvIndex());
+
+ // Tidy equipment directly to avoid weapon still shown bug, for instance
+ mEquipment->removeEquipment(item->getInvIndex());
+}
+
+void LocalPlayer::useItem(Item *item)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PLAYER_INVENTORY_USE);
+ outMsg.writeInt16(item->getInvIndex());
+ outMsg.writeInt32(item->getId());
+ // Note: id is dest of item, usually player_node->account_ID ??
+}
+
+#endif
+
void LocalPlayer::dropItem(Item *item, int quantity)
{
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::drop(item->getInvIndex(), quantity);
+#else
+ // TODO: Fix wrong coordinates of drops, serverside?
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PLAYER_INVENTORY_DROP);
+ outMsg.writeInt16(item->getInvIndex());
+ outMsg.writeInt16(quantity);
+#endif
}
+#ifdef TMWSERV_SUPPORT
void LocalPlayer::splitItem(Item *item, int quantity)
{
int newIndex = mInventory->getFreeSlot();
@@ -236,39 +430,68 @@ void LocalPlayer::splitItem(Item *item, int quantity)
item->getInvIndex(), newIndex, quantity);
}
}
+#endif
void LocalPlayer::pickUp(FloorItem *item)
{
+#ifdef TMWSERV_SUPPORT
int dx = item->getX() - (int) getPosition().x / 32;
int dy = item->getY() - (int) getPosition().y / 32;
+#else
+ int dx = item->getX() - mX;
+ int dy = item->getY() - mY;
+#endif
- if (dx * dx + dy * dy < 4) {
+ if (dx * dx + dy * dy < 4)
+ {
+#ifdef TMWSERV_SUPPORT
int id = item->getId();
Net::GameServer::Player::pickUp(id >> 16, id & 0xFFFF);
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_ITEM_PICKUP);
+ outMsg.writeInt32(item->getId());
+#endif
mPickUpTarget = NULL;
- } else {
+ }
+ else
+ {
+#ifdef TMWSERV_SUPPORT
setDestination(item->getX() * 32 + 16, item->getY() * 32 + 16);
+#else
+ setDestination(item->getX(), item->getY());
+#endif
mPickUpTarget = item;
+#ifdef EATHENA_SUPPORT
+ stopAttack();
+#endif
}
}
void LocalPlayer::walk(unsigned char dir)
{
- // TODO: Evaluate the implementation of this method
+ // TODO: Evaluate the implementation of this method for tmwserv
if (!mMap || !dir)
return;
+#ifdef TMWSERV_SUPPORT
const Vector &pos = getPosition();
int dScaler; // Distance to walk
+#endif
if (mAction == WALK && !mPath.empty())
{
// Just finish the current action, otherwise we get out of sync
+#ifdef TMWSERV_SUPPORT
Being::setDestination(pos.x, pos.y);
+#else
+ Being::setDestination(mX, mY);
+#endif
return;
}
int dx = 0, dy = 0;
+#ifdef TMWSERV_SUPPORT
if (dir & UP)
dy -= 32;
if (dir & DOWN)
@@ -277,17 +500,35 @@ void LocalPlayer::walk(unsigned char dir)
dx -= 32;
if (dir & RIGHT)
dx += 32;
+#else
+ if (dir & UP)
+ dy--;
+ if (dir & DOWN)
+ dy++;
+ if (dir & LEFT)
+ dx--;
+ if (dir & RIGHT)
+ dx++;
+#endif
// Prevent skipping corners over colliding tiles
+#ifdef TMWSERV_SUPPORT
if (dx && !mMap->getWalk(((int) pos.x + dx) / 32,
(int) pos.y / 32, getWalkMask()))
dx = 16 - (int) pos.x % 32;
if (dy && !mMap->getWalk((int) pos.x / 32,
((int) pos.y + dy) / 32, getWalkMask()))
dy = 16 - (int) pos.y % 32;
+#else
+ if (dx && !mMap->getWalk(mX + dx, mY, getWalkMask()))
+ dx = 0;
+ if (dy && !mMap->getWalk(mX, mY + dy, getWalkMask()))
+ dy = 0;
+#endif
// Choose a straight direction when diagonal target is blocked
+#ifdef TMWSERV_SUPPORT
if (dx && dy && !mMap->getWalk((pos.x + dx) / 32,
(pos.y + dy) / 32, getWalkMask()))
dx = 16 - (int) pos.x % 32;
@@ -309,16 +550,74 @@ void LocalPlayer::walk(unsigned char dir)
{
setDestination((int) pos.x + (dx * dScaler), (int) pos.y + (dy * dScaler));
}
+#else
+ if (dx && dy && !mMap->getWalk(mX + dx, mY + dy, getWalkMask()))
+ dx = 0;
+
+ // Walk to where the player can actually go
+ if ((dx || dy) && mMap->getWalk(mX + dx, mY + dy, getWalkMask()))
+ {
+ setDestination(mX + dx, mY + dy);
+ }
+#endif
else if (dir)
{
// If the being can't move, just change direction
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::changeDir(dir);
+#else
+ // TODO: Communicate this to the server
+#endif
setDirection(dir);
}
}
+Being* LocalPlayer::getTarget() const
+{
+ return mTarget;
+}
+
+void LocalPlayer::setTarget(Being *target)
+{
+#ifdef EATHENA_SUPPORT
+ if (mLastTarget != -1 || target == this)
+ return;
+
+ mLastTarget = tick_time;
+
+ if (target == mTarget)
+ target = NULL;
+
+ if (target || mAction == ATTACK)
+ {
+ mTargetTime = tick_time;
+ }
+ else
+ {
+ mKeepAttacking = false;
+ mTargetTime = -1;
+ }
+#endif
+
+ if (mTarget)
+ mTarget->untarget();
+
+ if (mTarget && mTarget->getType() == Being::MONSTER)
+ static_cast<Monster *>(mTarget)->showName(false);
+
+ mTarget = target;
+
+ if (target && target->getType() == Being::MONSTER)
+ static_cast<Monster *>(target)->showName(true);
+}
+
+#ifdef TMWSERV_SUPPORT
+void LocalPlayer::setDestination(int x, int y)
+#else
void LocalPlayer::setDestination(Uint16 x, Uint16 y)
+#endif
{
+#ifdef TMWSERV_SUPPORT
// Fix coordinates so that the player does not seem to dig into walls.
const int tx = x / 32;
const int ty = y / 32;
@@ -336,15 +635,25 @@ void LocalPlayer::setDestination(Uint16 x, Uint16 y)
x = tx * 32 + fx;
y = ty * 32 + fy;
+#endif
+
// Only send a new message to the server when destination changes
if (x != mDestX || y != mDestY)
{
mDestX = x;
mDestY = y;
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::walk(x, y);
//Debugging fire burst
effectManager->trigger(15,x,y);
+#else
+ char temp[4] = "";
+ MessageOut outMsg(mNetwork);
+ set_coordinates(temp, x, y, mDirection);
+ outMsg.writeInt16(0x0085);
+ outMsg.writeString(temp, 3);
+#endif
}
mPickUpTarget = NULL;
@@ -357,12 +666,16 @@ void LocalPlayer::setWalkingDir(int dir)
// If we're not already walking, start walking.
if (mAction != WALK && dir
- && get_elapsed_time(mLocalWalkTime) >= walkingKeyboardDelay)
+#ifdef TMWSERV_SUPPORT
+ && get_elapsed_time(mLocalWalkTime) >= walkingKeyboardDelay
+#endif
+ )
{
walk(dir);
}
}
+#ifdef TMWSERV_SUPPORT
void LocalPlayer::stopWalking(bool sendToServer)
{
if (mAction == WALK && mWalkingDir) {
@@ -376,6 +689,53 @@ void LocalPlayer::stopWalking(bool sendToServer)
clearPath();
}
+#endif
+
+#ifdef EATHENA_SUPPORT
+void LocalPlayer::raiseAttribute(Attribute attr)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_STAT_UPDATE_REQUEST);
+
+ switch (attr)
+ {
+ case STR:
+ outMsg.writeInt16(0x000d);
+ break;
+
+ case AGI:
+ outMsg.writeInt16(0x000e);
+ break;
+
+ case VIT:
+ outMsg.writeInt16(0x000f);
+ break;
+
+ case INT:
+ outMsg.writeInt16(0x0010);
+ break;
+
+ case DEX:
+ outMsg.writeInt16(0x0011);
+ break;
+
+ case LUK:
+ outMsg.writeInt16(0x0012);
+ break;
+ }
+ outMsg.writeInt8(1);
+}
+
+void LocalPlayer::raiseSkill(Uint16 skillId)
+{
+ if (mSkillPoint <= 0)
+ return;
+
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_SKILL_LEVELUP_REQUEST);
+ outMsg.writeInt16(skillId);
+}
+#endif
void LocalPlayer::toggleSit()
{
@@ -386,13 +746,20 @@ void LocalPlayer::toggleSit()
Being::Action newAction;
switch (mAction)
{
- case Being::STAND: newAction = Being::SIT; break;
- case Being::SIT: newAction = Being::STAND; break;
+ case STAND: newAction = SIT; break;
+ case SIT: newAction = STAND; break;
default: return;
}
+#ifdef TMWSERV_SUPPORT
setAction(newAction);
Net::GameServer::Player::changeAction(newAction);
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0089);
+ outMsg.writeInt32(0);
+ outMsg.writeInt8((newAction == SIT) ? 2 : 3);
+#endif
}
void LocalPlayer::emote(Uint8 emotion)
@@ -402,19 +769,38 @@ void LocalPlayer::emote(Uint8 emotion)
mLastAction = tick_time;
// XXX Convert for new server
- /*
- MessageOut outMsg(0x00bf);
+#ifdef EATHENA_SUPPORT
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x00bf);
outMsg.writeInt8(emotion);
- */
+#endif
}
+#ifdef EATHENA_SUPPORT
+void LocalPlayer::tradeReply(bool accept)
+{
+ if (!accept)
+ mTrading = false;
+
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_TRADE_RESPONSE);
+ outMsg.writeInt8(accept ? 3 : 4);
+}
+#endif
+
void LocalPlayer::trade(Being *being) const
{
+#ifdef TMWSERV_SUPPORT
extern std::string tradePartnerName;
extern int tradePartnerID;
tradePartnerName = being->getName();
tradePartnerID = being->getId();
Net::GameServer::Player::requestTrade(tradePartnerID);
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_TRADE_REQUEST);
+ outMsg.writeInt32(being->getId());
+#endif
}
bool LocalPlayer::tradeRequestOk() const
@@ -422,6 +808,8 @@ bool LocalPlayer::tradeRequestOk() const
return !mTrading;
}
+#ifdef TMWSERV_SUPPORT
+
void LocalPlayer::attack()
{
if (mLastAction != -1)
@@ -477,20 +865,97 @@ void LocalPlayer::useSpecial(int special)
Net::GameServer::Player::useSpecial(special);
}
-Being* LocalPlayer::getTarget() const
+#else
+
+void LocalPlayer::attack(Being *target, bool keep)
{
- return mTarget;
+ mKeepAttacking = keep;
+
+ if (!target)
+ return;
+
+ if ((mTarget != target) || !mTarget)
+ {
+ mLastTarget = -1;
+ setTarget(target);
+ }
+
+ 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)
+ setDirection(DOWN);
+ else
+ setDirection(UP);
+ }
+ else
+ {
+ if (dist_x > 0)
+ setDirection(RIGHT);
+ else
+ setDirection(LEFT);
+ }
+
+ // 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.empty())
+ sound.playSfx(soundFile);
+ }
+ else
+ {
+ sound.playSfx("sfx/fist-swish.ogg");
+ }
+
+ MessageOut outMsg(mNetwork);
+ 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;
}
+#endif // no TMWSERV_SUPPORT
+
void LocalPlayer::revive()
{
// XXX Convert for new server
- /*
- MessageOut outMsg(0x00b2);
+#ifdef EATHENA_SUPPORT
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x00b2);
outMsg.writeInt8(0);
- */
+#endif
}
+#ifdef TMWSERV_SUPPORT
+
void LocalPlayer::raiseAttribute(size_t attr)
{
// we assume that the server allows the change. When not we will undo it later.
@@ -556,8 +1021,28 @@ std::pair<int, int> LocalPlayer::getExperience(int skill)
return std::pair<int, int> (mExpCurrent.at(skill), mExpNext.at(skill));
}
+#else
+
+void LocalPlayer::setXp(int xp)
+{
+ if (mMap && xp > mXp)
+ {
+ const std::string text = toString(xp - mXp) + " xp";
+
+ // Show XP number
+ particleEngine->addTextRiseFadeOutEffect(text,
+ 255, 255, 0,
+ hitYellowFont,
+ mPx + 16, mPy - 16);
+ }
+ mXp = xp;
+}
+
+#endif
+
int LocalPlayer::getAttackRange()
{
+#ifdef TMWSERV_SUPPORT
Item *weapon = mEquipment->getEquipment(EQUIP_FIGHT1_SLOT);
if (weapon)
{
@@ -565,10 +1050,14 @@ int LocalPlayer::getAttackRange()
return info.getAttackRange();
}
return 32; // unarmed range
+#else
+ return mAttackRange;
+#endif
}
bool LocalPlayer::withinAttackRange(Being *target)
{
+#ifdef TMWSERV_SUPPORT
const Vector &targetPos = target->getPosition();
const Vector &pos = getPosition();
const int dx = abs(targetPos.x - pos.x);
@@ -576,12 +1065,119 @@ bool LocalPlayer::withinAttackRange(Being *target)
const int range = getAttackRange();
return !(dx > range || dy > range);
+#else
+ int dist_x = abs(target->mX - mX);
+ int dist_y = abs(target->mY - mY);
+
+ if (dist_x > getAttackRange() || dist_y > getAttackRange())
+ {
+ return false;
+ }
+
+ return true;
+#endif
}
void LocalPlayer::setGotoTarget(Being *target)
{
+#ifdef TMWSERV_SUPPORT
mTarget = target;
mGoingToTarget = true;
const Vector &targetPos = target->getPosition();
setDestination(targetPos.x, targetPos.y);
+#else
+ mLastTarget = -1;
+ setTarget(target);
+ mGoingToTarget = true;
+ setDestination(target->mX, target->mY);
+#endif
}
+
+
+extern MiniStatusWindow *miniStatusWindow;
+
+void LocalPlayer::handleStatusEffect(StatusEffect *effect, int effectId)
+{
+ Being::handleStatusEffect(effect, effectId);
+
+
+
+ if (effect) {
+ effect->deliverMessage();
+ effect->playSFX();
+
+ AnimatedSprite *sprite = effect->getIcon();
+
+ if (!sprite) {
+ // delete sprite, if necessary
+ for (unsigned int i = 0; i < mStatusEffectIcons.size();)
+ if (mStatusEffectIcons[i] == effectId) {
+ mStatusEffectIcons.erase(mStatusEffectIcons.begin() + i);
+ miniStatusWindow->eraseIcon(i);
+ } else i++;
+ } else {
+ // replace sprite or append
+ bool found = false;
+
+ for (unsigned int i = 0; i < mStatusEffectIcons.size(); i++)
+ if (mStatusEffectIcons[i] == effectId) {
+ miniStatusWindow->setIcon(i, sprite);
+ found = true;
+ break;
+ }
+
+ if (!found) { // add new
+ int offset = mStatusEffectIcons.size();
+ miniStatusWindow->setIcon(offset, sprite);
+ mStatusEffectIcons.push_back(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,
+ (16 - (currentImageSet->getWidth() / 2)),
+ (16 - (currentImageSet->getHeight() / 2)));
+ }
+
+ currentCursor = new SimpleAnimation(anim);
+
+ const int index = outRange ? 1 : 0;
+
+ mTargetCursorImages[index][size] = currentImageSet;
+ mTargetCursor[index][size] = currentCursor;
+}
+
diff --git a/src/localplayer.h b/src/localplayer.h
index 0b9ba712..7ced3fdf 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -1,34 +1,53 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_LOCALPLAYER_H
-#define _TMW_LOCALPLAYER_H
+#ifndef LOCALPLAYER_H
+#define LOCALPLAYER_H
+
+#include <memory>
+#include <vector>
#include "player.h"
-#include <memory>
+#ifdef EATHENA_SUPPORT
+// TODO move into some sane place...
+#define MAX_SLOT 2
+#define INVENTORY_SIZE 102
+#define STORAGE_SIZE 301
+#else
+#define INVENTORY_SIZE 50
+#endif
+
+class Equipment;
class FloorItem;
+class ImageSet;
class Inventory;
class Item;
+class Map;
+#ifdef EATHENA_SUPPORT
+class Network;
+#endif
+
+#ifdef TMWSERV_SUPPORT
/**
* Attributes used during combat. Available to all the beings.
@@ -113,26 +132,43 @@ enum
NB_CHARACTER_ATTRIBUTES = CHAR_SKILL_END
};
+#endif
+
/**
* The local player character.
*/
class LocalPlayer : public Player
{
public:
- enum Attribute {
+ enum Attribute
+ {
+#ifdef TMWSERV_SUPPORT
STR = 0, AGI, DEX, VIT, INT, WIL, CHR
+#else
+ STR = 0, AGI, VIT, INT, DEX, LUK
+#endif
};
/**
* Constructor.
*/
+#ifdef TMWSERV_SUPPORT
LocalPlayer();
+#else
+ LocalPlayer(Uint32 id, Uint16 job, Map *map);
+#endif
/**
* Destructor.
*/
~LocalPlayer();
+ virtual void setName(const std::string &name);
+
+#ifdef EATHENA_SUPPORT
+ void setNetwork(Network *network) { mNetwork = network; }
+ Network *getNetwork() {return mNetwork; }
+#endif
virtual void logic();
/**
@@ -142,11 +178,18 @@ class LocalPlayer : public Player
virtual void nextStep();
/**
- * Draws the name text below the being.
+ * Returns the player's inventory.
*/
- virtual void
- drawName(Graphics *, int, int) {};
+ Inventory* getInventory() const { return mInventory; }
+
+#ifdef EATHENA_SUPPORT
+ /**
+ * Returns the player's storage
+ */
+ Inventory* getStorage() const { return mStorage; }
+#endif
+#ifdef TMWSERV_SUPPORT
/**
* Check the player has permission to invite users to specific guild
*/
@@ -164,6 +207,7 @@ class LocalPlayer : public Player
void clearInventory();
void setInvItem(int index, int id, int amount);
+#endif
/**
* Move the Inventory item from the old slot to the new slot.
@@ -171,14 +215,6 @@ class LocalPlayer : public Player
void moveInvItem(Item *item, int newIndex);
/**
- * Searches for the specified item by it's identification.
- *
- * @param itemId The id of the item to be searched.
- * @return Item found on success, NULL on failure.
- */
- Item* searchForItem(int itemId);
-
- /**
* Equips an item.
*/
void equipItem(Item *item);
@@ -186,16 +222,33 @@ class LocalPlayer : public Player
/**
* Unequips an item.
*/
+#ifdef TMWSERV_SUPPORT
void unequipItem(int slot);
+#else
+ void unequipItem(Item *item);
+#endif
+#ifdef TMWSERV_SUPPORT
void useItem(int slot);
+#else
+ void useItem(Item *item);
+#endif
void dropItem(Item *item, int quantity);
+#ifdef TMWSERV_SUPPORT
void splitItem(Item *item, int quantity);
+#endif
void pickUp(FloorItem *item);
+#ifdef EATHENA_SUPPORT
+ /**
+ * Sets the attack range.
+ */
+ void setAttackRange(int range) { mAttackRange = range; }
+#endif
+
/**
* Gets the attack range.
*/
@@ -223,28 +276,56 @@ class LocalPlayer : public Player
*/
void setTrading(bool trading) { mTrading = trading; }
+#ifdef TMWSERV_SUPPORT
void attack();
-
void useSpecial(int id);
+#else
+ void attack(Being *target = NULL, bool keep = false);
+#endif
- Being* getTarget() const;
+ /**
+ * 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();
+
+#ifdef EATHENA_SUPPORT
+ void stopAttack();
+#endif
/**
* Overridden to do nothing. The attacks of the local player are
* displayed as soon as the player attacks, not when the server says
* the player does.
+ *
+ * @param victim The attacked being.
+ * @param damage The amount of damage dealt (0 means miss).
*/
+ virtual void handleAttack(Being *victim, int damage) {}
virtual void handleAttack() {}
/**
+ * Returns the current target of the player. Returns 0 if no being is
+ * currently targeted.
+ */
+ Being* getTarget() const;
+
+
+ /**
* Sets the target being of the player.
*/
- void setTarget(Being* target) { mTarget = target; }
+ void setTarget(Being* target);
/**
* Sets a new destination for this being to walk to.
*/
- void setDestination(Uint16 x, Uint16 y);
+#ifdef TMWSERV_SUPPORT
+ void setDestination(int x, int y);
+#else
+ virtual void setDestination(Uint16 x, Uint16 y);
+#endif
/**
* Sets a new direction to keep walking in.
@@ -267,6 +348,11 @@ class LocalPlayer : public Player
*/
bool withinAttackRange(Being *target);
+#ifdef EATHENA_SUPPORT
+ void raiseAttribute(Attribute attr);
+ void raiseSkill(Uint16 skillId);
+#else
+
/**
* Stops the player dead in his tracks
*/
@@ -281,23 +367,61 @@ class LocalPlayer : public Player
* Uses a correction point to lower an attribute
*/
void lowerAttribute(size_t attr);
+#endif
void toggleSit();
void emote(Uint8 emotion);
void revive();
- int getHP() const
- { return mHP; }
+#ifdef EATHENA_SUPPORT
+ /**
+ * 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.
+ */
+ void setXp(int xp);
+
+ /**
+ * Returns the amount of experience points.
+ */
+ int getXp() const { return mXp; }
+
+ Uint32 mCharId; /**< Used only during character selection. */
+
+ Uint32 mJobXp;
+ Uint32 mJobLevel;
+ Uint32 mXpForNextLevel, mJobXpForNextLevel;
+ Uint16 mMp, mMaxMp;
- int getMaxHP() const
- { return mMaxHP; }
+ Uint16 mAttackRange;
- void setHP(int value)
- { mHP = value; }
+ Uint8 mAttr[6];
+ Uint8 mAttrUp[6];
- void setMaxHP(int value)
- { mMaxHP = value; }
+ Sint16 ATK, MATK, DEF, MDEF, HIT, FLEE;
+ Sint16 ATK_BONUS, MATK_BONUS, DEF_BONUS, MDEF_BONUS, FLEE_BONUS;
+
+ Uint16 mStatPoint, mSkillPoint;
+ Uint16 mStatsPointsToAttribute;
+#endif
+
+ int getHp() const
+ { return mHp; }
+
+ int getMaxHp() const
+ { return mMaxHp; }
+
+ void setHp(int value)
+ { mHp = value; }
+
+ void setMaxHp(int value)
+ { mMaxHp = value; }
int getLevel() const
{ return mLevel; }
@@ -305,11 +429,13 @@ class LocalPlayer : public Player
void setLevel(int value)
{ mLevel = value; }
+#ifdef TMWSERV_SUPPORT
void setLevelProgress(int percent)
{ mLevelProgress = percent; }
int getLevelProgress() const
{ return mLevelProgress; }
+#endif
int getMoney() const
{ return mMoney; }
@@ -320,9 +446,16 @@ class LocalPlayer : public Player
int getTotalWeight() const
{ return mTotalWeight; }
+ void setTotalWeight(int value)
+ { mTotalWeight = value; }
+
int getMaxWeight() const
{ return mMaxWeight; }
+ void setMaxWeight(int value)
+ { mMaxWeight = value; }
+
+#ifdef TMWSERV_SUPPORT
int getAttributeBase(int num) const
{ return mAttributeBase[num]; }
@@ -357,14 +490,31 @@ class LocalPlayer : public Player
static const SkillInfo& getSkillInfo(int skill);
std::pair<int, int> getExperience(int skill);
+#endif
+ 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 */
- Inventory *mInventory;
const std::auto_ptr<Equipment> mEquipment;
protected:
+ virtual void
+ handleStatusEffect(StatusEffect *effect, int effectId);
+
void walk(unsigned char dir);
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+ int mXp; /**< Experience points. */
+ bool mInStorage; /**< Whether storage is currently accessible */
+ int mTargetTime; /** How long the being has been targeted **/
+ int mLastTarget; /** Time stamp of last targeting action, -1 if none. */
+#endif
+
+#ifdef TMWSERV_SUPPORT
// Character status:
std::vector<int> mAttributeBase;
std::vector<int> mAttributeEffective;
@@ -372,29 +522,56 @@ class LocalPlayer : public Player
std::vector<int> mExpNext;
int mCharacterPoints;
int mCorrectionPoints;
- int mLevel;
int mLevelProgress;
+#endif
+ int mLevel;
int mMoney;
int mTotalWeight;
int mMaxWeight;
- int mHP;
- int mMaxHP;
+ int mHp;
+ int mMaxHp;
Being *mTarget;
FloorItem *mPickUpTarget;
bool mTrading;
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 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. */
+#ifdef TMWSERV_SUPPORT
int mLocalWalkTime; /**< Timestamp used to control keyboard walk
messages flooding */
+#endif
+
+ std::vector<int> mStatusEffectIcons;
+ Inventory *mInventory;
+#ifdef EATHENA_SUPPORT
+ Inventory *mStorage;
+#endif
+
+ // Load the target cursors into memory
+ void initTargetCursor();
+
+ /**
+ * Helper function for loading target cursors
+ */
+ void loadTargetCursor(std::string filename, int width, int height,
+ bool outRange, Being::TargetCursorSize size);
+
+ /** Images of the target cursor. */
+ ImageSet *mTargetCursorImages[2][NUM_TC];
+
+ /** Animated target cursors. */
+ SimpleAnimation *mTargetCursor[2][NUM_TC];
+
+#ifdef TMWSERV_SUPPORT
std::list<std::string> mExpMessages; /**< Queued exp messages*/
int mExpMessageTime;
-
+#endif
};
extern LocalPlayer *player_node;
diff --git a/src/lockedarray.h b/src/lockedarray.h
index 8e525191..c4c83ea9 100644
--- a/src/lockedarray.h
+++ b/src/lockedarray.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_LOCKEDARRAY_H
-#define _TMW_LOCKEDARRAY_H
+#ifndef LOCKEDARRAY_H
+#define LOCKEDARRAY_H
#include <algorithm>
diff --git a/src/log.cpp b/src/log.cpp
index 96630a96..b0024f80 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -1,26 +1,24 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 30078e35..b06bdc89 100644
--- a/src/log.h
+++ b/src/log.h
@@ -1,28 +1,27 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LOG_H
#define _LOG_H
-#include <iosfwd>
#include <fstream>
class ChatWindow;
diff --git a/src/logindata.h b/src/logindata.h
index c386f490..ae89eb5f 100644
--- a/src/logindata.h
+++ b/src/logindata.h
@@ -1,26 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_LOGINDATA_H
-#define _TMW_LOGINDATA_H
+#ifndef LOGINDATA_H
+#define LOGINDATA_H
+
+#include <string>
#include <string>
@@ -31,10 +33,19 @@ struct LoginData
std::string newPassword;
std::string hostname;
std::string updateHost;
+#ifdef TMWSERV_SUPPORT
std::string email;
std::string newEmail;
+#endif
short port;
+#ifdef EATHENA_SUPPORT
+ int account_ID;
+ int session_ID1;
+ int session_ID2;
+ char sex;
+#endif
+
bool remember; /**< Whether to store the username and host. */
bool registerLogin; /**< Whether an account is being registered. */
@@ -45,10 +56,19 @@ struct LoginData
newPassword.clear();
hostname.clear();
updateHost.clear();
+#ifdef TMWSERV_SUPPORT
email.clear();
newEmail.clear();
+#endif
port = 0;
+
+#ifdef EATHENA_SUPPORT
+ account_ID = 0;
+ session_ID1 = 0;
+ session_ID2 = 0;
+ sex = 0;
+#endif
};
};
-#endif // _TMW_LOGINDATA_H
+#endif // LOGINDATA_H
diff --git a/src/main.cpp b/src/main.cpp
index 39a0fb37..7d623f69 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,26 +1,24 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "main.h"
-
#include <getopt.h>
#include <iostream>
#include <physfs.h>
@@ -33,68 +31,123 @@
#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 "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 "units.h"
+#include "gui/button.h"
+#ifdef EATHENA_SUPPORT
+#include "gui/char_server.h"
+#endif
#include "gui/char_select.h"
-#include "gui/connection.h"
+#include "gui/color.h"
#include "gui/gui.h"
#include "gui/login.h"
#include "gui/ok_dialog.h"
#include "gui/progressbar.h"
-#include "gui/quitdialog.h"
#include "gui/register.h"
#include "gui/sdlinput.h"
+#include "gui/setup.h"
+#ifdef TMWSERV_SUPPORT
+#include "gui/connection.h"
+#include "gui/quitdialog.h"
#include "gui/serverdialog.h"
-#include "gui/textfield.h"
+#endif
#include "gui/updatewindow.h"
+#ifdef TMWSERV_SUPPORT
#include "net/charserverhandler.h"
#include "net/connection.h"
#include "net/loginhandler.h"
-#include "net/logouthandler.h"
#include "net/network.h"
+#else
+#include "net/ea/charserverhandler.h"
+#include "net/ea/loginhandler.h"
+#include "net/ea/network.h"
+#include "net/ea/maploginhandler.h"
+#include "net/messageout.h"
+#endif
+#include "net/logouthandler.h"
+#ifdef TMWSERV_SUPPORT
#include "net/accountserver/accountserver.h"
#include "net/accountserver/account.h"
#include "net/chatserver/chatserver.h"
#include "net/gameserver/gameserver.h"
+#endif
+#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"
+#ifdef TMWSERV_SUPPORT
#include "utils/dtor.h"
+#endif
#include "utils/gettext.h"
-#include "utils/tostring.h"
+#include "utils/stringutils.h"
+#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
+ {
+ /**
+ * Called when receiving actions from widget.
+ */
+ void action(const gcn::ActionEvent &event);
+ } listener;
+}
+
+#ifdef TMWSERV_SUPPORT
std::string token; //used to store magic_token
+#else
+// Account infos
+char n_server, n_character;
+
+// TODO Anyone knows a good location for this? Or a way to make it non-global?
+class SERVER_INFO;
+SERVER_INFO **server_info;
+#endif
Graphics *graphics;
@@ -109,24 +162,34 @@ Configuration branding; /**< XML branding information reader */
Logger *logger; /**< Log object */
KeyboardConfig keyboard;
+#ifdef TMWSERV_SUPPORT
Net::Connection *gameServerConnection = 0;
Net::Connection *chatServerConnection = 0;
+Net::Connection *accountServerConnection = 0;
+#endif
CharServerHandler charServerHandler;
LoginData loginData;
+#ifdef TMWSERV_SUPPORT
LoginHandler loginHandler;
LogoutHandler logoutHandler;
+#endif
LockedArray<LocalPlayer*> charInfo(maxSlot + 1);
+Color *textColor;
+
// This anonymous namespace hides whatever is inside from other modules.
namespace {
-Net::Connection *accountServerConnection = 0;
-
std::string homeDir;
std::string updateHost;
std::string updatesDir;
+#ifdef EATHENA_SUPPORT
+LoginHandler loginHandler;
+MapLoginHandler mapLoginHandler;
+#endif
+
/**
* A structure holding the values of various options that can be passed from
* the command line.
@@ -140,12 +203,14 @@ struct Options
printHelp(false),
printVersion(false),
skipUpdate(false),
+ chooseDefault(false),
serverPort(0)
{};
bool printHelp;
bool printVersion;
bool skipUpdate;
+ bool chooseDefault;
std::string username;
std::string password;
std::string character;
@@ -157,18 +222,19 @@ struct Options
short serverPort;
};
-} // anonymous namespace
-
/**
* Parse the update host and determine the updates directory
* Then verify that the directory exists (creating if needed).
*/
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
@@ -178,29 +244,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 = STATE_ERROR;
}
- } 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 = STATE_ERROR;
+ }
+#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 = STATE_ERROR;
+#endif
}
}
}
@@ -231,7 +327,7 @@ void initHomeDir()
#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 +343,11 @@ void initConfiguration(const Options &options)
std::string defaultHost = branding.getValue("defaultServer",
"server.themanaworld.org");
config.setValue("host", defaultHost);
+#ifdef TWMSERV_SUPPORT
int defaultPort = (int)branding.getValue("defaultPort", 9601);
+#else
+ int defaultPort = (int)branding.getValue("defaultPort", 6901);
+#endif
config.setValue("port", defaultPort);
config.setValue("hwaccel", 0);
#if (defined __APPLE__ || defined WIN32) && defined USE_OPENGL
@@ -270,24 +370,24 @@ void initConfiguration(const Options &options)
// Checking if the configuration file exists... otherwise create 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);
}
}
@@ -341,7 +441,7 @@ void initEngine(const Options &options)
strncat(path, "/data", PATH_MAX - 1);
resman->addToSearchPath(path, true);
#else
- resman->addToSearchPath(TMW_DATADIR "data", true);
+ resman->addToSearchPath(PKG_DATADIR "data", true);
#endif
#ifdef WIN32
@@ -368,23 +468,23 @@ void initEngine(const Options &options)
Image::setLoadAsOpenGL(useOpenGL);
// Create the graphics context
- graphics = useOpenGL ? new OpenGLGraphics() : new Graphics();
+ graphics = useOpenGL ? new OpenGLGraphics : new Graphics;
#else
// Create the graphics context
- graphics = new Graphics();
+ 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);
}
@@ -393,10 +493,17 @@ void initEngine(const Options &options)
graphics->_beginDraw();
// Initialize the item shortcuts.
- itemShortcut = new ItemShortcut();
+ itemShortcut = new ItemShortcut;
+
+ // Initialize the emote shortcuts.
+ emoteShortcut = new EmoteShortcut;
gui = new Gui(graphics);
+#ifdef TMWSERV_SUPPORT
state = STATE_CHOOSE_SERVER; /**< Initial game state */
+#else
+ state = STATE_LOGIN; /**< Initial game state */
+#endif
// Initialize sound engine
try {
@@ -416,6 +523,9 @@ void initEngine(const Options &options)
// Initialize keyboard
keyboard.init();
+
+ // Initialise player relations
+ player_relations.init();
}
/** Clear the engine */
@@ -423,6 +533,7 @@ void exit_engine()
{
// Before config.write() since it writes the shortcuts to the config
delete itemShortcut;
+ delete emoteShortcut;
config.write();
@@ -436,6 +547,8 @@ void exit_engine()
sound.close();
// Unload XML databases
+ ColorDB::unload();
+ EmoteDB::unload();
ItemDB::unload();
MonsterDB::unload();
NPCDB::unload();
@@ -445,73 +558,82 @@ void exit_engine()
void printHelp()
{
- std::cout <<
- "tmw\n\n"
- "Options:\n"
- " -h --help : Display this help\n"
- " -v --version : Display the version\n"
- " -u --skipupdate : Skip the update process\n"
- " -d --data : Directory to load game data from\n"
- " -U --username : Login with this username\n"
- " -P --password : Login with this password\n"
- " -s --server : Login Server name or IP\n"
- " -o --port : Login Server Port\n"
- " -c --character : Login with this character\n"
- " -C --configfile : Configuration file to use\n"
- " -H --updatehost : Use this update host\n";
+ std::cout
+ << _("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
+ << _(" -S --homedir : Directory to use as home directory") << std::endl
+ << _(" -H --updatehost : Use this update host") << std::endl
+ << _(" -P --password : Login with this password") << std::endl
+ << _(" -c --character : Login with this character") << std::endl
+ << _(" -o --port : Login Server Port") << std::endl
+ << _(" -s --server : Login Server name or IP") << 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
}
void parseOptions(int argc, char *argv[], Options &options)
{
- const char *optstring = "hvud:U:P:Dc:s:o:C:H:";
+ const char *optstring = "hvud:U:P:Dc:s:o:C:H:S:";
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' },
+ { "default", no_argument, 0, 'D' },
{ "password", required_argument, 0, 'P' },
- { "server", required_argument, 0, 's' },
- { "port", required_argument, 0, 'o' },
{ "character", required_argument, 0, 'c' },
- { "configfile", required_argument, 0, 'C' },
+ { "help", no_argument, 0, 'h' },
+ { "homedir", required_argument, 0, 'S' },
{ "updatehost", required_argument, 0, 'H' },
+ { "port", required_argument, 0, 'o' },
+ { "server", required_argument, 0, 's' },
+ { "skipupdate", no_argument, 0, 'u' },
+ { "username", required_argument, 0, 'U' },
+ { "version", no_argument, 0, 'v' },
{ 0 }
};
while (optind < argc) {
+
int result = getopt_long(argc, argv, optstring, long_options, NULL);
if (result == -1)
break;
switch (result) {
+ case 'C':
+ options.configPath = optarg;
+ break;
+ case 'd':
+ options.dataPath = optarg;
+ break;
+ case 'D':
+ options.chooseDefault = true;
+ break;
default: // Unknown option
case 'h':
options.printHelp = true;
break;
- case 'v':
- options.printVersion = true;
- break;
- case 'u':
- options.skipUpdate = true;
- break;
- case 'd':
- options.dataPath = optarg;
+ case 'H':
+ options.updateHost = optarg;
break;
- case 'U':
- options.username = optarg;
+ case 'c':
+ options.character = optarg;
break;
case 'P':
options.password = optarg;
@@ -522,14 +644,17 @@ void parseOptions(int argc, char *argv[], Options &options)
case 'o':
options.serverPort = (short)atoi(optarg);
break;
- case 'c':
- options.character = optarg;
+ case 'u':
+ options.skipUpdate = true;
break;
- case 'C':
- options.configPath = optarg;
+ case 'U':
+ options.username = optarg;
break;
- case 'H':
- options.updateHost = optarg;
+ case 'v':
+ options.printVersion = true;
+ break;
+ case 'S':
+ homeDir = optarg;
break;
}
}
@@ -555,17 +680,19 @@ void loadUpdates()
}
}
-
-namespace {
-
struct ErrorListener : public gcn::ActionListener
{
void action(const gcn::ActionEvent &event)
{
+#ifdef TMWSERV_SUPPORT
state = STATE_CHOOSE_SERVER;
+#else
+ state = loginData.registerLogin ? STATE_REGISTER : STATE_LOGIN;
+#endif
}
} errorListener;
+#ifdef TMWSERV_SUPPORT
struct AccountListener : public gcn::ActionListener
{
void action(const gcn::ActionEvent &event)
@@ -581,29 +708,65 @@ struct LoginListener : public gcn::ActionListener
state = STATE_LOGIN;
}
} loginListener;
-
-} // anonymous namespace
+#endif
// TODO Find some nice place for these functions
+#ifdef TMWSERV_SUPPORT
void accountLogin(LoginData *loginData)
+#else
+void accountLogin(Network *network, LoginData *loginData)
+#endif
{
+#ifdef EATHENA_SUPPORT
+ logger->log("Trying to connect to account server...");
+#endif
logger->log("Username is %s", loginData->username.c_str());
-
+#ifdef EATHENA_SUPPORT
+ network->connect(loginData->hostname, loginData->port);
+ network->registerHandler(&loginHandler);
+#endif
loginHandler.setLoginData(loginData);
+#ifdef TMWSERV_SUPPORT
Net::registerHandler(&loginHandler);
charServerHandler.setCharInfo(&charInfo);
Net::registerHandler(&charServerHandler);
+#endif
// Send login infos
+#ifdef TMWSERV_SUPPORT
Net::AccountServer::login(accountServerConnection,
0, // client version
loginData->username,
loginData->password);
+#else
+ MessageOut outMsg(network);
+ outMsg.writeInt16(0x0064);
+ outMsg.writeInt32(0); // client version
+ outMsg.writeString(loginData->username, 24);
+ outMsg.writeString(loginData->password, 24);
+
+ /*
+ * eAthena calls the last byte "client version 2", but it isn't used at
+ * at all. We're retasking it, with bit 0 to indicate whether the client
+ * can handle the 0x63 "update host" packet. Clients prior to 0.0.25 send
+ * 0 here.
+ */
+ outMsg.writeInt8(0x01);
+#endif
// Clear the password, avoids auto login when returning to login
loginData->password = "";
+#ifdef EATHENA_SUPPORT
+ // Remove _M or _F from username after a login for registration purpose
+ if (loginData->registerLogin)
+ {
+ loginData->username =
+ loginData->username.substr(0, loginData->username.length() - 2);
+ }
+#endif
+
// TODO This is not the best place to save the config, but at least better
// than the login gui window
if (loginData->remember)
@@ -614,6 +777,66 @@ void accountLogin(LoginData *loginData)
config.setValue("remember", loginData->remember);
}
+#ifdef EATHENA_SUPPORT
+
+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...");
+ network->connect(loginData->hostname, loginData->port);
+ network->registerHandler(&charServerHandler);
+ charServerHandler.setCharInfo(&charInfo);
+ charServerHandler.setLoginData(loginData);
+
+ // Send login infos
+ MessageOut outMsg(network);
+ outMsg.writeInt16(0x0065);
+ outMsg.writeInt32(loginData->account_ID);
+ outMsg.writeInt32(loginData->session_ID1);
+ outMsg.writeInt32(loginData->session_ID2);
+ // [Fate] The next word is unused by the old char server, so we squeeze in
+ // tmw client version information
+ outMsg.writeInt16(CLIENT_PROTOCOL_VERSION);
+ outMsg.writeInt8(loginData->sex);
+
+ // We get 4 useless bytes before the real answer comes in
+ network->skip(4);
+}
+
+void mapLogin(Network *network, LoginData *loginData)
+{
+ logger->log("Memorizing selected character %s",
+ player_node->getName().c_str());
+ config.setValue("lastCharacter", player_node->getName());
+
+ MessageOut outMsg(network);
+
+ logger->log("Trying to connect to map server...");
+ logger->log("Map: %s", map_path.c_str());
+
+ network->connect(loginData->hostname, loginData->port);
+ network->registerHandler(&mapLoginHandler);
+
+ // Send login infos
+ outMsg.writeInt16(0x0072);
+ outMsg.writeInt32(loginData->account_ID);
+ outMsg.writeInt32(player_node->mCharId);
+ outMsg.writeInt32(loginData->session_ID1);
+ outMsg.writeInt32(loginData->session_ID2);
+ outMsg.writeInt8(loginData->sex);
+
+ // We get 4 useless bytes before the real answer comes in
+ network->skip(4);
+}
+
+#else
+
void accountRegister(LoginData *loginData)
{
logger->log("Username is %s", loginData->username.c_str());
@@ -748,6 +971,8 @@ void reconnectAccount(const std::string& passToken)
Net::AccountServer::reconnectAccount(accountServerConnection, passToken);
}
+#endif
+
void xmlNullLogger(void *ctx, const char *msg, ...)
{
// Does nothing, that's the whole point of it
@@ -764,479 +989,785 @@ void initXML()
xmlSetGenericErrorFunc(NULL, xmlNullLogger);
}
+} // namespace
+
extern "C" char const *_nl_locale_name_default(void);
/** Main */
int main(int argc, char *argv[])
{
- try
+ // Parse command line options
+ Options options;
+ parseOptions(argc, argv, options);
+ if (options.printHelp)
{
- // Parse command line options
- Options options;
- parseOptions(argc, argv, options);
- if (options.printHelp)
- {
- printHelp();
- return 0;
- }
- else if (options.printVersion)
- {
- printVersion();
- return 0;
- }
+ printHelp();
+ return 0;
+ }
+ else if (options.printVersion)
+ {
+ printVersion();
+ return 0;
+ }
#if ENABLE_NLS
#ifdef WIN32
- putenv(("LANG=" + std::string(_nl_locale_name_default())).c_str());
+ 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");
+ setlocale(LC_MESSAGES, "");
+ bind_textdomain_codeset("tmw", "UTF-8");
+ textdomain("tmw");
#endif
- // Initialize PhysicsFS
- PHYSFS_init(argv[0]);
+ // Initialize PhysicsFS
+ PHYSFS_init(argv[0]);
- initXML();
+ initXML();
- // load branding information
- branding.init("data/branding.xml");
+ // load branding information
+ branding.init("data/branding.xml");
- initHomeDir();
- // Configure logger
- logger = new Logger();
- logger->setLogFile(homeDir + std::string("/tmw.log"));
- logger->setLogToStandardOut(config.getValue("logToStandardOut", 0));
+ initHomeDir();
+ // Configure logger
+ logger = new Logger();
+ logger->setLogFile(homeDir + std::string("/tmw.log"));
+ logger->setLogToStandardOut(config.getValue("logToStandardOut", 0));
- // Log the tmw version
+ // Log the tmw version
#ifdef PACKAGE_VERSION
- logger->log("The Mana World v%s", PACKAGE_VERSION);
+ logger->log("The Mana World v%s", PACKAGE_VERSION);
#else
- logger->log("The Mana World - version not defined");
+ logger->log("The Mana World - version not defined");
#endif
- initConfiguration(options);
+ initConfiguration(options);
- initEngine(options);
+ initEngine(options);
- Game *game = NULL;
- Window *currentDialog = NULL;
- QuitDialog* quitDialog = NULL;
- Image *login_wallpaper = NULL;
+ // Needs to be created in main, as the updater uses it
+ textColor = new Color;
- gcn::Container *top = static_cast<gcn::Container*>(gui->getTop());
-#ifdef PACKAGE_VERSION
- gcn::Label *versionLabel = new gcn::Label(PACKAGE_VERSION);
- top->add(versionLabel, 25, 2);
+ Game *game = NULL;
+ Window *currentDialog = NULL;
+#ifdef TMWSERV_SUPPORT
+ QuitDialog* quitDialog = NULL;
#endif
+ Image *login_wallpaper = NULL;
+ setupWindow = new Setup;
- sound.playMusic(branding.getValue("loginMusic", ""));
-
- // Server choice
- if (options.serverName.empty()) {
- loginData.hostname = config.getValue("MostUsedServerName0",
+ gcn::Container *top = static_cast<gcn::Container*>(gui->getTop());
+#ifdef PACKAGE_VERSION
+ gcn::Label *versionLabel = new gcn::Label(PACKAGE_VERSION);
+ top->add(versionLabel, 25, 2);
+#endif
+ 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(),
+ progressBar->getY() + 4);
+ progressBar->setVisible(false);
+ gcn::Button *setup = new Button(_("Setup"), "Setup", &listener);
+ setup->setPosition(top->getWidth() - setup->getWidth() - 3, 3);
+ top->add(setup);
+
+ sound.playMusic(branding.getValue("loginMusic", ""));
+
+ // Server choice
+ if (options.serverName.empty()) {
+ loginData.hostname = config.getValue("MostUsedServerName0",
branding.getValue("defaultServer", "server.themanaworld.org").c_str());
- }
- else {
- loginData.hostname = options.serverName;
- }
- if (options.serverPort == 0) {
- loginData.port = (short)config.getValue("MostUsedServerPort0",
- branding.getValue("defaultPort", 9601));
- } else {
- loginData.port = options.serverPort;
- }
+ }
+ else {
+ loginData.hostname = options.serverName;
+ }
+ if (options.serverPort == 0) {
+ loginData.port = (short)config.getValue("MostUsedServerPort0",
+ branding.getValue("defaultPort", 9601));
+ } else {
+ loginData.port = options.serverPort;
+ }
- loginData.username = options.username;
- if (loginData.username.empty()) {
- if (config.getValue("remember", 0)) {
- loginData.username = config.getValue("username", "");
- }
- }
- if (!options.password.empty()) {
- loginData.password = options.password;
+ loginData.username = options.username;
+ if (loginData.username.empty()) {
+ if (config.getValue("remember", 0)) {
+ loginData.username = config.getValue("username", "");
}
+ }
+ if (!options.password.empty()) {
+ loginData.password = options.password;
+ }
- loginData.remember = config.getValue("remember", 0);
- loginData.registerLogin = false;
+#ifdef EATHENA_SUPPORT
+ loginData.hostname = config.getValue("host", "server.themanaworld.org");
+ loginData.port = (short)config.getValue("port", 6901);
+#endif
+ loginData.remember = config.getValue("remember", 0);
+ loginData.registerLogin = false;
+
+#ifdef TMWSERV_SUPPORT
+ Net::initialize();
+ accountServerConnection = Net::getConnection();
+ gameServerConnection = Net::getConnection();
+ chatServerConnection = Net::getConnection();
+#else
+ SDLNet_Init();
+ Network *network = new Network;
+#endif
+
+ // Set the most appropriate wallpaper, based on screen width
+ int screenWidth = (int) config.getValue("screenwidth", defaultScreenWidth);
+#ifdef EATHENA_SUPPORT
+ int screenHeight = static_cast<int>(config.getValue("screenheight",
+ defaultScreenHeight));
+#endif
+ 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";
- Net::initialize();
- accountServerConnection = Net::getConnection();
- gameServerConnection = Net::getConnection();
- chatServerConnection = Net::getConnection();
+ if (!ResourceManager::getInstance()->exists(wallpaperName))
+ wallpaperName = "graphics/images/login_wallpaper.png";
- unsigned int oldstate = !state; // We start with a status change.
+ login_wallpaper = ResourceManager::getInstance()->getImage(wallpaperName);
- SDL_Event event;
- while (state != STATE_FORCE_QUIT)
+ if (!login_wallpaper)
+ logger->log("Couldn't load %s as wallpaper", wallpaperName.c_str());
+
+ unsigned int oldstate = !state; // We start with a status change.
+
+ SDL_Event event;
+#ifdef TMWSERV_SUPPORT
+ while (state != STATE_FORCE_QUIT)
+#else
+ while (state != STATE_EXIT)
+#endif
+ {
+ // Handle SDL events
+ while (SDL_PollEvent(&event))
{
- // Handle SDL events
- while (SDL_PollEvent(&event))
+ switch (event.type)
{
- switch (event.type)
- {
- case SDL_QUIT:
- state = STATE_FORCE_QUIT;
- break;
-
- case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_ESCAPE)
+ case SDL_QUIT:
+#ifdef TMWSERV_SUPPORT
+ state = STATE_FORCE_QUIT;
+#else
+ state = STATE_EXIT;
+#endif
+ break;
+
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_ESCAPE)
+ {
+#ifdef TMWSERV_SUPPORT
+ if (!quitDialog)
{
- if (!quitDialog)
- {
- quitDialog = new QuitDialog(NULL, &quitDialog);
- }
- else
- {
- quitDialog->requestMoveToTop();
- }
+ quitDialog = new QuitDialog(NULL, &quitDialog);
}
- break;
- }
-
- guiInput->pushInput(event);
+ else
+ {
+ quitDialog->requestMoveToTop();
+ }
+#else
+ state = STATE_EXIT;
+#endif
+ }
+ break;
}
- Net::flush();
- gui->logic();
+ guiInput->pushInput(event);
+ }
- if (!login_wallpaper)
- {
- std::string wallpaperFile = branding.getValue(
- "loginWallpaper", "graphics/images/login_wallpaper.png");
- login_wallpaper = ResourceManager::getInstance()->
- getImage(wallpaperFile);
- if (!login_wallpaper)
- {
- logger->error(wallpaperFile);
- }
- }
+#ifdef TMWSERV_SUPPORT
+ Net::flush();
+#else
+ network->flush();
+ network->dispatchMessages();
+#endif
+ gui->logic();
- if (graphics->getWidth() > login_wallpaper->getWidth() ||
- graphics->getHeight() > login_wallpaper->getHeight())
- {
- graphics->setColor(gcn::Color(64, 64, 64));
- graphics->fillRectangle(gcn::Rectangle(
- 0, 0, graphics->getWidth(), graphics->getHeight()));
- }
- graphics->drawImage(login_wallpaper,
- (graphics->getWidth() - login_wallpaper->getWidth()) / 2,
- (graphics->getHeight() - login_wallpaper->getHeight()) / 2);
- gui->draw();
- graphics->updateScreen();
-
- // TODO: Add connect timeouts
- if (state == STATE_CONNECT_ACCOUNT &&
- accountServerConnection->isConnected())
- {
- if (options.skipUpdate) {
- state = STATE_LOADDATA;
- } else {
- state = STATE_UPDATE;
- }
- }
- else if (state == STATE_CONNECT_GAME &&
- gameServerConnection->isConnected() &&
- chatServerConnection->isConnected())
- {
- accountServerConnection->disconnect();
- Net::clearHandlers();
+#ifdef EATHENA_SUPPORT
+ if (network->getState() == Network::NET_ERROR)
+ {
+ state = STATE_ERROR;
- state = STATE_GAME;
+ if (!network->getError().empty()) {
+ errorMessage = network->getError();
+ } else {
+ errorMessage = _("Got disconnected from server!");
}
- else if (state == STATE_RECONNECT_ACCOUNT &&
- accountServerConnection->isConnected())
- {
- reconnectAccount(token);
- state = STATE_WAIT;
+ }
+#endif
+
+ if (progressBar->isVisible())
+ {
+ progressBar->setProgress(progressBar->getProgress() + 0.005f);
+ if (progressBar->getProgress() == 1.0f)
+ progressBar->setProgress(0.0f);
+ }
+
+ if (graphics->getWidth() > login_wallpaper->getWidth() ||
+ graphics->getHeight() > login_wallpaper->getHeight())
+ {
+ graphics->setColor(gcn::Color(64, 64, 64));
+ graphics->fillRectangle(gcn::Rectangle(
+ 0, 0, graphics->getWidth(), graphics->getHeight()));
+ }
+ graphics->drawImage(login_wallpaper,
+ (graphics->getWidth() - login_wallpaper->getWidth()) / 2,
+ (graphics->getHeight() - login_wallpaper->getHeight()) / 2);
+ gui->draw();
+ graphics->updateScreen();
+
+#ifdef TMWSERV_SUPPORT
+ // TODO: Add connect timeouts
+ if (state == STATE_CONNECT_ACCOUNT &&
+ accountServerConnection->isConnected())
+ {
+ if (options.skipUpdate) {
+ state = STATE_LOADDATA;
+ } else {
+ state = STATE_UPDATE;
}
+ }
+ else if (state == STATE_CONNECT_GAME &&
+ gameServerConnection->isConnected() &&
+ chatServerConnection->isConnected())
+ {
+ accountServerConnection->disconnect();
+ Net::clearHandlers();
- if (state != oldstate) {
- // Load updates after exiting the update state
- if (oldstate == STATE_UPDATE)
- {
- loadUpdates();
- // Reload the wallpaper in case that it was updated
- login_wallpaper->decRef();
- login_wallpaper = ResourceManager::getInstance()->getImage(
+ state = STATE_GAME;
+ }
+ else if (state == STATE_RECONNECT_ACCOUNT &&
+ accountServerConnection->isConnected())
+ {
+ reconnectAccount(token);
+ state = STATE_WAIT;
+ }
+#endif
+
+#ifdef TMWSERV_SUPPORT
+ if (state != oldstate) {
+ // Load updates after exiting the update state
+ if (oldstate == STATE_UPDATE)
+ {
+ loadUpdates();
+ // Reload the wallpaper in case that it was updated
+ login_wallpaper->decRef();
+ login_wallpaper = ResourceManager::getInstance()->getImage(
branding.getValue("loginWallpaper",
"graphics/images/login_wallpaper.png"));
- }
-
- oldstate = state;
-
- // Get rid of the dialog of the previous state
- if (currentDialog) {
- delete currentDialog;
- currentDialog = NULL;
- }
- // State has changed, while the quitDialog was active, it might
- // not be correct anymore
- if (quitDialog) {
- quitDialog->scheduleDelete();
- }
-
- switch (state) {
- case STATE_CHOOSE_SERVER:
- logger->log("State: CHOOSE_SERVER");
-
- // Allow changing this using a server choice dialog
- // We show the dialog box only if the command-line
- // options weren't set.
- if (options.serverName.empty() && options.serverPort == 0) {
- currentDialog = new ServerDialog(&loginData);
- } else {
- state = STATE_CONNECT_ACCOUNT;
-
- // Reset options so that cancelling or connect
- // timeout will show the server dialog.
- options.serverName.clear();
- options.serverPort = 0;
- }
- break;
-
- case STATE_CONNECT_ACCOUNT:
- logger->log("State: CONNECT_ACCOUNT");
- logger->log("Trying to connect to account server...");
- accountServerConnection->connect(loginData.hostname,
- loginData.port);
- currentDialog = new ConnectionDialog(
- STATE_SWITCH_ACCOUNTSERVER_ATTEMPT);
- break;
-
- case STATE_UPDATE:
- // Determine which source to use for the update host
- if (!options.updateHost.empty())
- updateHost = options.updateHost;
- else
- updateHost = loginData.updateHost;
+ }
- setUpdatesDir();
- logger->log("State: UPDATE");
- currentDialog = new UpdaterWindow(updateHost,
- homeDir + "/" + updatesDir);
- break;
-
- case STATE_LOGIN:
- logger->log("State: LOGIN");
- if (options.username.empty()
- || options.password.empty()) {
- currentDialog = new LoginDialog(&loginData);
- } else {
- state = STATE_LOGIN_ATTEMPT;
- // Clear the password so that when login fails, the
- // dialog will show up next time.
- options.password.clear();
- }
- break;
+ oldstate = state;
- case STATE_LOADDATA:
- logger->log("State: LOADDATA");
+ // Get rid of the dialog of the previous state
+ if (currentDialog) {
+ delete currentDialog;
+ currentDialog = NULL;
+ }
+ // State has changed, while the quitDialog was active, it might
+ // not be correct anymore
+ if (quitDialog) {
+ quitDialog->scheduleDelete();
+ }
- // Add customdata directory
- ResourceManager::getInstance()->searchAndAddArchives(
+ switch (state) {
+ case STATE_CHOOSE_SERVER:
+ logger->log("State: CHOOSE_SERVER");
+
+ // Allow changing this using a server choice dialog
+ // We show the dialog box only if the command-line
+ // options weren't set.
+ if (options.serverName.empty() && options.serverPort == 0) {
+ currentDialog = new ServerDialog(&loginData);
+ } else {
+ state = STATE_CONNECT_ACCOUNT;
+
+ // Reset options so that cancelling or connect
+ // timeout will show the server dialog.
+ options.serverName.clear();
+ options.serverPort = 0;
+ }
+ break;
+
+ case STATE_CONNECT_ACCOUNT:
+ logger->log("State: CONNECT_ACCOUNT");
+ logger->log("Trying to connect to account server...");
+ accountServerConnection->connect(loginData.hostname,
+ loginData.port);
+ currentDialog = new ConnectionDialog(
+ STATE_SWITCH_ACCOUNTSERVER_ATTEMPT);
+ break;
+
+ case STATE_UPDATE:
+ // Determine which source to use for the update host
+ if (!options.updateHost.empty())
+ updateHost = options.updateHost;
+ else
+ updateHost = loginData.updateHost;
+
+ setUpdatesDir();
+ logger->log("State: UPDATE");
+ currentDialog = new UpdaterWindow(updateHost,
+ homeDir + "/" + updatesDir);
+ break;
+
+ case STATE_LOGIN:
+ logger->log("State: LOGIN");
+ if (options.username.empty()
+ || options.password.empty()) {
+ currentDialog = new LoginDialog(&loginData);
+ } else {
+ state = STATE_LOGIN_ATTEMPT;
+ // Clear the password so that when login fails, the
+ // dialog will show up next time.
+ options.password.clear();
+ }
+ break;
+
+ case STATE_LOADDATA:
+ logger->log("State: LOADDATA");
+
+ // Add customdata directory
+ ResourceManager::getInstance()->searchAndAddArchives(
"customdata/",
"zip",
false);
- // Load XML databases
- ItemDB::load();
- MonsterDB::load();
- NPCDB::load();
- state = STATE_LOGIN;
- break;
-
- case STATE_LOGIN_ATTEMPT:
- accountLogin(&loginData);
- break;
-
- case STATE_LOGIN_ERROR:
- logger->log("State: LOGIN ERROR");
- currentDialog = new OkDialog("Error ", errorMessage);
- currentDialog->addActionListener(&loginListener);
- currentDialog = NULL; // OkDialog deletes itself
- break;
-
- case STATE_SWITCH_ACCOUNTSERVER:
- logger->log("State: SWITCH_ACCOUNTSERVER");
-
- gameServerConnection->disconnect();
- chatServerConnection->disconnect();
- accountServerConnection->disconnect();
-
- state = STATE_CHOOSE_SERVER;
- break;
-
- case STATE_SWITCH_ACCOUNTSERVER_ATTEMPT:
- logger->log("State: SWITCH_ACCOUNTSERVER_ATTEMPT");
- switchAccountServer();
-
- state = STATE_SWITCH_ACCOUNTSERVER;
- break;
-
- case STATE_REGISTER:
- logger->log("State: REGISTER");
- currentDialog = new RegisterDialog(&loginData);
- break;
-
- case STATE_REGISTER_ATTEMPT:
- accountRegister(&loginData);
- break;
-
- case STATE_CHAR_SELECT:
- logger->log("State: CHAR_SELECT");
- currentDialog =
- new CharSelectDialog(&charInfo, &loginData);
-
- if (((CharSelectDialog*) currentDialog)->
- selectByName(options.character)) {
- ((CharSelectDialog*) currentDialog)->action(
- gcn::ActionEvent(NULL, "ok"));
- } else {
- ((CharSelectDialog*) currentDialog)->selectByName(
- config.getValue("lastCharacter", ""));
- }
-
- break;
-
- case STATE_CHANGEEMAIL_ATTEMPT:
- logger->log("State: CHANGE EMAIL ATTEMPT");
- accountChangeEmail(&loginData);
- break;
-
- case STATE_CHANGEEMAIL:
- logger->log("State: CHANGE EMAIL");
- currentDialog = new OkDialog("Email Address change",
- "Email Address changed successfully!");
- currentDialog->addActionListener(&accountListener);
- currentDialog = NULL; // OkDialog deletes itself
- loginData.email = loginData.newEmail;
- loginData.newEmail = "";
- break;
-
- case STATE_CHANGEPASSWORD_ATTEMPT:
- logger->log("State: CHANGE PASSWORD ATTEMPT");
- accountChangePassword(&loginData);
- break;
-
- case STATE_CHANGEPASSWORD:
- logger->log("State: CHANGE PASSWORD");
- currentDialog = new OkDialog("Password change",
- "Password changed successfully!");
- currentDialog->addActionListener(&accountListener);
- currentDialog = NULL; // OkDialog deletes itself
- loginData.password = loginData.newPassword;
- loginData.newPassword = "";
- break;
-
- case STATE_UNREGISTER_ATTEMPT:
- logger->log("State: UNREGISTER ATTEMPT");
- accountUnRegister(&loginData);
- break;
-
- case STATE_UNREGISTER:
- logger->log("State: UNREGISTER");
- accountServerConnection->disconnect();
- currentDialog = new OkDialog("Unregister successful",
- "Farewell, come back any time ....");
- loginData.clear();
- //The errorlistener sets the state to STATE_CHOOSE_SERVER
- currentDialog->addActionListener(&errorListener);
- currentDialog = NULL; // OkDialog deletes itself
- break;
-
- case STATE_ACCOUNTCHANGE_ERROR:
- logger->log("State: ACCOUNT CHANGE ERROR");
- currentDialog = new OkDialog("Error ", errorMessage);
- currentDialog->addActionListener(&accountListener);
- currentDialog = NULL; // OkDialog deletes itself
- break;
-
-
- case STATE_ERROR:
- logger->log("State: ERROR");
- currentDialog = new OkDialog("Error", errorMessage);
- currentDialog->addActionListener(&errorListener);
- currentDialog = NULL; // OkDialog deletes itself
- gameServerConnection->disconnect();
- chatServerConnection->disconnect();
- Net::clearHandlers();
- break;
-
- case STATE_CONNECT_GAME:
- logger->log("State: CONNECT_GAME");
- currentDialog = new ConnectionDialog(STATE_SWITCH_ACCOUNTSERVER_ATTEMPT);
- break;
-
- case STATE_GAME:
- logger->log("Memorizing selected character %s",
- player_node->getName().c_str());
- config.setValue("lastCharacter", player_node->getName());
-
- Net::GameServer::connect(gameServerConnection, token);
- Net::ChatServer::connect(chatServerConnection, token);
- sound.fadeOutMusic(1000);
+ // Load XML databases
+ ColorDB::load();
+ ItemDB::load();
+ MonsterDB::load();
+ NPCDB::load();
+ EmoteDB::load();
+ Units::loadUnits();
+
+ state = STATE_LOGIN;
+ break;
+
+ case STATE_LOGIN_ATTEMPT:
+ accountLogin(&loginData);
+ break;
+
+ case STATE_LOGIN_ERROR:
+ logger->log("State: LOGIN ERROR");
+ currentDialog = new OkDialog("Error ", errorMessage);
+ currentDialog->addActionListener(&loginListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ break;
+
+ case STATE_SWITCH_ACCOUNTSERVER:
+ logger->log("State: SWITCH_ACCOUNTSERVER");
+
+ gameServerConnection->disconnect();
+ chatServerConnection->disconnect();
+ accountServerConnection->disconnect();
+
+ state = STATE_CHOOSE_SERVER;
+ break;
+
+ case STATE_SWITCH_ACCOUNTSERVER_ATTEMPT:
+ logger->log("State: SWITCH_ACCOUNTSERVER_ATTEMPT");
+ switchAccountServer();
+
+ state = STATE_SWITCH_ACCOUNTSERVER;
+ break;
+
+ case STATE_REGISTER:
+ logger->log("State: REGISTER");
+ currentDialog = new RegisterDialog(&loginData);
+ break;
+
+ case STATE_REGISTER_ATTEMPT:
+ accountRegister(&loginData);
+ break;
+
+ case STATE_CHAR_SELECT:
+ logger->log("State: CHAR_SELECT");
+ currentDialog =
+ new CharSelectDialog(&charInfo, &loginData);
+
+ if (((CharSelectDialog*) currentDialog)->
+ selectByName(options.character)) {
+ ((CharSelectDialog*) currentDialog)->action(
+ gcn::ActionEvent(NULL, "ok"));
+ } else {
+ ((CharSelectDialog*) currentDialog)->selectByName(
+ config.getValue("lastCharacter", ""));
+ }
+
+ break;
+
+ case STATE_CHANGEEMAIL_ATTEMPT:
+ logger->log("State: CHANGE EMAIL ATTEMPT");
+ accountChangeEmail(&loginData);
+ break;
+
+ case STATE_CHANGEEMAIL:
+ logger->log("State: CHANGE EMAIL");
+ currentDialog = new OkDialog("Email Address change",
+ "Email Address changed successfully!");
+ currentDialog->addActionListener(&accountListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ loginData.email = loginData.newEmail;
+ loginData.newEmail = "";
+ break;
+
+ case STATE_CHANGEPASSWORD_ATTEMPT:
+ logger->log("State: CHANGE PASSWORD ATTEMPT");
+ accountChangePassword(&loginData);
+ break;
+
+ case STATE_CHANGEPASSWORD:
+ logger->log("State: CHANGE PASSWORD");
+ currentDialog = new OkDialog("Password change",
+ "Password changed successfully!");
+ currentDialog->addActionListener(&accountListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ loginData.password = loginData.newPassword;
+ loginData.newPassword = "";
+ break;
+
+ case STATE_UNREGISTER_ATTEMPT:
+ logger->log("State: UNREGISTER ATTEMPT");
+ accountUnRegister(&loginData);
+ break;
+
+ case STATE_UNREGISTER:
+ logger->log("State: UNREGISTER");
+ accountServerConnection->disconnect();
+ currentDialog = new OkDialog("Unregister successful",
+ "Farewell, come back any time ....");
+ loginData.clear();
+ //The errorlistener sets the state to STATE_CHOOSE_SERVER
+ currentDialog->addActionListener(&errorListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ break;
+
+ case STATE_ACCOUNTCHANGE_ERROR:
+ logger->log("State: ACCOUNT CHANGE ERROR");
+ currentDialog = new OkDialog("Error ", errorMessage);
+ currentDialog->addActionListener(&accountListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ break;
+
+
+ case STATE_ERROR:
+ logger->log("State: ERROR");
+ currentDialog = new OkDialog("Error", errorMessage);
+ currentDialog->addActionListener(&errorListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ gameServerConnection->disconnect();
+ chatServerConnection->disconnect();
+ Net::clearHandlers();
+ break;
+
+ case STATE_CONNECT_GAME:
+ logger->log("State: CONNECT_GAME");
+ currentDialog = new ConnectionDialog(STATE_SWITCH_ACCOUNTSERVER_ATTEMPT);
+ break;
+
+ case STATE_GAME:
+ logger->log("Memorizing selected character %s",
+ player_node->getName().c_str());
+ config.setValue("lastCharacter", player_node->getName());
+
+ Net::GameServer::connect(gameServerConnection, token);
+ Net::ChatServer::connect(chatServerConnection, token);
+ sound.fadeOutMusic(1000);
#ifdef PACKAGE_VERSION
- delete versionLabel;
- versionLabel = NULL;
+ delete versionLabel;
+ versionLabel = NULL;
#endif
- currentDialog = NULL;
-
- logger->log("State: GAME");
- game = new Game;
- game->logic();
- delete game;
-
- // If the quitdialog didn't set the next state
- if (state == STATE_GAME)
- {
- state = STATE_EXIT;
- }
- break;
+ currentDialog = NULL;
- case STATE_SWITCH_CHARACTER:
- logger->log("State: SWITCH_CHARACTER");
- switchCharacter(&token);
- break;
+ logger->log("State: GAME");
+ game = new Game;
+ game->logic();
+ delete game;
+
+ // If the quitdialog didn't set the next state
+ if (state == STATE_GAME)
+ {
+ state = STATE_EXIT;
+ }
+ break;
+
+ case STATE_SWITCH_CHARACTER:
+ logger->log("State: SWITCH_CHARACTER");
+ switchCharacter(&token);
+ break;
+
+ case STATE_RECONNECT_ACCOUNT:
+ logger->log("State: RECONNECT_ACCOUNT");
+
+ // Done with game & chat
+ gameServerConnection->disconnect();
+ chatServerConnection->disconnect();
+
+ accountServerConnection->connect(
+ loginData.hostname,
+ loginData.port);
+ break;
+
+ case STATE_WAIT:
+ break;
+
+ case STATE_EXIT:
+ logger->log("State: EXIT");
+ logoutThenExit();
+ break;
+
+ default:
+ state = STATE_FORCE_QUIT;
+ break;
+ }
+ }
- case STATE_RECONNECT_ACCOUNT:
- logger->log("State: RECONNECT_ACCOUNT");
+#else // no TMWSERV_SUPPORT
- // Done with game & chat
- gameServerConnection->disconnect();
- chatServerConnection->disconnect();
+ if (state != oldstate) {
+ switch (oldstate)
+ {
+ case STATE_UPDATE:
+ loadUpdates();
+ // Reload the wallpaper in case that it was updated
+ login_wallpaper->decRef();
+ login_wallpaper = ResourceManager::getInstance()->
+ getImage(wallpaperName);
+ // Load units
+ Units::loadUnits();
+ break;
+
+ // Those states don't cause a network disconnect
+ case STATE_LOADDATA:
+ break;
+
+ case STATE_ACCOUNT:
+ case STATE_CHAR_CONNECT:
+ case STATE_CONNECTING:
+ progressBar->setVisible(false);
+ progressLabel->setCaption("");
+ break;
+
+ default:
+ network->disconnect();
+ network->clearHandlers();
+ break;
+ }
- accountServerConnection->connect(
- loginData.hostname,
- loginData.port);
- break;
+ oldstate = state;
- case STATE_WAIT:
- break;
+ if (currentDialog && state != STATE_ACCOUNT &&
+ state != STATE_CHAR_CONNECT) {
+ delete currentDialog;
+ currentDialog = NULL;
+ }
- case STATE_EXIT:
- logger->log("State: EXIT");
- logoutThenExit();
- break;
+ switch (state) {
+ case STATE_LOADDATA:
+ logger->log("State: LOADDATA");
+
+ // Add customdata directory
+ ResourceManager::getInstance()->searchAndAddArchives(
+ "customdata/",
+ "zip",
+ false);
+
+ // Load XML databases
+ ColorDB::load();
+ ItemDB::load();
+ MonsterDB::load();
+ NPCDB::load();
+ EmoteDB::load();
+
+ state = STATE_CHAR_CONNECT;
+ break;
+
+ case STATE_LOGIN:
+ logger->log("State: LOGIN");
+
+ if (!loginData.password.empty()) {
+ loginData.registerLogin = false;
+ state = STATE_ACCOUNT;
+ } else {
+ currentDialog = new LoginDialog(&loginData);
+ positionDialog(currentDialog, screenWidth,
+ screenHeight);
+ }
+ break;
+
+ case STATE_REGISTER:
+ logger->log("State: REGISTER");
+ currentDialog = new RegisterDialog(&loginData);
+ positionDialog(currentDialog, screenWidth, screenHeight);
+ break;
+
+ case STATE_CHAR_SERVER:
+ 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 = STATE_UPDATE;
+ }
+ else
+ {
+ int nextState = (options.skipUpdate) ?
+ STATE_LOADDATA : STATE_UPDATE;
+ currentDialog = new ServerSelectDialog(&loginData,
+ nextState);
+ positionDialog(currentDialog, screenWidth,
+ screenHeight);
+ if (options.chooseDefault
+ || !options.character.empty())
+ {
+ ((ServerSelectDialog*) currentDialog)->action(
+ gcn::ActionEvent(NULL, "ok"));
+ }
+ }
+ break;
+ case STATE_CHAR_SELECT:
+ 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.character))
+ options.chooseDefault = true;
+ else
+ ((CharSelectDialog*) currentDialog)->selectByName(
+ config.getValue("lastCharacter", ""));
+
+ if (options.chooseDefault)
+ ((CharSelectDialog*) currentDialog)->action(
+ gcn::ActionEvent(NULL, "ok"));
+
+ break;
+
+ case STATE_GAME:
+ sound.fadeOutMusic(1000);
- default:
- state = STATE_FORCE_QUIT;
- break;
- }
+#ifdef PACKAGE_VERSION
+ delete versionLabel;
+ versionLabel = NULL;
+#endif
+ delete progressBar;
+ delete progressLabel;
+ delete setup;
+ delete setupWindow;
+ progressBar = NULL;
+ progressLabel = NULL;
+ currentDialog = NULL;
+ setup = NULL;
+ setupWindow = NULL;
+ login_wallpaper->decRef();
+ login_wallpaper = NULL;
+
+ logger->log("State: GAME");
+ game = new Game(network);
+ game->logic();
+ delete game;
+ state = STATE_EXIT;
+ break;
+
+ case STATE_UPDATE:
+ // Determine which source to use for the update host
+ if (!options.updateHost.empty())
+ updateHost = options.updateHost;
+ else
+ updateHost = loginData.updateHost;
+
+ setUpdatesDir();
+ logger->log("State: UPDATE");
+
+ if (options.skipUpdate) {
+ state = STATE_LOADDATA;
+ } else {
+ currentDialog = new UpdaterWindow(updateHost,
+ homeDir + "/" + updatesDir);
+ positionDialog(currentDialog, screenWidth,
+ screenHeight);
+ }
+ break;
+
+ case STATE_ERROR:
+ logger->log("State: ERROR");
+ currentDialog = new OkDialog(_("Error"), errorMessage);
+ positionDialog(currentDialog, screenWidth, screenHeight);
+ currentDialog->addActionListener(&errorListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ network->disconnect();
+ network->clearHandlers();
+ break;
+
+ case STATE_CONNECTING:
+ logger->log("State: CONNECTING");
+ progressBar->setVisible(true);
+ progressLabel->setCaption(
+ _("Connecting to map server..."));
+ progressLabel->adjustSize();
+ mapLogin(network, &loginData);
+ break;
+
+ case STATE_CHAR_CONNECT:
+ progressBar->setVisible(true);
+ progressLabel->setCaption(
+ _("Connecting to character server..."));
+ progressLabel->adjustSize();
+ charLogin(network, &loginData);
+ break;
+
+ case STATE_ACCOUNT:
+ progressBar->setVisible(true);
+ progressLabel->setCaption(
+ _("Connecting to account server..."));
+ progressLabel->adjustSize();
+ accountLogin(network, &loginData);
+ break;
+
+ default:
+ state = STATE_EXIT;
+ break;
}
}
+#endif
+ /*
+ * 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;
+ delete versionLabel;
#endif
- }
- catch (...)
- {
- logger->log("Exception");
- }
+ delete progressBar;
+ delete progressLabel;
+ delete setup;
+ delete setupWindow;
+#ifdef TMWSERV_SUPPORT
if (accountServerConnection)
accountServerConnection->disconnect();
if (gameServerConnection)
@@ -1248,6 +1779,10 @@ int main(int argc, char *argv[])
delete gameServerConnection;
delete chatServerConnection;
Net::finalize();
+#else
+ delete network;
+ SDLNet_Quit();
+#endif
logger->log("Quitting");
exit_engine();
@@ -1256,3 +1791,22 @@ int main(int argc, char *argv[])
return 0;
}
+
+void SetupListener::action(const gcn::ActionEvent &event)
+{
+ Window *window = NULL;
+
+ if (event.getId() == "Setup")
+ {
+ window = setupWindow;
+ }
+
+ if (window)
+ {
+ window->setVisible(!window->isVisible());
+ if (window->isVisible())
+ {
+ window->requestMoveToTop();
+ }
+ }
+}
diff --git a/src/main.h b/src/main.h
index 49173266..11ea1f70 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_MAIN_H
-#define _TMW_MAIN_H
+#ifndef MAIN_H
+#define MAIN_H
/**
* \mainpage
@@ -57,28 +57,33 @@
#include "../config.h"
#elif defined WIN32
#include "winver.h"
+#elif defined __APPLE__
+#define PACKAGE_VERSION "0.1.0"
#endif
-#ifndef TMW_DATADIR
-#define TMW_DATADIR ""
+#ifndef PKG_DATADIR
+#define PKG_DATADIR ""
#endif
/*
* Client different States
*/
enum {
- STATE_CHOOSE_SERVER,
- STATE_CONNECT_ACCOUNT,
- STATE_UPDATE,
+ STATE_EXIT,
STATE_LOADDATA,
STATE_LOGIN,
+ STATE_REGISTER,
+ STATE_CHAR_SELECT,
+ STATE_GAME,
+ STATE_ERROR,
+ STATE_UPDATE,
+#ifdef TMWSERV_SUPPORT
+ STATE_CHOOSE_SERVER,
+ STATE_CONNECT_ACCOUNT,
STATE_LOGIN_ATTEMPT,
STATE_LOGIN_ERROR,
- STATE_REGISTER,
STATE_REGISTER_ATTEMPT,
STATE_ACCOUNTCHANGE_ERROR,
- STATE_ERROR,
- STATE_CHAR_SELECT,
STATE_CHANGEEMAIL_ATTEMPT,
STATE_CHANGEEMAIL,
STATE_CHANGEPASSWORD_ATTEMPT,
@@ -91,10 +96,16 @@ enum {
STATE_SWITCH_ACCOUNTSERVER,
STATE_LOGOUT_ATTEMPT,
STATE_CONNECT_GAME,
- STATE_GAME,
STATE_WAIT,
- STATE_EXIT,
STATE_FORCE_QUIT
+#else
+ STATE_ACCOUNT,
+ STATE_CHAR_CONNECT,
+ STATE_CHAR_SERVER,
+ STATE_CHAR_NEW,
+ STATE_CHAR_DEL,
+ STATE_CONNECTING
+#endif
};
/* length definitions for several char[]s in order
@@ -120,7 +131,12 @@ const short defaultMusicVolume = 60;
// Defines the number of usable player slots
const short maxSlot = 2;
+#ifdef TMWSERV_SUPPORT
extern std::string token;
+#else
+extern char n_server, n_character;
+#endif
+
extern unsigned char state;
extern std::string errorMessage;
diff --git a/src/map.cpp b/src/map.cpp
index 5c2290d6..e7646fd2 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -1,43 +1,42 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "map.h"
-
#include <queue>
-#include <cassert>
#include "beingmanager.h"
#include "configuration.h"
#include "game.h"
#include "graphics.h"
+#include "map.h"
#include "particle.h"
+#include "simpleanimation.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"
+#include "utils/stringutils.h"
extern volatile int tick_time;
@@ -63,6 +62,38 @@ struct Location
MetaTile *tile;
};
+TileAnimation::TileAnimation(Animation *ani):
+ mLastImage(NULL)
+{
+ mAnimation = new SimpleAnimation(ani);
+}
+
+TileAnimation::~TileAnimation()
+{
+ delete mAnimation;
+}
+
+void TileAnimation::update()
+{
+ if (!mAnimation)
+ return;
+
+ //update animation
+ mAnimation->update(1);
+
+ // exchange images
+ Image *img = mAnimation->getCurrentImage();
+ if (img != mLastImage)
+ {
+ for (std::list<std::pair<MapLayer*, int> >::iterator i =
+ mAffected.begin(); i != mAffected.end(); i++)
+ {
+ i->first->setTile(i->second, img);
+ }
+ mLastImage = img;
+ }
+}
+
MapLayer::MapLayer(int x, int y, int width, int height, bool isFringeLayer):
mX(x), mY(y),
mWidth(width), mHeight(height),
@@ -80,7 +111,7 @@ MapLayer::~MapLayer()
void MapLayer::setTile(int x, int y, Image *img)
{
- mTiles[x + y * mWidth] = img;
+ setTile(x + y * mWidth, img);
}
Image* MapLayer::getTile(int x, int y) const
@@ -110,8 +141,14 @@ void MapLayer::draw(Graphics *graphics,
{
// If drawing the fringe layer, make sure all sprites above this row of
// tiles have been drawn
- if (mIsFringeLayer) {
- while (si != sprites.end() && (*si)->getPixelY() <= y * 32) {
+ if (mIsFringeLayer)
+ {
+#ifdef TMWSERV_SUPPORT
+ while (si != sprites.end() && (*si)->getPixelY() <= y * 32)
+#else
+ while (si != sprites.end() && (*si)->getPixelY() <= y * 32 - 32)
+#endif
+ {
(*si)->draw(graphics, -scrollX, -scrollY);
si++;
}
@@ -120,7 +157,8 @@ void MapLayer::draw(Graphics *graphics,
for (int x = startX; x < endX; x++)
{
Image *img = getTile(x, y);
- if (img) {
+ if (img)
+ {
const int px = (x + mX) * 32 - scrollX;
const int py = (y + mY) * 32 - scrollY + 32 - img->getHeight();
graphics->drawImage(img, px, py);
@@ -165,6 +203,7 @@ Map::~Map()
delete_all(mLayers);
delete_all(mTilesets);
delete_all(mOverlays);
+ delete_all(mTileAnimations);
}
void Map::initializeOverlays()
@@ -211,6 +250,17 @@ bool spriteCompare(const Sprite *a, const Sprite *b)
return a->getPixelY() < b->getPixelY();
}
+void Map::update()
+{
+ //update animated tiles
+ for (std::map<int, TileAnimation*>::iterator iAni = mTileAnimations.begin();
+ iAni != mTileAnimations.end();
+ iAni++)
+ {
+ iAni->second->update();
+ }
+}
+
void Map::draw(Graphics *graphics, int scrollX, int scrollY)
{
int endPixelY = graphics->getHeight() + scrollY + mTileHeight - 1;
@@ -226,8 +276,10 @@ void Map::draw(Graphics *graphics, int scrollX, int scrollY)
// Make sure sprites are sorted
mSprites.sort(spriteCompare);
+ // 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,
@@ -354,10 +406,8 @@ Tileset* Map::getTilesetWithGid(int gid) const
void Map::blockTile(int x, int y, BlockType type)
{
- if (type == BLOCKTYPE_NONE || x < 0 || y < 0 || x >= mWidth || y >= mHeight)
- {
+ if (type == BLOCKTYPE_NONE || !contains(x, y))
return;
- }
int tileNum = x + y * mWidth;
@@ -384,10 +434,8 @@ void Map::blockTile(int x, int y, BlockType type)
bool Map::getWalk(int x, int y, char walkmask) const
{
// You can't walk outside of the map
- if (x < 0 || y < 0 || x >= mWidth || y >= mHeight)
- {
+ if (!contains(x, y))
return false;
- }
// Check if the tile is walkable
return !(mMetaTiles[x + y * mWidth].blockmask & walkmask);
@@ -419,7 +467,7 @@ static int const basicCost = 100;
Path Map::findPath(int startX, int startY, int destX, int destY, unsigned char walkmask, int maxCost)
{
// Path to be built up (empty by default)
- std::list<Position> path;
+ Path path;
// Declare open list, a list with open tiles sorted on F cost
std::priority_queue<Location> openList;
@@ -439,20 +487,19 @@ Path Map::findPath(int startX, int startY, int destX, int destY, unsigned char w
// Keep trying new open tiles until no more tiles to try or target found
while (!openList.empty() && !foundPath)
{
- // Take the location with the lowest F cost from the open list, and
- // add it to the closed list.
+ // Take the location with the lowest F cost from the open list.
Location curr = openList.top();
openList.pop();
// If the tile is already on the closed list, this means it has already
// been processed with a shorter path to the start point (lower G cost)
- if (curr.tile->whichList == onClosedList)
+ if (curr.tile->whichList == mOnClosedList)
{
continue;
}
// Put the current tile on the closed list
- curr.tile->whichList = onClosedList;
+ curr.tile->whichList = mOnClosedList;
// Check the adjacent tiles
for (int dy = -1; dy <= 1; dy++)
@@ -465,8 +512,7 @@ Path Map::findPath(int startX, int startY, int destX, int destY, unsigned char w
// Skip if if we're checking the same tile we're leaving from,
// or if the new location falls outside of the map boundaries
- if ((dx == 0 && dy == 0) ||
- (x < 0 || y < 0 || x >= mWidth || y >= mHeight))
+ if ((dx == 0 && dy == 0) || !contains(x, y))
{
continue;
}
@@ -474,7 +520,9 @@ Path Map::findPath(int startX, int startY, int destX, int destY, unsigned char w
MetaTile *newTile = getMetaTile(x, y);
// Skip if the tile is on the closed list or is not walkable
- if (newTile->whichList == onClosedList || newTile->blockmask & walkmask)
+ // unless its the destination tile
+ if (newTile->whichList == mOnClosedList ||
+ ((newTile->blockmask & walkmask) && !(x == destX && y == destY)))
{
continue;
}
@@ -510,6 +558,13 @@ Path Map::findPath(int startX, int startY, int destX, int destY, unsigned char w
++Gcost;
}
+ // It costs extra to walk through a being (needs to be enough
+ // to make it more attractive to walk around).
+ if (!getWalk(x, y, BLOCKMASK_CHARACTER | BLOCKMASK_MONSTER))
+ {
+ Gcost += 3 * basicCost;
+ }
+
// Skip if Gcost becomes too much
// Warning: probably not entirely accurate
if (Gcost > maxCost * basicCost)
@@ -517,7 +572,7 @@ Path Map::findPath(int startX, int startY, int destX, int destY, unsigned char w
continue;
}
- if (newTile->whichList != onOpenList)
+ if (newTile->whichList != mOnOpenList)
{
// Found a new tile (not on open nor on closed list)
@@ -539,7 +594,7 @@ Path Map::findPath(int startX, int startY, int destX, int destY, unsigned char w
if (x != destX || y != destY) {
// Add this tile to the open list
- newTile->whichList = onOpenList;
+ newTile->whichList = mOnOpenList;
openList.push(Location(x, y, newTile));
}
else {
@@ -568,8 +623,8 @@ Path Map::findPath(int startX, int startY, int destX, int destY, unsigned char w
// Two new values to indicate whether a tile is on the open or closed list,
// this way we don't have to clear all the values between each pathfinding.
- onClosedList += 2;
- onOpenList += 2;
+ mOnClosedList += 2;
+ mOnOpenList += 2;
// If a path has been found, iterate backwards using the parent locations
// to extract it.
@@ -604,11 +659,25 @@ 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))
+ {
+ for (std::list<ParticleEffectData>::iterator i = particleEffects.begin();
+ i != particleEffects.end();
+ i++
+ )
+ {
+ particleEngine->addEffect(i->file, i->x, i->y);
+ }
+ }
+}
+
+TileAnimation* Map::getAnimationForGid(int gid)
+{
+ std::map<int, TileAnimation*>::iterator i = mTileAnimations.find(gid);
+ if (i == mTileAnimations.end())
{
- particleEngine->addEffect(i->file, i->x, i->y);
+ return NULL;
+ } else {
+ return i->second;
}
}
diff --git a/src/map.h b/src/map.h
index 07bf2866..09bed293 100644
--- a/src/map.h
+++ b/src/map.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_MAP_H_
-#define _TMW_MAP_H_
+#ifndef MAP_H
+#define MAP_H
#include <list>
#include <vector>
@@ -28,11 +28,13 @@
#include "position.h"
#include "properties.h"
+class Animation;
class AmbientOverlay;
class Graphics;
class Image;
class MapLayer;
class Particle;
+class SimpleAnimation;
class Sprite;
class Tileset;
@@ -64,6 +66,23 @@ struct MetaTile
};
/**
+ * Animation cycle of a tile image which changes the map accordingly.
+ */
+class TileAnimation
+{
+ public:
+ TileAnimation(Animation *ani);
+ ~TileAnimation();
+ void update();
+ void addAffectedTile(MapLayer *layer, int index)
+ { mAffected.push_back(std::make_pair(layer, index)); }
+ private:
+ std::list<std::pair<MapLayer*, int> > mAffected;
+ SimpleAnimation *mAnimation;
+ Image *mLastImage;
+};
+
+/**
* A map layer. Stores a grid of tiles and their offset, and implements layer
* rendering.
*/
@@ -88,6 +107,11 @@ class MapLayer
void setTile(int x, int y, Image *img);
/**
+ * Set tile image with x + y * width already known.
+ */
+ void setTile(int index, Image *img) { mTiles[index] = img; }
+
+ /**
* Get tile image, with x and y in layer coordinates.
*/
Image *getTile(int x, int y) const;
@@ -145,6 +169,11 @@ class Map : public Properties
void initializeOverlays();
/**
+ * Updates animations. Called every game tick.
+ */
+ void update();
+
+ /**
* Draws the map to the given graphics output. This method draws all
* layers, sprites and overlay effects.
*
@@ -172,8 +201,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.
@@ -194,26 +222,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.
@@ -224,14 +248,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
@@ -241,16 +263,25 @@ class Map : public Properties
/**
* Initializes all added particle effects
*/
- void
- initializeParticleEffects(Particle* particleEngine);
+ void initializeParticleEffects(Particle* particleEngine);
+
+ /**
+ * Adds a tile animation to the map
+ */
+ void addAnimation(int gid, TileAnimation *animation)
+ { mTileAnimations[gid] = animation; }
+
+ /**
+ * Gets the tile animation for a specific gid
+ */
+ TileAnimation *getAnimationForGid(int gid);
private:
/**
* 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 the given coordinates fall within the map boundaries.
@@ -265,9 +296,6 @@ class Map : public Properties
static const unsigned char BLOCKMASK_MONSTER = 0x02; // = bin 0000 0010
int *mOccupation[NB_BLOCKTYPES];
- // Pathfinding members
- int onClosedList, onOpenList;
-
int mWidth, mHeight;
int mTileWidth, mTileHeight;
int mMaxTileHeight;
@@ -292,6 +320,8 @@ class Map : public Properties
int y;
};
std::list<ParticleEffectData> particleEffects;
+
+ std::map<int, TileAnimation*> mTileAnimations;
};
#endif
diff --git a/src/monster.cpp b/src/monster.cpp
index c472a21b..deabd7a8 100644
--- a/src/monster.cpp
+++ b/src/monster.cpp
@@ -1,44 +1,48 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "monster.h"
-
#include "animatedsprite.h"
#include "game.h"
+#include "localplayer.h"
+#include "monster.h"
#include "particle.h"
#include "sound.h"
+#include "text.h"
#include "resources/monsterdb.h"
+#include "resources/monsterinfo.h"
-#include "utils/tostring.h"
+static const int NAME_X_OFFSET = 16;
+static const int NAME_Y_OFFSET = 16;
-
-Monster::Monster(Uint16 id, Uint16 job, Map *map):
- Being(id, job, map)
+Monster::Monster(Uint32 id, Uint16 job, Map *map):
+ Being(id, job, map),
+ mText(0)
{
const MonsterInfo& info = getInfo();
// 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++)
@@ -56,27 +60,48 @@ Monster::Monster(Uint16 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()
{
+ delete mText;
+}
+
+#ifdef EATHENA_SUPPORT
+void Monster::logic()
+{
+ if (mAction != STAND)
+ {
+ mFrame = (get_elapsed_time(mWalkTime) * 4) / getWalkSpeed();
+
+ if (mFrame >= 4 && mAction != DEAD)
+ {
+ nextStep();
+ }
+ }
+
+ Being::logic();
}
+#endif
-Being::Type
-Monster::getType() const
+Being::Type Monster::getType() const
{
return MONSTER;
}
-void
-Monster::setAction(Action action, int attackType)
+void Monster::setAction(Action action, int attackType)
{
SpriteAction currentAction = ACTION_INVALID;
int rotation = 0;
@@ -93,10 +118,11 @@ Monster::setAction(Action action, int attackType)
break;
case ATTACK:
currentAction = getInfo().getAttackAction(attackType);
+ mSprites[BASE_SPRITE]->reset();
//attack particle effect
particleEffect = getInfo().getAttackParticleEffect(attackType);
- if (particleEffect != "")
+ if (!particleEffect.empty() && mParticleEffects)
{
switch (mDirection)
{
@@ -106,21 +132,21 @@ Monster::setAction(Action action, int attackType)
case RIGHT: rotation = 270; break;
default: break;
}
- mSprites[BASE_SPRITE]->reset();
- Particle *p;
- p = particleEngine->addEffect(
+ Particle *p;
+ p = particleEngine->addEffect(
particleEffect, 0, 0, rotation);
- controlParticle(p);
+ controlParticle(p);
}
break;
case STAND:
- currentAction = ACTION_STAND;
- break;
+ currentAction = ACTION_STAND;
+ break;
case HURT:
- // Not implemented yet
- break;
- default:
- break;
+ // Not implemented yet
+ break;
+ case SIT:
+ // Also not implemented yet
+ break;
}
if (currentAction != ACTION_INVALID)
@@ -136,8 +162,9 @@ Monster::setAction(Action action, int attackType)
}
}
-void
-Monster::handleAttack()
+#ifdef TMWSERV_SUPPORT
+
+void Monster::handleAttack()
{
Being::handleAttack();
@@ -149,21 +176,62 @@ Monster::handleAttack()
sound.playSfx(mi.getSound(MONSTER_EVENT_HIT));
}
-void
-Monster::takeDamage(int amount)
+#else
+
+void Monster::handleAttack(Being *victim, int damage)
+{
+ Being::handleAttack(victim, damage);
+
+ const MonsterInfo &mi = getInfo();
+ sound.playSfx(mi.getSound((damage > 0) ?
+ MONSTER_EVENT_HIT : MONSTER_EVENT_MISS));
+}
+
+#endif
+
+void Monster::takeDamage(int amount)
{
if (amount > 0) sound.playSfx(getInfo().getSound(MONSTER_EVENT_HURT));
Being::takeDamage(amount);
}
-Being::TargetCursorSize
-Monster::getTargetCursorSize() const
+Being::TargetCursorSize Monster::getTargetCursorSize() const
{
return getInfo().getTargetCursorSize();
}
-const MonsterInfo&
-Monster::getInfo() const
+const MonsterInfo &Monster::getInfo() const
{
+#ifdef TMWSERV_SUPPORT
return MonsterDB::get(mJob);
+#else
+ return MonsterDB::get(mJob - 1002);
+#endif
+}
+
+void Monster::showName(bool show)
+{
+ 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));
+ }
+ else
+ {
+ mText = 0;
+ }
+}
+
+void Monster::updateCoords()
+{
+ if (mText)
+ {
+ mText->adviseXY(mPx + NAME_X_OFFSET,
+ mPy + NAME_Y_OFFSET - getHeight());
+ }
}
diff --git a/src/monster.h b/src/monster.h
index 5b6fcf61..5251d37e 100644
--- a/src/monster.h
+++ b/src/monster.h
@@ -1,39 +1,44 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_MONSTER_H
-#define _TMW_MONSTER_H
+#ifndef MONSTER_H
+#define MONSTER_H
#include "being.h"
class MonsterInfo;
+class Text;
class Monster : public Being
{
public:
- Monster(Uint16 id, Uint16 job, Map *map);
+ Monster(Uint32 id, Uint16 job, Map *map);
- virtual ~Monster();
+ ~Monster();
- virtual void setAction(Action action, int attackType);
+#ifdef EATHENA_SUPPORT
+ virtual void logic();
+#endif
+
+ virtual void setAction(Action action, int attackType = 0);
virtual Type getType() const;
@@ -43,8 +48,15 @@ class Monster : public Being
/**
* Handles an attack of another being by this monster. Plays a hit or
* miss sound when appropriate.
+ *
+ * @param victim The attacked being.
+ * @param damage The amount of damage dealt (0 means miss).
*/
+#ifdef TMWSERV_SUPPORT
virtual void handleAttack();
+#else
+ virtual void handleAttack(Being *victim, int damage);
+#endif
/**
* Puts a damage bubble above this monster and plays the hurt sound
@@ -56,8 +68,12 @@ 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
+ */
+ void showName(bool show);
/**
* Gets the way the monster is blocked by other objects
@@ -71,6 +87,17 @@ class Monster : public Being
*/
virtual Map::BlockType getBlockType() const
{ return Map::BLOCKTYPE_MONSTER; }
+
+ /**
+ * Update the text when the monster moves
+ */
+ void updateCoords();
+
+ private:
+ /**
+ * holds a text object when the mod displays it's name, 0 otherwise
+ */
+ Text *mText;
};
#endif
diff --git a/src/net/accountserver/internal.h b/src/net/accountserver/internal.h
index 35f986cd..b3d64582 100644
--- a/src/net/accountserver/internal.h
+++ b/src/net/accountserver/internal.h
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/net/buysellhandler.cpp b/src/net/buysellhandler.cpp
index 596ac434..a551f213 100644
--- a/src/net/buysellhandler.cpp
+++ b/src/net/buysellhandler.cpp
@@ -61,17 +61,6 @@ void BuySellHandler::handleMessage(MessageIn &msg)
switch (msg.getId())
{
-#if 0
- case SMSG_NPC_BUY_SELL_CHOICE:
- buyDialog->setVisible(false);
- buyDialog->reset();
- sellDialog->setVisible(false);
- sellDialog->reset();
- buySellDialog->setVisible(true);
- current_npc = dynamic_cast<NPC*>(beingManager->findBeing(msg.readInt32()));
- break;
-#endif
-
case GPMSG_NPC_BUY:
buyDialog->reset();
buyDialog->setMoney(player_node->getMoney());
diff --git a/src/net/buysellhandler.h b/src/net/buysellhandler.h
index 52e9b2f7..719b76d9 100644
--- a/src/net/buysellhandler.h
+++ b/src/net/buysellhandler.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NET_BUYSELLHANDLER_H
-#define _TMW_NET_BUYSELLHANDLER_H
+#ifndef NET_BUYSELLHANDLER_H
+#define NET_BUYSELLHANDLER_H
#include "messagehandler.h"
diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp
index bde856a5..5905dba0 100644
--- a/src/net/charserverhandler.cpp
+++ b/src/net/charserverhandler.cpp
@@ -209,7 +209,7 @@ LocalPlayer* CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
{
LocalPlayer *tempPlayer = new LocalPlayer;
slot = msg.readInt8(); // character slot
- tempPlayer->mName = msg.readString();
+ tempPlayer->setName(msg.readString());
tempPlayer->setGender(msg.readInt8() == GENDER_MALE ? GENDER_MALE : GENDER_FEMALE);
int hs = msg.readInt8(), hc = msg.readInt8();
tempPlayer->setHairStyle(hs, hc);
diff --git a/src/net/chathandler.cpp b/src/net/chathandler.cpp
index d81a8b7d..90af899a 100644
--- a/src/net/chathandler.cpp
+++ b/src/net/chathandler.cpp
@@ -37,8 +37,6 @@
#include "../gui/chat.h"
#include "../gui/guildwindow.h"
-#include "../utils/tostring.h"
-
extern Being *player_node;
ChatHandler::ChatHandler()
diff --git a/src/net/chathandler.h b/src/net/chathandler.h
index aeaf5368..a9e9bd99 100644
--- a/src/net/chathandler.h
+++ b/src/net/chathandler.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NET_CHATHANDLER_H
-#define _TMW_NET_CHATHANDLER_H
+#ifndef NET_CHATHANDLER_H
+#define NET_CHATHANDLER_H
#include "messagehandler.h"
diff --git a/src/net/ea/beinghandler.cpp b/src/net/ea/beinghandler.cpp
new file mode 100644
index 00000000..1edc6079
--- /dev/null
+++ b/src/net/ea/beinghandler.cpp
@@ -0,0 +1,542 @@
+/*
+ * 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 <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 "../../npc.h"
+#include "../../player_relations.h"
+
+const int EMOTION_TIME = 150; /**< Duration of emotion icon */
+
+BeingHandler::BeingHandler(bool enableSync):
+ mSync(enableSync)
+{
+ static const Uint16 _messages[] = {
+ SMSG_BEING_VISIBLE,
+ SMSG_BEING_MOVE,
+ SMSG_BEING_MOVE2,
+ SMSG_BEING_REMOVE,
+ SMSG_BEING_ACTION,
+ SMSG_BEING_SELFEFFECT,
+ SMSG_BEING_EMOTION,
+ SMSG_BEING_CHANGE_LOOKS,
+ SMSG_BEING_CHANGE_LOOKS2,
+ SMSG_BEING_NAME_RESPONSE,
+ SMSG_PLAYER_UPDATE_1,
+ SMSG_PLAYER_UPDATE_2,
+ SMSG_PLAYER_MOVE,
+ SMSG_PLAYER_STOP,
+ SMSG_PLAYER_MOVE_TO_ATTACK,
+ 0x0119,
+ 0x0196,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void BeingHandler::handleMessage(MessageIn &msg)
+{
+ Uint32 id;
+ Uint16 job, speed;
+ Uint16 headTop, headMid, headBottom;
+ Uint16 shoes, gloves;
+ Uint16 weapon, shield;
+ Uint16 gmstatus;
+ Sint16 param1;
+ int stunMode;
+ Uint32 statusEffects;
+ Sint8 type;
+ Uint16 status;
+ Being *srcBeing, *dstBeing;
+ int hairStyle, hairColor, flag;
+
+ switch (msg.getId())
+ {
+ case SMSG_BEING_VISIBLE:
+ case SMSG_BEING_MOVE:
+ // Information about a being in range
+ id = msg.readInt32();
+ speed = msg.readInt16();
+ stunMode = msg.readInt16(); // opt1
+ statusEffects = msg.readInt16(); // opt2
+ statusEffects |= ((Uint32)msg.readInt16()) << 16; // option
+ job = msg.readInt16(); // class
+
+ dstBeing = beingManager->findBeing(id);
+
+ if (!dstBeing)
+ {
+ // Being with id >= 110000000 and job 0 are better
+ // known as ghosts, so don't create those.
+ if (job == 0 && id >= 110000000)
+ {
+ break;
+ }
+
+ dstBeing = beingManager->createBeing(id, job);
+ }
+ else if (msg.getId() == 0x0078)
+ {
+ dstBeing->clearPath();
+ dstBeing->mFrame = 0;
+ dstBeing->mWalkTime = tick_time;
+ dstBeing->setAction(Being::STAND);
+ }
+
+
+ // Prevent division by 0 when calculating frame
+ if (speed == 0) { speed = 150; }
+
+ dstBeing->setWalkSpeed(speed);
+ dstBeing->mJob = job;
+ hairStyle = msg.readInt16();
+ dstBeing->setSprite(Being::WEAPON_SPRITE, msg.readInt16());
+ headBottom = msg.readInt16();
+
+ if (msg.getId() == SMSG_BEING_MOVE)
+ {
+ msg.readInt32(); // server tick
+ }
+
+ dstBeing->setSprite(Being::SHIELD_SPRITE, msg.readInt16());
+ headTop = msg.readInt16();
+ headMid = msg.readInt16();
+ hairColor = msg.readInt16();
+ shoes = msg.readInt16(); // clothes color - "abused" as shoes
+ gloves = msg.readInt16(); // head dir - "abused" as gloves
+ msg.readInt16(); // guild
+ msg.readInt16(); // unknown
+ msg.readInt16(); // unknown
+ msg.readInt16(); // manner
+ dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3
+ msg.readInt8(); // karma
+ dstBeing->setGender(
+ (msg.readInt8() == 0) ? GENDER_FEMALE : GENDER_MALE);
+
+ // Set these after the gender, as the sprites may be gender-specific
+ dstBeing->setSprite(Being::BOTTOMCLOTHES_SPRITE, headBottom);
+ dstBeing->setSprite(Being::TOPCLOTHES_SPRITE, headMid);
+ dstBeing->setSprite(Being::HAT_SPRITE, headTop);
+ dstBeing->setSprite(Being::SHOE_SPRITE, shoes);
+ dstBeing->setSprite(Being::GLOVES_SPRITE, gloves);
+ dstBeing->setHairStyle(hairStyle, hairColor);
+
+ if (msg.getId() == SMSG_BEING_MOVE)
+ {
+ Uint16 srcX, srcY, dstX, dstY;
+ msg.readCoordinatePair(srcX, srcY, dstX, dstY);
+ dstBeing->setAction(Being::STAND);
+ dstBeing->mX = srcX;
+ dstBeing->mY = srcY;
+ dstBeing->setDestination(dstX, dstY);
+ }
+ else
+ {
+ Uint8 dir;
+ msg.readCoordinates(dstBeing->mX, dstBeing->mY, dir);
+ dstBeing->setDirection(dir);
+ }
+
+ msg.readInt8(); // unknown
+ msg.readInt8(); // unknown
+ msg.readInt8(); // unknown / sit
+
+ dstBeing->setStunMode(stunMode);
+ dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff);
+ dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff);
+ break;
+
+ case SMSG_BEING_MOVE2:
+ /*
+ * A simplified movement packet, used by the
+ * later versions of eAthena for both mobs and
+ * players
+ */
+ dstBeing = beingManager->findBeing(msg.readInt32());
+
+ Uint16 srcX, srcY, dstX, dstY;
+ msg.readCoordinatePair(srcX, srcY, dstX, dstY);
+ msg.readInt32(); // Server tick
+
+ /*
+ * This packet doesn't have enough info to actually
+ * create a new being, so if the being isn't found,
+ * we'll just pretend the packet didn't happen
+ */
+
+ if (dstBeing) {
+ dstBeing->setAction(Being::STAND);
+ dstBeing->mX = srcX;
+ dstBeing->mY = srcY;
+ dstBeing->setDestination(dstX, dstY);
+ }
+
+ break;
+
+ case SMSG_BEING_REMOVE:
+ // A being should be removed or has died
+ dstBeing = beingManager->findBeing(msg.readInt32());
+
+ 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->handleDeath();
+
+ if (msg.readInt8() == 1)
+ dstBeing->setAction(Being::DEAD);
+ else
+ beingManager->destroyBeing(dstBeing);
+
+ break;
+
+ case SMSG_BEING_ACTION:
+ srcBeing = beingManager->findBeing(msg.readInt32());
+ dstBeing = beingManager->findBeing(msg.readInt32());
+ msg.readInt32(); // server tick
+ msg.readInt32(); // src speed
+ msg.readInt32(); // dst speed
+ param1 = msg.readInt16();
+ msg.readInt16(); // param 2
+ type = msg.readInt8();
+ msg.readInt16(); // param 3
+
+ switch (type)
+ {
+ case 0x0a: // Critical Damage
+ if (dstBeing)
+ dstBeing->showCrit();
+ case 0x00: // Damage
+ if (dstBeing)
+ dstBeing->takeDamage(param1);
+ if (srcBeing)
+ srcBeing->handleAttack(dstBeing, param1);
+ break;
+
+ case 0x02: // Sit
+ if (srcBeing)
+ {
+ srcBeing->mFrame = 0;
+ srcBeing->setAction(Being::SIT);
+ }
+ break;
+
+ case 0x03: // Stand up
+ if (srcBeing)
+ {
+ srcBeing->mFrame = 0;
+ srcBeing->setAction(Being::STAND);
+ }
+ break;
+ }
+ break;
+
+ case SMSG_BEING_SELFEFFECT: {
+ id = (Uint32)msg.readInt32();
+ if (!beingManager->findBeing(id))
+ break;
+
+ int effectType = msg.readInt32();
+ Being* being = beingManager->findBeing(id);
+
+ effectManager->trigger(effectType, being);
+
+ break;
+ }
+
+ case SMSG_BEING_EMOTION:
+ if (!(dstBeing = beingManager->findBeing(msg.readInt32())))
+ {
+ break;
+ }
+
+ if (player_relations.hasPermission(dstBeing, PlayerRelation::EMOTE))
+ dstBeing->setEmote(msg.readInt8(), EMOTION_TIME);
+
+ break;
+
+ case SMSG_BEING_CHANGE_LOOKS:
+ case SMSG_BEING_CHANGE_LOOKS2:
+ {
+ /*
+ * SMSG_BEING_CHANGE_LOOKS (0x00c3) and
+ * SMSG_BEING_CHANGE_LOOKS2 (0x01d7) do basically the same
+ * thing. The difference is that ...LOOKS carries a single
+ * 8 bit value, where ...LOOKS2 carries two 16 bit values.
+ *
+ * If type = 2, then the first 16 bit value is the weapon ID,
+ * and the second 16 bit value is the shield ID. If no
+ * shield is equipped, or type is not 2, then the second
+ * 16 bit value will be 0.
+ */
+
+ if (!(dstBeing = beingManager->findBeing(msg.readInt32())))
+ {
+ break;
+ }
+
+ int type = msg.readInt8();
+ int id = 0;
+ int id2 = 0;
+
+ if (msg.getId() == SMSG_BEING_CHANGE_LOOKS) {
+ id = msg.readInt8();
+ } else { // SMSG_BEING_CHANGE_LOOKS2
+ id = msg.readInt16();
+ id2 = msg.readInt16();
+ }
+
+ switch (type) {
+ case 1: // eAthena LOOK_HAIR
+ dstBeing->setHairStyle(id, -1);
+ break;
+ case 2: // Weapon ID in id, Shield ID in id2
+ dstBeing->setSprite(Being::WEAPON_SPRITE, id);
+ dstBeing->setSprite(Being::SHIELD_SPRITE, id2);
+ break;
+ case 3: // Change lower headgear for eAthena, pants for us
+ dstBeing->setSprite(Being::BOTTOMCLOTHES_SPRITE, id);
+ break;
+ case 4: // Change upper headgear for eAthena, hat for us
+ dstBeing->setSprite(Being::HAT_SPRITE, id);
+ break;
+ case 5: // Change middle headgear for eathena, armor for us
+ dstBeing->setSprite(Being::TOPCLOTHES_SPRITE, id);
+ break;
+ case 6: // eAthena LOOK_HAIR_COLOR
+ dstBeing->setHairStyle(-1, id);
+ break;
+ case 8: // eAthena LOOK_SHIELD
+ dstBeing->setSprite(Being::SHIELD_SPRITE, id);
+ break;
+ case 9: // eAthena LOOK_SHOES
+ dstBeing->setSprite(Being::SHOE_SPRITE, id);
+ break;
+ case 10: // LOOK_GLOVES
+ dstBeing->setSprite(Being::GLOVES_SPRITE, id);
+ break;
+ case 11: // LOOK_CAPE
+ dstBeing->setSprite(Being::CAPE_SPRITE, id);
+ break;
+ case 12:
+ dstBeing->setSprite(Being::MISC1_SPRITE, id);
+ break;
+ case 13:
+ dstBeing->setSprite(Being::MISC2_SPRITE, id);
+ break;
+ default:
+ logger->log("SMSG_BEING_CHANGE_LOOKS: unsupported type: "
+ "%d, id: %d", type, id);
+ break;
+ }
+ }
+ break;
+
+ case SMSG_BEING_NAME_RESPONSE:
+ if ((dstBeing = beingManager->findBeing(msg.readInt32())))
+ {
+ dstBeing->setName(msg.readString(24));
+ }
+ break;
+
+ case SMSG_PLAYER_UPDATE_1:
+ case SMSG_PLAYER_UPDATE_2:
+ case SMSG_PLAYER_MOVE:
+ // An update about a player, potentially including movement.
+ id = msg.readInt32();
+ speed = msg.readInt16();
+ stunMode = msg.readInt16(); // opt1; Aethyra use this as cape
+ statusEffects = msg.readInt16(); // opt2; Aethyra use this as misc1
+ statusEffects |= ((Uint32) msg.readInt16())
+ << 16; // status.options; Aethyra uses this as misc2
+ job = msg.readInt16();
+
+ dstBeing = beingManager->findBeing(id);
+
+ if (!dstBeing)
+ {
+ dstBeing = beingManager->createBeing(id, job);
+ }
+
+ dstBeing->setWalkSpeed(speed);
+ dstBeing->mJob = job;
+ hairStyle = msg.readInt16();
+ weapon = msg.readInt16();
+ shield = msg.readInt16();
+ headBottom = msg.readInt16();
+
+ if (msg.getId() == SMSG_PLAYER_MOVE)
+ {
+ msg.readInt32(); // server tick
+ }
+
+ headTop = msg.readInt16();
+ headMid = msg.readInt16();
+ hairColor = msg.readInt16();
+ msg.readInt16(); // clothes color - Aethyra-"abused" as shoes, we ignore it
+ msg.readInt16(); // head dir - Aethyra-"abused" as gloves, we ignore it
+ msg.readInt32(); // guild
+ msg.readInt16(); // emblem
+ msg.readInt16(); // manner
+ dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3
+ msg.readInt8(); // karma
+ dstBeing->setGender(
+ (msg.readInt8() == 0) ? GENDER_FEMALE : GENDER_MALE);
+
+ // Set these after the gender, as the sprites may be gender-specific
+ dstBeing->setSprite(Being::WEAPON_SPRITE, weapon);
+ dstBeing->setSprite(Being::SHIELD_SPRITE, shield);
+ dstBeing->setSprite(Being::BOTTOMCLOTHES_SPRITE, headBottom);
+ dstBeing->setSprite(Being::TOPCLOTHES_SPRITE, headMid);
+ dstBeing->setSprite(Being::HAT_SPRITE, headTop);
+ //dstBeing->setSprite(Being::CAPE_SPRITE, cape);
+ //dstBeing->setSprite(Being::MISC1_SPRITE, misc1);
+ //dstBeing->setSprite(Being::MISC2_SPRITE, misc2);
+ dstBeing->setHairStyle(hairStyle, hairColor);
+
+ if (msg.getId() == SMSG_PLAYER_MOVE)
+ {
+ Uint16 srcX, srcY, dstX, dstY;
+ msg.readCoordinatePair(srcX, srcY, dstX, dstY);
+ dstBeing->mX = srcX;
+ dstBeing->mY = srcY;
+ dstBeing->setDestination(dstX, dstY);
+ }
+ else
+ {
+ Uint8 dir;
+ msg.readCoordinates(dstBeing->mX, dstBeing->mY, dir);
+ dstBeing->setDirection(dir);
+ }
+
+ gmstatus = msg.readInt16();
+ if (gmstatus & 0x80)
+ dstBeing->setGM();
+
+ if (msg.getId() == SMSG_PLAYER_UPDATE_1)
+ {
+ 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)
+ {
+ msg.readInt8(); // unknown
+ }
+
+ msg.readInt8(); // Lv
+ msg.readInt8(); // unknown
+
+ dstBeing->mWalkTime = tick_time;
+ dstBeing->mFrame = 0;
+
+ dstBeing->setStunMode(stunMode);
+ dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff);
+ dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff);
+ break;
+
+ 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.
+ */
+
+ id = msg.readInt32();
+ if (mSync || id != player_node->getId()) {
+ dstBeing = beingManager->findBeing(id);
+ if (dstBeing) {
+ dstBeing->mX = msg.readInt16();
+ dstBeing->mY = msg.readInt16();
+ if (dstBeing->mAction == Being::WALK) {
+ dstBeing->mFrame = 0;
+ dstBeing->setAction(Being::STAND);
+ }
+ }
+ }
+ break;
+
+ 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...
+ */
+ break;
+
+ case 0x0119:
+ // Change in players' flags
+ id = msg.readInt32();
+ dstBeing = beingManager->findBeing(id);
+ stunMode = msg.readInt16();
+ statusEffects = msg.readInt16();
+ statusEffects |= ((Uint32) msg.readInt16()) << 16;
+ msg.readInt8();
+
+ if (dstBeing) {
+ dstBeing->setStunMode(stunMode);
+ dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff);
+ dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff);
+ }
+ break;
+
+ case 0x0196:
+ // Status change
+ status = msg.readInt16();
+ id = msg.readInt32();
+ flag = msg.readInt8(); // 0: stop, 1: start
+
+ dstBeing = beingManager->findBeing(id);
+ if (dstBeing)
+ dstBeing->setStatusEffect(status, flag);
+ break;
+ }
+}
diff --git a/src/net/ea/beinghandler.h b/src/net/ea/beinghandler.h
new file mode 100644
index 00000000..16a7c8d6
--- /dev/null
+++ b/src/net/ea/beinghandler.h
@@ -0,0 +1,39 @@
+/*
+ * 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
+ */
+
+#ifndef NET_BEINGHANDLER_H
+#define NET_BEINGHANDLER_H
+
+#include "../messagehandler.h"
+
+class BeingHandler : public MessageHandler
+{
+ public:
+ BeingHandler(bool enableSync);
+
+ void handleMessage(MessageIn &msg);
+
+ private:
+ // Should we honor server "Stop Walking" packets
+ bool mSync;
+};
+
+#endif
diff --git a/src/net/ea/buysellhandler.cpp b/src/net/ea/buysellhandler.cpp
new file mode 100644
index 00000000..480c71b8
--- /dev/null
+++ b/src/net/ea/buysellhandler.cpp
@@ -0,0 +1,133 @@
+/*
+ * 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 <SDL_types.h>
+
+#include "buysellhandler.h"
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../beingmanager.h"
+#include "../../inventory.h"
+#include "../../item.h"
+#include "../../localplayer.h"
+#include "../../npc.h"
+
+#include "../../gui/buy.h"
+#include "../../gui/chat.h"
+#include "../../gui/sell.h"
+
+#include "../../utils/gettext.h"
+
+extern BuyDialog *buyDialog;
+extern Window *buySellDialog;
+extern SellDialog *sellDialog;
+
+BuySellHandler::BuySellHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_NPC_BUY_SELL_CHOICE,
+ SMSG_NPC_BUY,
+ SMSG_NPC_SELL,
+ SMSG_NPC_BUY_RESPONSE,
+ SMSG_NPC_SELL_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void BuySellHandler::handleMessage(MessageIn &msg)
+{
+ int n_items;
+ switch (msg.getId())
+ {
+ case SMSG_NPC_BUY_SELL_CHOICE:
+ buyDialog->setVisible(false);
+ buyDialog->reset();
+ sellDialog->setVisible(false);
+ sellDialog->reset();
+ buySellDialog->setVisible(true);
+ current_npc = dynamic_cast<NPC*>(beingManager->findBeing(msg.readInt32()));
+ break;
+
+ case SMSG_NPC_BUY:
+ msg.readInt16(); // length
+ n_items = (msg.getLength() - 4) / 11;
+ buyDialog->reset();
+ buyDialog->setMoney(player_node->getMoney());
+ buyDialog->setVisible(true);
+
+ for (int k = 0; k < n_items; k++)
+ {
+ Sint32 value = msg.readInt32();
+ msg.readInt32(); // DCvalue
+ msg.readInt8(); // type
+ Sint16 itemId = msg.readInt16();
+ buyDialog->addItem(itemId, 0, value);
+ }
+ break;
+
+ case SMSG_NPC_SELL:
+ msg.readInt16(); // length
+ n_items = (msg.getLength() - 4) / 10;
+ if (n_items > 0) {
+ sellDialog->setMoney(player_node->getMoney());
+ sellDialog->reset();
+ sellDialog->setVisible(true);
+
+ for (int k = 0; k < n_items; k++)
+ {
+ Sint16 index = msg.readInt16();
+ Sint32 value = msg.readInt32();
+ msg.readInt32(); // OCvalue
+
+ Item *item = player_node->getInventory()->getItem(index);
+ if (item && !(item->isEquipped())) {
+ sellDialog->addItem(item, value);
+ }
+ }
+ }
+ else {
+ chatWindow->chatLog(_("Nothing to sell"), BY_SERVER);
+ if (current_npc) current_npc->handleDeath();
+ }
+ break;
+
+ case SMSG_NPC_BUY_RESPONSE:
+ if (msg.readInt8() == 0) {
+ chatWindow->chatLog(_("Thanks for buying"), BY_SERVER);
+ } else {
+ // Reset player money since buy dialog already assumed purchase
+ // would go fine
+ buyDialog->setMoney(player_node->getMoney());
+ chatWindow->chatLog(_("Unable to buy"), BY_SERVER);
+ }
+ break;
+
+ case SMSG_NPC_SELL_RESPONSE:
+ if (msg.readInt8() == 0) {
+ chatWindow->chatLog(_("Thanks for selling"), BY_SERVER);
+ } else {
+ chatWindow->chatLog(_("Unable to sell"), BY_SERVER);
+ }
+ break;
+ }
+}
diff --git a/src/net/ea/buysellhandler.h b/src/net/ea/buysellhandler.h
new file mode 100644
index 00000000..5bf58d8e
--- /dev/null
+++ b/src/net/ea/buysellhandler.h
@@ -0,0 +1,35 @@
+/*
+ * 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
+ */
+
+#ifndef NET_BUYSELLHANDLER_H
+#define NET_BUYSELLHANDLER_H
+
+#include "../messagehandler.h"
+
+class BuySellHandler : public MessageHandler
+{
+ public:
+ BuySellHandler();
+
+ void handleMessage(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/ea/charserverhandler.cpp b/src/net/ea/charserverhandler.cpp
new file mode 100644
index 00000000..0fef3de7
--- /dev/null
+++ b/src/net/ea/charserverhandler.cpp
@@ -0,0 +1,235 @@
+/*
+ * 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 "charserverhandler.h"
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../game.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+#include "../../logindata.h"
+#include "../../main.h"
+
+#include "../../gui/char_select.h"
+#include "../../gui/ok_dialog.h"
+
+#include "../../utils/gettext.h"
+#include "../../utils/stringutils.h"
+
+CharServerHandler::CharServerHandler():
+ mCharCreateDialog(0)
+{
+ static const Uint16 _messages[] = {
+ SMSG_CONNECTION_PROBLEM,
+ 0x006b,
+ 0x006c,
+ 0x006d,
+ 0x006e,
+ 0x006f,
+ 0x0070,
+ 0x0071,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void CharServerHandler::handleMessage(MessageIn &msg)
+{
+ 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 = STATE_ERROR;
+ break;
+
+ case 0x006b:
+ 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;
+
+ for (int i = 0; i < n_character; i++)
+ {
+ tempPlayer = readPlayerData(msg, slot);
+ mCharInfo->select(slot);
+ mCharInfo->setEntry(tempPlayer);
+ logger->log("CharServer: Player: %s (%d)",
+ tempPlayer->getName().c_str(), slot);
+ }
+
+ state = STATE_CHAR_SELECT;
+ break;
+
+ case 0x006c:
+ switch (msg.readInt8()) {
+ case 0:
+ errorMessage = _("Access denied");
+ break;
+ case 1:
+ errorMessage = _("Cannot use this ID");
+ break;
+ default:
+ errorMessage = _("Unknown failure to select character");
+ break;
+ }
+ mCharInfo->unlock();
+ break;
+
+ case 0x006d:
+ tempPlayer = readPlayerData(msg, slot);
+ mCharInfo->unlock();
+ mCharInfo->select(slot);
+ mCharInfo->setEntry(tempPlayer);
+ n_character++;
+
+ // Close the character create dialog
+ if (mCharCreateDialog)
+ {
+ mCharCreateDialog->scheduleDelete();
+ mCharCreateDialog = 0;
+ }
+ break;
+
+ case 0x006e:
+ new OkDialog(_("Error"), _("Failed to create character. Most likely"
+ " the name is already taken."));
+
+ if (mCharCreateDialog)
+ mCharCreateDialog->unlock();
+ break;
+
+ case 0x006f:
+ delete mCharInfo->getEntry();
+ mCharInfo->setEntry(0);
+ mCharInfo->unlock();
+ n_character--;
+ new OkDialog(_("Info"), _("Player deleted"));
+ break;
+
+ case 0x0070:
+ mCharInfo->unlock();
+ new OkDialog(_("Error"), _("Failed to delete character."));
+ break;
+
+ case 0x0071:
+ player_node = mCharInfo->getEntry();
+ slot = mCharInfo->getPos();
+ msg.skip(4); // CharID, must be the same as player_node->charID
+ map_path = msg.readString(16);
+ mLoginData->hostname = ipToString(msg.readInt32());
+ mLoginData->port = msg.readInt16();
+ mCharInfo->unlock();
+ mCharInfo->select(0);
+ // Clear unselected players infos
+ do
+ {
+ LocalPlayer *tmp = mCharInfo->getEntry();
+ if (tmp != player_node)
+ {
+ delete tmp;
+ mCharInfo->setEntry(0);
+ }
+ mCharInfo->next();
+ } while (mCharInfo->getPos());
+
+ mCharInfo->select(slot);
+ state = STATE_CONNECTING;
+ break;
+ }
+}
+
+LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
+{
+ LocalPlayer *tempPlayer = new LocalPlayer(mLoginData->account_ID, 0, NULL);
+ tempPlayer->setGender(
+ (mLoginData->sex == 0) ? GENDER_FEMALE : GENDER_MALE);
+
+ tempPlayer->mCharId = msg.readInt32();
+ tempPlayer->setXp(msg.readInt32());
+ tempPlayer->setMoney(msg.readInt32());
+ tempPlayer->mJobXp = msg.readInt32();
+ tempPlayer->mJobLevel = msg.readInt32();
+ tempPlayer->setSprite(Being::SHOE_SPRITE, msg.readInt16());
+ tempPlayer->setSprite(Being::GLOVES_SPRITE, msg.readInt16());
+ tempPlayer->setSprite(Being::CAPE_SPRITE, msg.readInt16());
+ tempPlayer->setSprite(Being::MISC1_SPRITE, msg.readInt16());
+ msg.readInt32(); // option
+ msg.readInt32(); // karma
+ msg.readInt32(); // manner
+ msg.skip(2); // unknown
+ tempPlayer->setHp(msg.readInt16());
+ tempPlayer->setMaxHp(msg.readInt16());
+ tempPlayer->mMp = msg.readInt16();
+ tempPlayer->mMaxMp = msg.readInt16();
+ msg.readInt16(); // speed
+ msg.readInt16(); // class
+ int hairStyle = msg.readInt16();
+ Uint16 weapon = msg.readInt16();
+ tempPlayer->setSprite(Being::WEAPON_SPRITE, weapon);
+ tempPlayer->setLevel(msg.readInt16());
+ msg.readInt16(); // skill point
+ tempPlayer->setSprite(Being::BOTTOMCLOTHES_SPRITE, msg.readInt16()); // head bottom
+ tempPlayer->setSprite(Being::SHIELD_SPRITE, msg.readInt16());
+ tempPlayer->setSprite(Being::HAT_SPRITE, msg.readInt16()); // head option top
+ tempPlayer->setSprite(Being::TOPCLOTHES_SPRITE, msg.readInt16()); // head option mid
+ int hairColor = msg.readInt16();
+ tempPlayer->setHairStyle(hairStyle, hairColor);
+ tempPlayer->setSprite(Being::MISC2_SPRITE, msg.readInt16());
+ tempPlayer->setName(msg.readString(24));
+ for (int i = 0; i < 6; i++) {
+ tempPlayer->mAttr[i] = msg.readInt8();
+ }
+ slot = msg.readInt8(); // character slot
+ msg.readInt8(); // unknown
+
+ return tempPlayer;
+}
diff --git a/src/net/ea/charserverhandler.h b/src/net/ea/charserverhandler.h
new file mode 100644
index 00000000..237f5e49
--- /dev/null
+++ b/src/net/ea/charserverhandler.h
@@ -0,0 +1,65 @@
+/*
+ * 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
+ */
+
+#ifndef NET_CHARSERVERHANDLER_H
+#define NET_CHARSERVERHANDLER_H
+
+#include "../messagehandler.h"
+
+#include "../../lockedarray.h"
+
+class CharCreateDialog;
+class LocalPlayer;
+class LoginData;
+
+/**
+ * Deals with incoming messages from the character server.
+ */
+class CharServerHandler : public MessageHandler
+{
+ public:
+ CharServerHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void setCharInfo(LockedArray<LocalPlayer*> *charInfo)
+ { mCharInfo = charInfo; }
+
+ void setLoginData(LoginData *loginData)
+ { mLoginData = loginData; }
+
+ /**
+ * Sets the character create dialog. The handler will clean up this
+ * dialog when a new character is succesfully created, and will unlock
+ * the dialog when a new character failed to be created.
+ */
+ void setCharCreateDialog(CharCreateDialog *window)
+ { mCharCreateDialog = window; }
+
+ protected:
+ LoginData *mLoginData;
+ LockedArray<LocalPlayer*> *mCharInfo;
+ CharCreateDialog *mCharCreateDialog;
+
+ LocalPlayer* readPlayerData(MessageIn &msg, int &slot);
+};
+
+#endif
diff --git a/src/net/ea/chathandler.cpp b/src/net/ea/chathandler.cpp
new file mode 100644
index 00000000..0293f987
--- /dev/null
+++ b/src/net/ea/chathandler.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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 <SDL_types.h>
+#include <string>
+
+#include "chathandler.h"
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../being.h"
+#include "../../beingmanager.h"
+#include "../../game.h"
+#include "../../player_relations.h"
+
+#include "../../gui/chat.h"
+
+#include "../../utils/gettext.h"
+#include "../../utils/stringutils.h"
+
+extern Being *player_node;
+
+#define SERVER_NAME "Server"
+
+ChatHandler::ChatHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_BEING_CHAT,
+ SMSG_PLAYER_CHAT,
+ SMSG_WHISPER,
+ SMSG_WHISPER_RESPONSE,
+ SMSG_GM_CHAT,
+ SMSG_WHO_ANSWER,
+ 0x10c, // MVP
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void ChatHandler::handleMessage(MessageIn &msg)
+{
+ Being *being;
+ std::string chatMsg;
+ std::string nick;
+ Sint16 chatMsgLength;
+
+ switch (msg.getId())
+ {
+ case SMSG_WHISPER_RESPONSE:
+ switch (msg.readInt8())
+ {
+ case 0x00:
+ // comment out since we'll local echo in chat.cpp instead, then only report failures
+ //chatWindow->chatLog("Whisper sent", BY_SERVER);
+ break;
+ case 0x01:
+ 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);
+ break;
+ }
+ break;
+
+ // Received whisper
+ case SMSG_WHISPER:
+ chatMsgLength = msg.readInt16() - 28;
+ nick = msg.readString(24);
+
+ if (chatMsgLength <= 0)
+ break;
+
+ chatMsg = msg.readString(chatMsgLength);
+ if (nick != SERVER_NAME)
+ chatMsg = nick + " : " + chatMsg;
+
+ if (nick == SERVER_NAME)
+ chatWindow->chatLog(chatMsg, BY_SERVER);
+ else {
+ if (player_relations.hasPermission(nick, PlayerRelation::WHISPER))
+ chatWindow->chatLog(chatMsg, ACT_WHISPER);
+ }
+
+ break;
+
+ // Received speech from being
+ case SMSG_BEING_CHAT: {
+ chatMsgLength = msg.readInt16() - 8;
+ being = beingManager->findBeing(msg.readInt32());
+
+ if (!being || chatMsgLength <= 0)
+ {
+ break;
+ }
+
+ chatMsg = msg.readString(chatMsgLength);
+
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+ std::string sender_name = ((pos == std::string::npos)
+ ? ""
+ : chatMsg.substr(0, pos));
+
+ // We use getIgnorePlayer instead of ignoringPlayer here because ignorePlayer' side
+ // effects are triggered right below for Being::IGNORE_SPEECH_FLOAT.
+ if (player_relations.checkPermissionSilently(sender_name, PlayerRelation::SPEECH_LOG))
+ chatWindow->chatLog(chatMsg, BY_OTHER);
+
+ chatMsg.erase(0, pos + 3);
+ trim(chatMsg);
+
+ if (player_relations.hasPermission(sender_name, PlayerRelation::SPEECH_FLOAT))
+ being->setSpeech(chatMsg, SPEECH_TIME);
+ break;
+ }
+
+ case SMSG_PLAYER_CHAT:
+ case SMSG_GM_CHAT: {
+ chatMsgLength = msg.readInt16() - 4;
+
+ if (chatMsgLength <= 0)
+ {
+ break;
+ }
+
+ chatMsg = msg.readString(chatMsgLength);
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+
+ if (msg.getId() == SMSG_PLAYER_CHAT)
+ {
+ chatWindow->chatLog(chatMsg, BY_PLAYER);
+
+ if (pos != std::string::npos)
+ chatMsg.erase(0, pos + 3);
+
+ trim(chatMsg);
+
+ player_node->setSpeech(chatMsg, SPEECH_TIME);
+ }
+ else
+ {
+ chatWindow->chatLog(chatMsg, BY_GM);
+ }
+ break;
+ }
+
+ case SMSG_WHO_ANSWER:
+ chatWindow->chatLog("Online users: " + toString(msg.readInt32()),
+ BY_SERVER);
+ break;
+
+ case 0x010c:
+ // Display MVP player
+ msg.readInt32(); // id
+ chatWindow->chatLog("MVP player", BY_SERVER);
+ break;
+ }
+}
diff --git a/src/gui/hbox.h b/src/net/ea/chathandler.h
index 4b241383..8207b1d5 100644
--- a/src/gui/hbox.h
+++ b/src/net/ea/chathandler.h
@@ -1,33 +1,35 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef HBOX_H
-#define HBOX_H
+#ifndef NET_CHATHANDLER_H
+#define NET_CHATHANDLER_H
-#include "box.h"
+#include "../messagehandler.h"
-class HBox : public Box
+class ChatHandler : public MessageHandler
{
- public:
- void draw(gcn::Graphics *);
+ public:
+ ChatHandler();
+
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/ea/equipmenthandler.cpp b/src/net/ea/equipmenthandler.cpp
new file mode 100644
index 00000000..19063daf
--- /dev/null
+++ b/src/net/ea/equipmenthandler.cpp
@@ -0,0 +1,190 @@
+/*
+ * 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 "equipmenthandler.h"
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../equipment.h"
+#include "../../inventory.h"
+#include "../../item.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+
+#include "../../gui/chat.h"
+
+#include "../../utils/gettext.h"
+
+EquipmentHandler::EquipmentHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_PLAYER_EQUIPMENT,
+ SMSG_PLAYER_EQUIP,
+ SMSG_PLAYER_UNEQUIP,
+ SMSG_PLAYER_ARROW_EQUIP,
+ SMSG_PLAYER_ATTACK_RANGE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void EquipmentHandler::handleMessage(MessageIn &msg)
+{
+ Sint32 itemCount;
+ Sint16 index, equipPoint, itemId;
+ Sint8 type;
+ int mask, position;
+ Item *item;
+ Inventory *inventory = player_node->getInventory();
+
+ switch (msg.getId())
+ {
+ case SMSG_PLAYER_EQUIPMENT:
+ msg.readInt16(); // length
+ itemCount = (msg.getLength() - 4) / 20;
+
+ for (int loop = 0; loop < itemCount; loop++)
+ {
+ index = msg.readInt16();
+ itemId = msg.readInt16();
+ msg.readInt8(); // type
+ msg.readInt8(); // identify flag
+ msg.readInt16(); // equip type
+ equipPoint = msg.readInt16();
+ msg.readInt8(); // attribute
+ msg.readInt8(); // refine
+ msg.skip(8); // card
+
+ inventory->setItem(index, itemId, 1, true);
+
+ if (equipPoint)
+ {
+ mask = 1;
+ position = 0;
+ while (!(equipPoint & mask))
+ {
+ mask <<= 1;
+ position++;
+ }
+ item = inventory->getItem(index);
+ player_node->mEquipment->setEquipment(position, index);
+ }
+ }
+ break;
+
+ case SMSG_PLAYER_EQUIP:
+ index = msg.readInt16();
+ equipPoint = msg.readInt16();
+ type = msg.readInt8();
+
+ logger->log("Equipping: %i %i %i", index, equipPoint, type);
+
+ if (!type) {
+ chatWindow->chatLog(_("Unable to equip."), BY_SERVER);
+ break;
+ }
+
+ if (!equipPoint) {
+ // No point given, no point in searching
+ break;
+ }
+
+ /*
+ * 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)) {
+ mask <<= 1;
+ position++;
+ }
+ logger->log("Position %i", position);
+
+ item = player_node->getInventory()->getItem(player_node->mEquipment->getEquipment(position));
+
+ // Unequip any existing equipped item in this position
+ if (item) {
+ item->setEquipped(false);
+ }
+
+ item = inventory->getItem(index);
+ player_node->mEquipment->setEquipment(position, index);
+ break;
+
+ case SMSG_PLAYER_UNEQUIP:
+ index = msg.readInt16();
+ equipPoint = msg.readInt16();
+ type = msg.readInt8();
+
+ if (!type) {
+ chatWindow->chatLog(_("Unable to unequip."), BY_SERVER);
+ break;
+ }
+
+ if (!equipPoint) {
+ // No point given, no point in searching
+ break;
+ }
+
+ mask = 1;
+ position = 0;
+ while (!(equipPoint & mask)) {
+ mask <<= 1;
+ position++;
+ }
+
+ item = inventory->getItem(index);
+ if (!item)
+ break;
+
+ item->setEquipped(false);
+
+ 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);
+ break;
+
+ case SMSG_PLAYER_ATTACK_RANGE:
+ player_node->setAttackRange(msg.readInt16());
+ break;
+
+ case SMSG_PLAYER_ARROW_EQUIP:
+ index = msg.readInt16();
+
+ if (index <= 1)
+ break;
+
+ item = inventory->getItem(index);
+
+ if (item) {
+ item->setEquipped(true);
+ player_node->mEquipment->setArrows(index);
+ logger->log("Arrows equipped: %i", index);
+ }
+ break;
+ }
+}
diff --git a/src/net/ea/equipmenthandler.h b/src/net/ea/equipmenthandler.h
new file mode 100644
index 00000000..fe4a7ecc
--- /dev/null
+++ b/src/net/ea/equipmenthandler.h
@@ -0,0 +1,35 @@
+/*
+ * 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
+ */
+
+#ifndef NET_EQUIPMENTHANDLER_H
+#define NET_EQUIPMENTHANDLER_H
+
+#include "../messagehandler.h"
+
+class EquipmentHandler : public MessageHandler
+{
+ public:
+ EquipmentHandler();
+
+ void handleMessage(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/ea/inventoryhandler.cpp b/src/net/ea/inventoryhandler.cpp
new file mode 100644
index 00000000..71eee291
--- /dev/null
+++ b/src/net/ea/inventoryhandler.cpp
@@ -0,0 +1,227 @@
+/*
+ * 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 <SDL_types.h>
+
+#include "inventoryhandler.h"
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../inventory.h"
+#include "../../item.h"
+#include "../../itemshortcut.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+
+#include "../../gui/chat.h"
+
+#include "../../resources/iteminfo.h"
+
+#include "../../utils/gettext.h"
+#include "../../utils/strprintf.h"
+#include "../../utils/stringutils.h"
+
+InventoryHandler::InventoryHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_PLAYER_INVENTORY,
+ SMSG_PLAYER_INVENTORY_ADD,
+ 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;
+}
+
+void InventoryHandler::handleMessage(MessageIn &msg)
+{
+ Sint32 number;
+ 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:
+ 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++) {
+ index = msg.readInt16();
+ itemId = msg.readInt16();
+ 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;
+
+ case SMSG_PLAYER_INVENTORY_ADD:
+ index = msg.readInt16();
+ amount = msg.readInt16();
+ itemId = msg.readInt16();
+ identified = msg.readInt8();
+ msg.readInt8(); // attribute
+ msg.readInt8(); // refine
+ for (int i = 0; i < 4; i++)
+ cards[i] = msg.readInt16();
+ equipType = msg.readInt16();
+ itemType = msg.readInt8();
+
+ if (msg.readInt8() > 0) {
+ 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(strprintf(_("You picked up %s %s"),
+ amountStr.c_str(), itemInfo.getName().c_str()), BY_SERVER);
+
+ if (Item *item = inventory->getItem(index)) {
+ item->setId(itemId);
+ item->increaseQuantity(amount);
+ } else {
+ inventory->setItem(index, itemId, amount, equipType != 0);
+ }
+ }
+ break;
+
+ case SMSG_PLAYER_INVENTORY_REMOVE:
+ index = msg.readInt16();
+ amount = msg.readInt16();
+ if (Item *item = inventory->getItem(index)) {
+ item->increaseQuantity(-amount);
+ if (item->getQuantity() == 0)
+ inventory->removeItemAt(index);
+ }
+ break;
+
+ case SMSG_PLAYER_INVENTORY_USE:
+ index = msg.readInt16();
+ msg.readInt16(); // item id
+ msg.readInt32(); // id
+ amount = msg.readInt16();
+ msg.readInt8(); // type
+
+ if (Item *item = inventory->getItem(index))
+ item->setQuantity(amount);
+ break;
+
+ case SMSG_ITEM_USE_RESPONSE:
+ index = msg.readInt16();
+ amount = msg.readInt16();
+
+ if (msg.readInt8() == 0) {
+ 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/ea/inventoryhandler.h b/src/net/ea/inventoryhandler.h
new file mode 100644
index 00000000..b2e469fa
--- /dev/null
+++ b/src/net/ea/inventoryhandler.h
@@ -0,0 +1,35 @@
+/*
+ * 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
+ */
+
+#ifndef NET_INVENTORYHANDLER_H
+#define NET_INVENTORYHANDLER_H
+
+#include "../messagehandler.h"
+
+class InventoryHandler : public MessageHandler
+{
+ public:
+ InventoryHandler();
+
+ void handleMessage(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/ea/loginhandler.cpp b/src/net/ea/loginhandler.cpp
new file mode 100644
index 00000000..3f58f2c0
--- /dev/null
+++ b/src/net/ea/loginhandler.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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 "loginhandler.h"
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../log.h"
+#include "../../logindata.h"
+#include "../../main.h"
+#include "../../serverinfo.h"
+
+#include "../../utils/gettext.h"
+#include "../../utils/strprintf.h"
+#include "../../utils/stringutils.h"
+
+extern SERVER_INFO **server_info;
+
+LoginHandler::LoginHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_CONNECTION_PROBLEM,
+ SMSG_UPDATE_HOST,
+ 0x0069,
+ 0x006a,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void LoginHandler::handleMessage(MessageIn &msg)
+{
+ int code;
+
+ 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 = _("No servers available");
+ break;
+ case 2:
+ errorMessage = _("This account is already logged in");
+ break;
+ default:
+ errorMessage = _("Unknown connection error");
+ break;
+ }
+ state = STATE_ERROR;
+ break;
+
+ case SMSG_UPDATE_HOST:
+ int len;
+
+ len = msg.readInt16() - 4;
+ mUpdateHost = msg.readString(len);
+
+ logger->log("Received update host \"%s\" from login server",
+ mUpdateHost.c_str());
+ break;
+
+ case 0x0069:
+ // Skip the length word
+ msg.skip(2);
+
+ n_server = (msg.getLength() - 47) / 32;
+ server_info =
+ (SERVER_INFO**) malloc(sizeof(SERVER_INFO*) * n_server);
+
+ mLoginData->session_ID1 = msg.readInt32();
+ mLoginData->account_ID = msg.readInt32();
+ mLoginData->session_ID2 = msg.readInt32();
+ msg.skip(30); // unknown
+ mLoginData->sex = msg.readInt8();
+
+ for (int i = 0; i < n_server; i++)
+ {
+ server_info[i] = new SERVER_INFO;
+
+ server_info[i]->address = msg.readInt32();
+ server_info[i]->port = msg.readInt16();
+ server_info[i]->name = msg.readString(20);
+ server_info[i]->online_users = msg.readInt32();
+ server_info[i]->updateHost = mUpdateHost;
+ msg.skip(2); // unknown
+
+ logger->log("Network: Server: %s (%s:%d)",
+ server_info[i]->name.c_str(),
+ ipToString(server_info[i]->address),
+ server_info[i]->port);
+ }
+ state = STATE_CHAR_SERVER;
+ break;
+
+ case 0x006a:
+ code = msg.readInt8();
+ logger->log("Login::error code: %i", code);
+
+ switch (code) {
+ case 0:
+ errorMessage = _("Unregistered ID");
+ break;
+ case 1:
+ errorMessage = _("Wrong password");
+ break;
+ case 2:
+ errorMessage = _("Account expired");
+ break;
+ case 3:
+ errorMessage = _("Rejected from server");
+ break;
+ case 4:
+
+ errorMessage = _("You have been permanently banned from "
+ "the game. Please contact the GM Team.");
+ break;
+ case 6:
+ 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");
+ break;
+ default:
+ errorMessage = _("Unknown error");
+ break;
+ }
+ state = STATE_ERROR;
+ break;
+ }
+}
diff --git a/src/net/ea/loginhandler.h b/src/net/ea/loginhandler.h
new file mode 100644
index 00000000..c2ba5083
--- /dev/null
+++ b/src/net/ea/loginhandler.h
@@ -0,0 +1,45 @@
+/*
+ * 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
+ */
+
+#ifndef NET_LOGINHANDLER_H
+#define NET_LOGINHANDLER_H
+
+#include <string>
+
+#include "../messagehandler.h"
+
+struct LoginData;
+
+class LoginHandler : public MessageHandler
+{
+ public:
+ LoginHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void setLoginData(LoginData *loginData) { mLoginData = loginData; };
+
+ private:
+ LoginData *mLoginData;
+ std::string mUpdateHost;
+};
+
+#endif
diff --git a/src/net/ea/maploginhandler.cpp b/src/net/ea/maploginhandler.cpp
new file mode 100644
index 00000000..6931024e
--- /dev/null
+++ b/src/net/ea/maploginhandler.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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 "maploginhandler.h"
+#include "../messagein.h"
+#include "protocol.h"
+
+#include "../../localplayer.h"
+#include "../../log.h"
+#include "../../main.h"
+
+#include "../../utils/gettext.h"
+
+MapLoginHandler::MapLoginHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_CONNECTION_PROBLEM,
+ SMSG_LOGIN_SUCCESS,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+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 = STATE_ERROR;
+ break;
+
+ case SMSG_LOGIN_SUCCESS:
+ msg.readInt32(); // server tick
+ msg.readCoordinates(player_node->mX, player_node->mY, direction);
+ msg.skip(2); // unknown
+ logger->log("Protocol: Player start position: (%d, %d), Direction: %d",
+ player_node->mX, player_node->mY, direction);
+ state = STATE_GAME;
+ break;
+ }
+}
diff --git a/src/net/ea/maploginhandler.h b/src/net/ea/maploginhandler.h
new file mode 100644
index 00000000..1ce5ee79
--- /dev/null
+++ b/src/net/ea/maploginhandler.h
@@ -0,0 +1,35 @@
+/*
+ * 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
+ */
+
+#ifndef NET_MAPLOGINHANDLER_H
+#define NET_MAPLOGINHANDLER_H
+
+#include "../messagehandler.h"
+
+class MapLoginHandler : public MessageHandler
+{
+ public:
+ MapLoginHandler();
+
+ void handleMessage(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/ea/network.cpp b/src/net/ea/network.cpp
new file mode 100644
index 00000000..199e94da
--- /dev/null
+++ b/src/net/ea/network.cpp
@@ -0,0 +1,436 @@
+/*
+ * 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 <sstream>
+
+#include "../messagehandler.h"
+#include "../messagein.h"
+#include "network.h"
+
+#include "../../log.h"
+#include "../../utils/stringutils.h"
+
+/** Warning: buffers and other variables are shared,
+ so there can be only one connection active at a time */
+
+short packet_lengths[] = {
+ 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// #0x0040
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, -1, 55, 17, 3, 37, 46, -1, 23, -1, 3,108, 3, 2,
+ 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6,
+// #0x0080
+ 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0,
+ 7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6,
+ 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6,
+ 8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3,
+// #0x00C0
+ 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27,
+ 3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1,
+ 30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2,
+ 3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10,
+// #0x0100
+ 2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1,
+ 10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16,
+ 6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1,
+ 6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26,
+// #0x0140
+ 22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6,
+ 110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42,
+ -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182,
+ 14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1,
+// #0x0180
+ 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6,
+ 90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, 4, 6, 2, 6,
+ 3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4,
+ 11, 7, -1, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3,
+// #0x01C0
+ 2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 0, 9, 9, 29, 6, 28,
+ 8, 14, 10, 35, 6, 8, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6,
+ 30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1,
+ -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10,
+// #0x200
+ 26, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+const unsigned int BUFFER_SIZE = 65536;
+
+int networkThread(void *data)
+{
+ Network *network = static_cast<Network*>(data);
+
+ if (!network->realConnect())
+ return -1;
+
+ network->receive();
+
+ return 0;
+}
+
+Network::Network():
+ mSocket(0),
+ mAddress(), mPort(0),
+ mInBuffer(new char[BUFFER_SIZE]),
+ mOutBuffer(new char[BUFFER_SIZE]),
+ mInSize(0), mOutSize(0),
+ mToSkip(0),
+ mState(IDLE),
+ mWorkerThread(0)
+{
+ mMutex = SDL_CreateMutex();
+}
+
+Network::~Network()
+{
+ clearHandlers();
+
+ if (mState != IDLE && mState != NET_ERROR)
+ disconnect();
+
+ SDL_DestroyMutex(mMutex);
+
+ delete[] mInBuffer;
+ delete[] mOutBuffer;
+}
+
+bool Network::connect(const std::string &address, short port)
+{
+ if (mState != IDLE && mState != NET_ERROR)
+ {
+ logger->log("Tried to connect an already connected socket!");
+ return false;
+ }
+
+ if (address.empty())
+ {
+ setError("Empty address given to Network::connect()!");
+ return false;
+ }
+
+ logger->log("Network::Connecting to %s:%i", address.c_str(), port);
+
+ mAddress = address;
+ mPort = port;
+
+ // Reset to sane values
+ mOutSize = 0;
+ mInSize = 0;
+ mToSkip = 0;
+
+ mState = CONNECTING;
+ mWorkerThread = SDL_CreateThread(networkThread, this);
+ if (!mWorkerThread)
+ {
+ setError("Unable to create network worker thread");
+ return false;
+ }
+
+ return true;
+}
+
+void Network::disconnect()
+{
+ mState = IDLE;
+
+ if (mWorkerThread)
+ {
+ SDL_WaitThread(mWorkerThread, NULL);
+ mWorkerThread = NULL;
+ }
+
+ if (mSocket)
+ {
+ SDLNet_TCP_Close(mSocket);
+ mSocket = 0;
+ }
+}
+
+void Network::registerHandler(MessageHandler *handler)
+{
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
+ {
+ mMessageHandlers[*i] = handler;
+ }
+
+ handler->setNetwork(this);
+}
+
+void Network::unregisterHandler(MessageHandler *handler)
+{
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
+ {
+ mMessageHandlers.erase(*i);
+ }
+
+ handler->setNetwork(0);
+}
+
+void Network::clearHandlers()
+{
+ MessageHandlerIterator i;
+ for (i = mMessageHandlers.begin(); i != mMessageHandlers.end(); i++)
+ {
+ i->second->setNetwork(0);
+ }
+ mMessageHandlers.clear();
+}
+
+void Network::dispatchMessages()
+{
+ while (messageReady())
+ {
+ MessageIn msg = getNextMessage();
+
+ MessageHandlerIterator iter = mMessageHandlers.find(msg.getId());
+
+ if (iter != mMessageHandlers.end())
+ iter->second->handleMessage(msg);
+ else
+ logger->log("Unhandled packet: %x", msg.getId());
+
+ skip(msg.getLength());
+ }
+}
+
+void Network::flush()
+{
+ if (!mOutSize || mState != CONNECTED)
+ return;
+
+ int ret;
+
+
+ SDL_mutexP(mMutex);
+ ret = SDLNet_TCP_Send(mSocket, mOutBuffer, mOutSize);
+ if (ret < (int)mOutSize)
+ {
+ setError("Error in SDLNet_TCP_Send(): " +
+ std::string(SDLNet_GetError()));
+ }
+ mOutSize = 0;
+ SDL_mutexV(mMutex);
+}
+
+void Network::skip(int len)
+{
+ SDL_mutexP(mMutex);
+ mToSkip += len;
+ if (!mInSize)
+ {
+ SDL_mutexV(mMutex);
+ return;
+ }
+
+ if (mInSize >= mToSkip)
+ {
+ mInSize -= mToSkip;
+ memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
+ mToSkip = 0;
+ }
+ else
+ {
+ mToSkip -= mInSize;
+ mInSize = 0;
+ }
+ SDL_mutexV(mMutex);
+}
+
+bool Network::messageReady()
+{
+ int len = -1;
+
+ SDL_mutexP(mMutex);
+ if (mInSize >= 2)
+ {
+ len = packet_lengths[readWord(0)];
+
+ if (len == -1 && mInSize > 4)
+ len = readWord(2);
+
+ }
+
+ bool ret = (mInSize >= static_cast<unsigned int>(len));
+ SDL_mutexV(mMutex);
+
+ return ret;
+}
+
+MessageIn Network::getNextMessage()
+{
+ while (!messageReady())
+ {
+ if (mState == NET_ERROR)
+ break;
+ }
+
+ SDL_mutexP(mMutex);
+ int msgId = readWord(0);
+ int len = packet_lengths[msgId];
+
+ if (len == -1)
+ len = readWord(2);
+
+#ifdef DEBUG
+ logger->log("Received packet 0x%x of length %d", msgId, len);
+#endif
+
+ MessageIn msg(mInBuffer, len);
+ SDL_mutexV(mMutex);
+
+ return msg;
+}
+
+bool Network::realConnect()
+{
+ IPaddress ipAddress;
+
+ if (SDLNet_ResolveHost(&ipAddress, mAddress.c_str(), mPort) == -1)
+ {
+ std::string error = "Unable to resolve host \"" + mAddress + "\"";
+ setError(error);
+ logger->log("SDLNet_ResolveHost: %s", error.c_str());
+ return false;
+ }
+
+ mState = CONNECTING;
+
+ mSocket = SDLNet_TCP_Open(&ipAddress);
+ if (!mSocket)
+ {
+ logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError());
+ setError(SDLNet_GetError());
+ return false;
+ }
+
+ logger->log("Network::Started session with %s:%i",
+ ipToString(ipAddress.host), ipAddress.port);
+
+ mState = CONNECTED;
+
+ return true;
+}
+
+void Network::receive()
+{
+ SDLNet_SocketSet set;
+
+ if (!(set = SDLNet_AllocSocketSet(1)))
+ {
+ setError("Error in SDLNet_AllocSocketSet(): " +
+ std::string(SDLNet_GetError()));
+ return;
+ }
+
+ if (SDLNet_TCP_AddSocket(set, mSocket) == -1)
+ {
+ setError("Error in SDLNet_AddSocket(): " +
+ std::string(SDLNet_GetError()));
+ }
+
+ while (mState == CONNECTED)
+ {
+ // TODO Try to get this to block all the time while still being able
+ // to escape the loop
+ int numReady = SDLNet_CheckSockets(set, ((Uint32)500));
+ int ret;
+ switch (numReady)
+ {
+ case -1:
+ logger->log("Error: SDLNet_CheckSockets");
+ // FALLTHROUGH
+ case 0:
+ break;
+
+ case 1:
+ // Receive data from the socket
+ SDL_mutexP(mMutex);
+ ret = SDLNet_TCP_Recv(mSocket, mInBuffer + mInSize, BUFFER_SIZE - mInSize);
+
+ if (!ret)
+ {
+ // We got disconnected
+ mState = IDLE;
+ logger->log("Disconnected.");
+ }
+ else if (ret < 0)
+ {
+ setError("Error in SDLNet_TCP_Recv(): " +
+ std::string(SDLNet_GetError()));
+ }
+ else {
+ mInSize += ret;
+ if (mToSkip)
+ {
+ if (mInSize >= mToSkip)
+ {
+ mInSize -= mToSkip;
+ memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
+ mToSkip = 0;
+ }
+ else
+ {
+ mToSkip -= mInSize;
+ mInSize = 0;
+ }
+ }
+ }
+ SDL_mutexV(mMutex);
+ break;
+
+ default:
+ // more than one socket is ready..
+ // this should not happen since we only listen once socket.
+ std::stringstream errorStream;
+ errorStream << "Error in SDLNet_TCP_Recv(), " << numReady
+ << " sockets are ready: " << SDLNet_GetError();
+ setError(errorStream.str());
+ break;
+ }
+ }
+
+ if (SDLNet_TCP_DelSocket(set, mSocket) == -1)
+ {
+ logger->log("Error in SDLNet_DelSocket(): %s", SDLNet_GetError());
+ }
+
+ SDLNet_FreeSocketSet(set);
+}
+
+void Network::setError(const std::string& error)
+{
+ logger->log("Network error: %s", error.c_str());
+ mError = error;
+ mState = NET_ERROR;
+}
+
+Uint16 Network::readWord(int pos)
+{
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ return SDL_Swap16((*(Uint16*)(mInBuffer+(pos))));
+#else
+ return (*(Uint16*)(mInBuffer+(pos)));
+#endif
+}
diff --git a/src/net/ea/network.h b/src/net/ea/network.h
new file mode 100644
index 00000000..02fe7538
--- /dev/null
+++ b/src/net/ea/network.h
@@ -0,0 +1,118 @@
+/*
+ * 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
+ */
+
+#ifndef NETWORK_
+#define NETWORK_
+
+#include <map>
+#include <SDL_net.h>
+#include <SDL_thread.h>
+#include <string>
+
+/**
+ * Protocol version, reported to the eAthena char and mapserver who can adjust
+ * the protocol accordingly.
+ */
+#define CLIENT_PROTOCOL_VERSION 1
+
+class MessageHandler;
+class MessageIn;
+
+class Network;
+
+class Network
+{
+ public:
+ friend int networkThread(void *data);
+ friend class MessageOut;
+
+ Network();
+
+ ~Network();
+
+ bool connect(const std::string &address, short port);
+
+ void disconnect();
+
+ void registerHandler(MessageHandler *handler);
+
+ void unregisterHandler(MessageHandler *handler);
+
+ void clearHandlers();
+
+ int getState() const { return mState; }
+
+ const std::string& getError() const { return mError; }
+
+ bool isConnected() const { return mState == CONNECTED; }
+
+ int getInSize() const { return mInSize; }
+
+ void skip(int len);
+
+ bool messageReady();
+
+ MessageIn getNextMessage();
+
+ void dispatchMessages();
+
+ void flush();
+
+ // ERROR replaced by NET_ERROR because already defined in Windows
+ enum {
+ IDLE,
+ CONNECTED,
+ CONNECTING,
+ DATA,
+ NET_ERROR
+ };
+
+ protected:
+ void setError(const std::string& error);
+
+ Uint16 readWord(int pos);
+
+ bool realConnect();
+
+ void receive();
+
+ TCPsocket mSocket;
+
+ std::string mAddress;
+ short mPort;
+
+ char *mInBuffer, *mOutBuffer;
+ unsigned int mInSize, mOutSize;
+
+ unsigned int mToSkip;
+
+ int mState;
+ std::string mError;
+
+ SDL_Thread *mWorkerThread;
+ SDL_mutex *mMutex;
+
+ typedef std::map<Uint16, MessageHandler*> MessageHandlers;
+ typedef MessageHandlers::iterator MessageHandlerIterator;
+ MessageHandlers mMessageHandlers;
+};
+
+#endif
diff --git a/src/net/ea/npchandler.cpp b/src/net/ea/npchandler.cpp
new file mode 100644
index 00000000..068a3be6
--- /dev/null
+++ b/src/net/ea/npchandler.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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 "../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"
+
+extern NpcIntegerDialog *npcIntegerDialog;
+extern NpcListDialog *npcListDialog;
+extern NpcTextDialog *npcTextDialog;
+extern NpcStringDialog *npcStringDialog;
+
+NPCHandler::NPCHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_NPC_CHOICE,
+ SMSG_NPC_MESSAGE,
+ SMSG_NPC_NEXT,
+ SMSG_NPC_CLOSE,
+ SMSG_NPC_INT_INPUT,
+ SMSG_NPC_STR_INPUT,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void NPCHandler::handleMessage(MessageIn &msg)
+{
+ int id;
+
+ switch (msg.getId())
+ {
+ 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);
+ break;
+
+ 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:
+ id = msg.readInt32();
+ current_npc = dynamic_cast<NPC*>(beingManager->findBeing(id));
+ npcTextDialog->showCloseButton();
+ break;
+
+ case SMSG_NPC_NEXT:
+ // Next button in NPC dialog, currently unused
+ id = msg.readInt32();
+ current_npc = dynamic_cast<NPC*>(beingManager->findBeing(id));
+ npcTextDialog->showNextButton();
+ break;
+
+ case SMSG_NPC_INT_INPUT:
+ // Request for an integer
+ id = msg.readInt32();
+ current_npc = dynamic_cast<NPC*>(beingManager->findBeing(id));
+ npcIntegerDialog->setRange(0, 2147483647);
+ npcIntegerDialog->setDefaultValue(0);
+ npcIntegerDialog->setVisible(true);
+ npcIntegerDialog->requestFocus();
+ break;
+
+ case SMSG_NPC_STR_INPUT:
+ // Request for a string
+ id = msg.readInt32();
+ current_npc = dynamic_cast<NPC*>(beingManager->findBeing(id));
+ npcStringDialog->setValue("");
+ npcStringDialog->setVisible(true);
+ npcStringDialog->requestFocus();
+ break;
+ }
+}
diff --git a/src/gui/vbox.h b/src/net/ea/npchandler.h
index 2072ab24..49df20c3 100644
--- a/src/gui/vbox.h
+++ b/src/net/ea/npchandler.h
@@ -1,33 +1,35 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef VBOX_H
-#define VBOX_H
+#ifndef NET_NPCHANDLER_H
+#define NET_NPCHANDLER_H
-#include "box.h"
+#include "../messagehandler.h"
-class VBox : public Box
+class NPCHandler : public MessageHandler
{
public:
- void draw(gcn::Graphics *);
+ NPCHandler();
+
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/ea/partyhandler.cpp b/src/net/ea/partyhandler.cpp
new file mode 100644
index 00000000..d1d3b55e
--- /dev/null
+++ b/src/net/ea/partyhandler.cpp
@@ -0,0 +1,122 @@
+/*
+ * The Mana World
+ * 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 <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/ea/partyhandler.h b/src/net/ea/partyhandler.h
new file mode 100644
index 00000000..5c10eb21
--- /dev/null
+++ b/src/net/ea/partyhandler.h
@@ -0,0 +1,39 @@
+/*
+ * The Mana World
+ * 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 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/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp
new file mode 100644
index 00000000..9f0acbb3
--- /dev/null
+++ b/src/net/ea/playerhandler.cpp
@@ -0,0 +1,417 @@
+/*
+ * 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 "../messagein.h"
+#include "playerhandler.h"
+#include "protocol.h"
+
+#include "../../engine.h"
+#include "../../localplayer.h"
+#include "../../log.h"
+#include "../../npc.h"
+#include "../../units.h"
+
+#include "../../gui/buy.h"
+#include "../../gui/chat.h"
+#include "../../gui/gui.h"
+#include "../../gui/npclistdialog.h"
+#include "../../gui/npc_text.h"
+#include "../../gui/ok_dialog.h"
+#include "../../gui/sell.h"
+#include "../../gui/skill.h"
+#include "../../gui/viewport.h"
+
+#include "../../utils/stringutils.h"
+#include "../../utils/gettext.h"
+
+// TODO Move somewhere else
+OkDialog *weightNotice = NULL;
+OkDialog *deathNotice = NULL;
+
+extern NpcListDialog *npcListDialog;
+extern NpcTextDialog *npcTextDialog;
+extern BuyDialog *buyDialog;
+extern SellDialog *sellDialog;
+extern Window *buySellDialog;
+
+// Max. distance we are willing to scroll after a teleport;
+// everything beyond will reset the port hard.
+static const int MAP_TELEPORT_SCROLL_DISTANCE = 8;
+
+/**
+ * Listener used for handling the overweigth message.
+ */
+// TODO Move somewhere else
+namespace {
+ struct WeightListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event)
+ {
+ weightNotice = NULL;
+ }
+ } weightListener;
+}
+
+/**
+ * Listener used for handling death message.
+ */
+// TODO Move somewhere else
+namespace {
+ struct DeathListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event)
+ {
+ player_node->revive();
+ deathNotice = NULL;
+ npcListDialog->setVisible(false);
+ npcTextDialog->setVisible(false);
+ buyDialog->setVisible(false);
+ sellDialog->setVisible(false);
+ buySellDialog->setVisible(false);
+ if (current_npc) current_npc->handleDeath();
+ }
+ } deathListener;
+}
+
+PlayerHandler::PlayerHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_WALK_RESPONSE,
+ SMSG_PLAYER_WARP,
+ SMSG_PLAYER_STAT_UPDATE_1,
+ SMSG_PLAYER_STAT_UPDATE_2,
+ SMSG_PLAYER_STAT_UPDATE_3,
+ SMSG_PLAYER_STAT_UPDATE_4,
+ SMSG_PLAYER_STAT_UPDATE_5,
+ SMSG_PLAYER_STAT_UPDATE_6,
+ SMSG_PLAYER_ARROW_MESSAGE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void PlayerHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case SMSG_WALK_RESPONSE:
+ /*
+ * This client assumes that all walk messages succeed,
+ * and that the server will send a correction notice
+ * otherwise.
+ */
+ break;
+
+ case SMSG_PLAYER_WARP:
+ {
+ std::string mapPath = msg.readString(16);
+ bool nearby;
+ Uint16 x = msg.readInt16();
+ Uint16 y = msg.readInt16();
+
+ logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y);
+
+ /*
+ * We must clear the local player's target *before* the call
+ * to changeMap, as it deletes all beings.
+ */
+ player_node->stopAttack();
+
+ nearby = (engine->getCurrentMapName() == mapPath);
+
+ // Switch the actual map, deleting the previous one if necessary
+ engine->changeMap(mapPath);
+
+ if (current_npc) current_npc->handleDeath();
+
+ float scrollOffsetX = 0.0f;
+ float scrollOffsetY = 0.0f;
+
+ /* Scroll if neccessary */
+ if (!nearby
+ || (abs(x - player_node->mX) > 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;
+ }
+
+ player_node->setAction(Being::STAND);
+ player_node->mFrame = 0;
+ player_node->mX = x;
+ player_node->mY = y;
+
+ logger->log("Adjust scrolling by %d:%d",
+ (int)scrollOffsetX,
+ (int)scrollOffsetY);
+
+ viewport->scrollBy(scrollOffsetX, scrollOffsetY);
+ }
+ break;
+
+ case SMSG_PLAYER_STAT_UPDATE_1:
+ {
+ Sint16 type = msg.readInt16();
+ Uint32 value = msg.readInt32();
+
+ switch (type)
+ {
+ //case 0x0000:
+ // player_node->setWalkSpeed(msg.readInt32());
+ // break;
+ case 0x0005: player_node->setHp(value); break;
+ case 0x0006: player_node->setMaxHp(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->setLevel(value); break;
+ case 0x000c:
+ player_node->mSkillPoint = value;
+ skillDialog->update();
+ break;
+ case 0x0018:
+ if ((int) value >= player_node->getMaxWeight() / 2 &&
+ player_node->getTotalWeight() <
+ player_node->getMaxWeight() / 2)
+ {
+ weightNotice = new OkDialog(_("Message"),
+ _("You are carrying more than "
+ "half your weight. You are "
+ "unable to regain health."));
+ weightNotice->addActionListener(
+ &weightListener);
+ }
+ player_node->setTotalWeight(value);
+ break;
+ case 0x0019: player_node->setMaxWeight(value); break;
+ case 0x0029: player_node->ATK = value; break;
+ case 0x002b: player_node->MATK = value; break;
+ case 0x002d: player_node->DEF = value; break;
+ case 0x002e: player_node->DEF_BONUS = value; break;
+ case 0x002f: player_node->MDEF = value; break;
+ 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->getHp() == 0 && !deathNotice)
+ {
+ 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."),
+ // NetHack reference:
+ _("Do you want your possessions identified?"),
+ // Secret of Mana reference:
+ _("Sadly, no trace of you was ever found..."),
+ // Final Fantasy VI reference:
+ _("Annihilated."),
+ // Earthbound reference:
+ _("Looks like you got your head handed to you."),
+ // Leisure Suit Larry 1 reference:
+ _("You screwed up again, dump your body down the tubes "
+ "and get you another one."),
+ // Monty Python references (Dead Parrot sketch mostly):
+ _("You're not dead yet. You're just resting."),
+ _("You are no more."),
+ _("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.")
+ };
+ std::string message(deadMsg[rand()%27]);
+
+ deathNotice = new OkDialog(_("Message"), message);
+ deathNotice->addActionListener(&deathListener);
+ player_node->setAction(Being::DEAD);
+ }
+ }
+ break;
+
+ case SMSG_PLAYER_STAT_UPDATE_2:
+ switch (msg.readInt16()) {
+ case 0x0001:
+ player_node->setXp(msg.readInt32());
+ break;
+ case 0x0002:
+ player_node->mJobXp = msg.readInt32();
+ break;
+ case 0x0014: {
+ int curGp = player_node->getMoney();
+ player_node->setMoney(msg.readInt32());
+ if (player_node->getMoney() > curGp)
+ chatWindow->chatLog(_("You picked up ") +
+ Units::formatCurrency(player_node->getMoney()
+ - curGp), BY_SERVER);
+ }
+ break;
+ case 0x0016:
+ player_node->mXpForNextLevel = msg.readInt32();
+ break;
+ case 0x0017:
+ player_node->mJobXpForNextLevel = msg.readInt32();
+ break;
+ }
+ break;
+
+ case SMSG_PLAYER_STAT_UPDATE_3:
+ {
+ Sint32 type = msg.readInt32();
+ Sint32 base = msg.readInt32();
+ Sint32 bonus = msg.readInt32();
+ Sint32 total = base + bonus;
+
+ switch (type) {
+ case 0x000d: player_node->mAttr[LocalPlayer::STR] = total;
+ break;
+ case 0x000e: player_node->mAttr[LocalPlayer::AGI] = total;
+ break;
+ case 0x000f: player_node->mAttr[LocalPlayer::VIT] = total;
+ break;
+ case 0x0010: player_node->mAttr[LocalPlayer::INT] = total;
+ break;
+ case 0x0011: player_node->mAttr[LocalPlayer::DEX] = total;
+ break;
+ case 0x0012: player_node->mAttr[LocalPlayer::LUK] = total;
+ break;
+ }
+ }
+ break;
+
+ case SMSG_PLAYER_STAT_UPDATE_4:
+ {
+ Sint16 type = msg.readInt16();
+ Sint8 fail = msg.readInt8();
+ Sint8 value = msg.readInt8();
+
+ if (fail != 1)
+ break;
+
+ switch (type) {
+ case 0x000d: player_node->mAttr[LocalPlayer::STR] = value;
+ break;
+ case 0x000e: player_node->mAttr[LocalPlayer::AGI] = value;
+ break;
+ case 0x000f: player_node->mAttr[LocalPlayer::VIT] = value;
+ break;
+ case 0x0010: player_node->mAttr[LocalPlayer::INT] = value;
+ break;
+ case 0x0011: player_node->mAttr[LocalPlayer::DEX] = value;
+ break;
+ case 0x0012: player_node->mAttr[LocalPlayer::LUK] = value;
+ break;
+ }
+ }
+ break;
+
+ // Updates stats and status points
+ case SMSG_PLAYER_STAT_UPDATE_5:
+ player_node->mStatsPointsToAttribute = msg.readInt16();
+ player_node->mAttr[LocalPlayer::STR] = msg.readInt8();
+ player_node->mAttrUp[LocalPlayer::STR] = msg.readInt8();
+ player_node->mAttr[LocalPlayer::AGI] = msg.readInt8();
+ player_node->mAttrUp[LocalPlayer::AGI] = msg.readInt8();
+ player_node->mAttr[LocalPlayer::VIT] = msg.readInt8();
+ player_node->mAttrUp[LocalPlayer::VIT] = msg.readInt8();
+ player_node->mAttr[LocalPlayer::INT] = msg.readInt8();
+ player_node->mAttrUp[LocalPlayer::INT] = msg.readInt8();
+ player_node->mAttr[LocalPlayer::DEX] = msg.readInt8();
+ player_node->mAttrUp[LocalPlayer::DEX] = msg.readInt8();
+ player_node->mAttr[LocalPlayer::LUK] = msg.readInt8();
+ player_node->mAttrUp[LocalPlayer::LUK] = msg.readInt8();
+ player_node->ATK = msg.readInt16(); // ATK
+ player_node->ATK_BONUS = msg.readInt16(); // ATK bonus
+ player_node->MATK = msg.readInt16(); // MATK max
+ player_node->MATK_BONUS = msg.readInt16(); // MATK min
+ player_node->DEF = msg.readInt16(); // DEF
+ player_node->DEF_BONUS = msg.readInt16(); // DEF bonus
+ player_node->MDEF = msg.readInt16(); // MDEF
+ player_node->MDEF_BONUS = msg.readInt16(); // MDEF bonus
+ player_node->HIT = msg.readInt16(); // HIT
+ player_node->FLEE = msg.readInt16(); // FLEE
+ player_node->FLEE_BONUS = msg.readInt16(); // FLEE bonus
+ msg.readInt16(); // critical
+ msg.readInt16(); // unknown
+ break;
+
+ case SMSG_PLAYER_STAT_UPDATE_6:
+ switch (msg.readInt16()) {
+ case 0x0020:
+ player_node->mAttrUp[LocalPlayer::STR] = msg.readInt8();
+ break;
+ case 0x0021:
+ player_node->mAttrUp[LocalPlayer::AGI] = msg.readInt8();
+ break;
+ case 0x0022:
+ player_node->mAttrUp[LocalPlayer::VIT] = msg.readInt8();
+ break;
+ case 0x0023:
+ player_node->mAttrUp[LocalPlayer::INT] = msg.readInt8();
+ break;
+ case 0x0024:
+ player_node->mAttrUp[LocalPlayer::DEX] = msg.readInt8();
+ break;
+ case 0x0025:
+ player_node->mAttrUp[LocalPlayer::LUK] = msg.readInt8();
+ break;
+ }
+ break;
+
+ case SMSG_PLAYER_ARROW_MESSAGE:
+ {
+ Sint16 type = msg.readInt16();
+
+ switch (type) {
+ case 0:
+ chatWindow->chatLog(_("Equip arrows first"),
+ BY_SERVER);
+ break;
+ default:
+ logger->log("0x013b: Unhandled message %i", type);
+ break;
+ }
+ }
+ break;
+ }
+}
diff --git a/src/gui/box.cpp b/src/net/ea/playerhandler.h
index 59d8c135..f3352289 100644
--- a/src/gui/box.cpp
+++ b/src/net/ea/playerhandler.h
@@ -1,42 +1,35 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "box.h"
+#ifndef NET_PLAYERHANDLER_H
+#define NET_PLAYERHANDLER_H
-Box::Box():
- padding(0)
-{
- setOpaque(false);
-}
+#include "../messagehandler.h"
-Box::~Box()
+class PlayerHandler : public MessageHandler
{
-}
+ public:
+ PlayerHandler();
-unsigned int Box::getPadding()
-{
- return padding;
-}
+ void handleMessage(MessageIn &msg);
+};
-void Box::setPadding(unsigned int p)
-{
- padding = p;
-}
+#endif
diff --git a/src/net/ea/protocol.cpp b/src/net/ea/protocol.cpp
new file mode 100644
index 00000000..69d69901
--- /dev/null
+++ b/src/net/ea/protocol.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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 "protocol.h"
+
+#define LOBYTE(w) ((unsigned char)(w))
+#define HIBYTE(w) ((unsigned char)(((unsigned short)(w)) >> 8))
+
+void set_coordinates(char *data,
+ unsigned short x,
+ unsigned short y,
+ unsigned char direction)
+{
+ short temp;
+ temp = x;
+ temp <<= 6;
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 2;
+ data[0] = HIBYTE(temp);
+ data[1] = (unsigned char)(temp);
+ temp = y;
+ temp <<= 4;
+ data[1] |= HIBYTE(temp);
+ data[2] = LOBYTE(temp);
+
+ // Translate direction to eAthena format
+ switch (direction)
+ {
+ case 1:
+ direction = 0;
+ break;
+ case 3:
+ direction = 1;
+ break;
+ case 2:
+ direction = 2;
+ break;
+ case 6:
+ direction = 3;
+ break;
+ case 4:
+ direction = 4;
+ break;
+ case 12:
+ direction = 5;
+ break;
+ case 8:
+ direction = 6;
+ break;
+ case 9:
+ direction = 7;
+ break;
+ default:
+ // OOPSIE! Impossible or unknown
+ direction = (unsigned char)-1;
+ }
+ data[2] |= direction;
+}
diff --git a/src/net/ea/protocol.h b/src/net/ea/protocol.h
new file mode 100644
index 00000000..55c0d8b6
--- /dev/null
+++ b/src/net/ea/protocol.h
@@ -0,0 +1,162 @@
+/*
+ * 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
+ */
+
+#ifndef PROTOCOL_H
+#define PROTOCOL_H
+
+/*********************************
+ * 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
+#define SMSG_PLAYER_MOVE 0x01da /**< A nearby player moves */
+#define SMSG_PLAYER_STOP 0x0088 /**< Stop walking, set position */
+#define SMSG_PLAYER_MOVE_TO_ATTACK 0x0139 /**< Move to within attack range */
+#define SMSG_PLAYER_STAT_UPDATE_1 0x00b0
+#define SMSG_PLAYER_STAT_UPDATE_2 0x00b1
+#define SMSG_PLAYER_STAT_UPDATE_3 0x0141
+#define SMSG_PLAYER_STAT_UPDATE_4 0x00bc
+#define SMSG_PLAYER_STAT_UPDATE_5 0x00bd
+#define SMSG_PLAYER_STAT_UPDATE_6 0x00be
+#define SMSG_WHO_ANSWER 0x00c2
+#define SMSG_PLAYER_WARP 0x0091 /**< Warp player to map/location */
+#define SMSG_PLAYER_INVENTORY 0x01ee
+#define SMSG_PLAYER_INVENTORY_ADD 0x00a0
+#define SMSG_PLAYER_INVENTORY_REMOVE 0x00af
+#define SMSG_PLAYER_INVENTORY_USE 0x01c8
+#define SMSG_PLAYER_EQUIPMENT 0x00a4
+#define SMSG_PLAYER_EQUIP 0x00aa
+#define SMSG_PLAYER_UNEQUIP 0x00ac
+#define SMSG_PLAYER_ATTACK_RANGE 0x013a
+#define SMSG_PLAYER_ARROW_EQUIP 0x013c
+#define SMSG_PLAYER_ARROW_MESSAGE 0x013b
+#define SMSG_PLAYER_SKILLS 0x010f
+#define SMSG_SKILL_FAILED 0x0110
+#define SMSG_ITEM_USE_RESPONSE 0x00a8
+#define SMSG_ITEM_VISIBLE 0x009d /**< An item is on the floor */
+#define SMSG_ITEM_DROPPED 0x009e /**< An item is dropped */
+#define SMSG_ITEM_REMOVE 0x00a1 /**< An item disappers */
+#define SMSG_BEING_VISIBLE 0x0078
+#define SMSG_BEING_MOVE 0x007b /**< A nearby monster moves */
+#define SMSG_BEING_SPAWN 0x007c /**< A being spawns nearby */
+#define SMSG_BEING_MOVE2 0x0086 /**< New eAthena being moves */
+#define SMSG_BEING_REMOVE 0x0080
+#define SMSG_BEING_CHANGE_LOOKS 0x00c3
+#define SMSG_BEING_CHANGE_LOOKS2 0x01d7 /**< Same as 0x00c3, but 16 bit ID */
+#define SMSG_BEING_SELFEFFECT 0x019b
+#define SMSG_BEING_EMOTION 0x00c0
+#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
+#define SMSG_NPC_CHOICE 0x00b7 /**< Display a choice */
+#define SMSG_NPC_BUY_SELL_CHOICE 0x00c4
+#define SMSG_NPC_BUY 0x00c6
+#define SMSG_NPC_SELL 0x00c7
+#define SMSG_NPC_BUY_RESPONSE 0x00ca
+#define SMSG_NPC_SELL_RESPONSE 0x00cb
+#define SMSG_NPC_INT_INPUT 0x0142 /**< Integer input */
+#define SMSG_NPC_STR_INPUT 0x01d4 /**< String input */
+#define SMSG_PLAYER_CHAT 0x008e /**< Player talks */
+#define SMSG_WHISPER 0x0097 /**< Whisper Recieved */
+#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
+#define SMSG_TRADE_ITEM_ADD_RESPONSE 0x01b1 /**< Not standard eAthena! */
+#define SMSG_TRADE_OK 0x00ec
+#define SMSG_TRADE_CANCEL 0x00ee
+#define SMSG_TRADE_COMPLETE 0x00f0
+
+#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
+#define CMSG_MAP_LOADED 0x007d
+#define CMSG_NPC_BUY_REQUEST 0x00c8
+#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
+#define CMSG_NPC_INT_RESPONSE 0x0143
+#define CMSG_NPC_STR_RESPONSE 0x01d5
+#define CMSG_SKILL_LEVELUP_REQUEST 0x0112
+#define CMSG_STAT_UPDATE_REQUEST 0x00bb
+#define CMSG_TRADE_ITEM_ADD_REQUEST 0x00e8
+#define CMSG_TRADE_CANCEL_REQUEST 0x00ed
+#define CMSG_TRADE_ADD_COMPLETE 0x00eb
+#define CMSG_TRADE_OK 0x00ef
+#define CMSG_NPC_TALK 0x0090
+#define CMSG_TRADE_REQUEST 0x00e4
+#define CMSG_PLAYER_INVENTORY_USE 0x00a7
+#define CMSG_PLAYER_INVENTORY_DROP 0x00a2
+#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);
+
+#endif
diff --git a/src/net/ea/skillhandler.cpp b/src/net/ea/skillhandler.cpp
new file mode 100644
index 00000000..6e766008
--- /dev/null
+++ b/src/net/ea/skillhandler.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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 "../messagein.h"
+#include "protocol.h"
+#include "skillhandler.h"
+
+#include "../../log.h"
+
+#include "../../gui/chat.h"
+#include "../../gui/skill.h"
+
+SkillHandler::SkillHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_PLAYER_SKILLS,
+ SMSG_SKILL_FAILED,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void SkillHandler::handleMessage(MessageIn &msg)
+{
+ int skillCount;
+
+ switch (msg.getId())
+ {
+ case SMSG_PLAYER_SKILLS:
+ msg.readInt16(); // length
+ skillCount = (msg.getLength() - 4) / 37;
+ skillDialog->cleanList();
+
+ for (int k = 0; k < skillCount; k++)
+ {
+ Sint16 skillId = msg.readInt16();
+ msg.readInt16(); // target type
+ msg.readInt16(); // unknown
+ Sint16 level = msg.readInt16();
+ Sint16 sp = msg.readInt16();
+ msg.readInt16(); // range
+ std::string skillName = msg.readString(24);
+ Sint8 up = msg.readInt8();
+
+ if (level != 0 || up != 0)
+ {
+ if (skillDialog->hasSkill(skillId)) {
+ skillDialog->setSkill(skillId, level, sp);
+ }
+ else {
+ skillDialog->addSkill(skillId, level, sp);
+ }
+ }
+ }
+ skillDialog->update();
+ break;
+
+ case SMSG_SKILL_FAILED:
+ // Action failed (ex. sit because you have not reached the
+ // right level)
+ CHATSKILL action;
+ action.skill = msg.readInt16();
+ action.bskill = msg.readInt16();
+ action.unused = msg.readInt16(); // unknown
+ action.success = msg.readInt8();
+ action.reason = msg.readInt8();
+ if (action.success != SKILL_FAILED &&
+ action.bskill == BSKILL_EMOTE)
+ {
+ logger->log("Action: %d/%d", action.bskill, action.success);
+ }
+ chatWindow->chatLog(action);
+ break;
+ }
+}
diff --git a/src/utils/tostring.h b/src/net/ea/skillhandler.h
index d2dd941a..57d68f47 100644
--- a/src/utils/tostring.h
+++ b/src/net/ea/skillhandler.h
@@ -1,35 +1,35 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_UTILS_TOSTRING_H
-#define _TMW_UTILS_TOSTRING_H
+#ifndef NET_SKILLHANDLER_H
+#define NET_SKILLHANDLER_H
-#include <sstream>
+#include "../messagehandler.h"
-template<typename T>
-std::string toString(const T &arg)
+class SkillHandler : public MessageHandler
{
- std::stringstream ss;
- ss << arg;
- return ss.str();
-}
+ public:
+ SkillHandler();
+
+ void handleMessage(MessageIn &msg);
+};
#endif
diff --git a/src/net/ea/tradehandler.cpp b/src/net/ea/tradehandler.cpp
new file mode 100644
index 00000000..6c953a11
--- /dev/null
+++ b/src/net/ea/tradehandler.cpp
@@ -0,0 +1,220 @@
+/*
+ * 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 "../messagein.h"
+#include "protocol.h"
+#include "tradehandler.h"
+
+#include "../../inventory.h"
+#include "../../item.h"
+#include "../../localplayer.h"
+#include "../../player_relations.h"
+
+#include "../../gui/chat.h"
+#include "../../gui/confirm_dialog.h"
+#include "../../gui/trade.h"
+
+#include "../../utils/gettext.h"
+
+std::string tradePartnerName;
+
+/**
+ * Listener for request trade dialogs
+ */
+namespace {
+ struct RequestTradeListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event)
+ {
+ player_node->tradeReply(event.getId() == "yes");
+ };
+ } listener;
+}
+
+TradeHandler::TradeHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_TRADE_REQUEST,
+ SMSG_TRADE_RESPONSE,
+ SMSG_TRADE_ITEM_ADD,
+ SMSG_TRADE_ITEM_ADD_RESPONSE,
+ SMSG_TRADE_OK,
+ SMSG_TRADE_CANCEL,
+ SMSG_TRADE_COMPLETE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+
+void TradeHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case SMSG_TRADE_REQUEST:
+ // If a trade window or request window is already open, send a
+ // trade cancel to any other trade request.
+ //
+ // Note that it would be nice if the server would prevent this
+ // situation, and that the requesting player would get a
+ // special message about the player being occupied.
+ tradePartnerName = msg.readString(24);
+
+ if (player_relations.hasPermission(tradePartnerName, PlayerRelation::TRADE))
+ {
+ if (!player_node->tradeRequestOk())
+ {
+ player_node->tradeReply(false);
+ break;
+ }
+
+ player_node->setTrading(true);
+ ConfirmDialog *dlg;
+ dlg = new ConfirmDialog(_("Request for trade"),
+ tradePartnerName +
+ _(" wants to trade with you, do you accept?"));
+ dlg->addActionListener(&listener);
+ }
+ else
+ {
+ player_node->tradeReply(false);
+ break;
+ }
+ break;
+
+ case SMSG_TRADE_RESPONSE:
+ switch (msg.readInt8())
+ {
+ case 0: // 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."),
+ BY_SERVER);
+ break;
+ case 2: // Invite request check failed...
+ chatWindow->chatLog(_("Trade cancelled due to an unknown reason."),
+ BY_SERVER);
+ break;
+ case 3: // Trade accepted
+ tradeWindow->reset();
+ tradeWindow->setCaption(
+ _("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);
+ // 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"),
+ BY_SERVER);
+ break;
+ }
+ break;
+
+ case SMSG_TRADE_ITEM_ADD:
+ {
+ Sint32 amount = msg.readInt32();
+ Sint16 type = msg.readInt16();
+ msg.readInt8(); // identified flag
+ msg.readInt8(); // attribute
+ msg.readInt8(); // refine
+ msg.skip(8); // card (4 shorts)
+
+ // TODO: handle also identified, etc
+ if (type == 0) {
+ tradeWindow->setMoney(amount);
+ } else {
+ tradeWindow->addItem(type, false, amount, false);
+ }
+ }
+ break;
+
+ case SMSG_TRADE_ITEM_ADD_RESPONSE:
+ // Trade: New Item add response (was 0x00ea, now 01b1)
+ {
+ const int index = msg.readInt16();
+ Item *item = player_node->getInventory()->getItem(index);
+ if (!item)
+ {
+ tradeWindow->receivedOk(true);
+ return;
+ }
+ Sint16 quantity = msg.readInt16();
+
+ switch (msg.readInt8())
+ {
+ case 0:
+ // Successfully added item
+ if (item->isEquipment() && item->isEquipped())
+ {
+ player_node->unequipItem(item);
+ }
+ tradeWindow->addItem(item->getId(), true, quantity,
+ item->isEquipment());
+ item->increaseQuantity(-quantity);
+ break;
+ case 1:
+ // Add item failed - player overweighted
+ 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;
+ default:
+ chatWindow->chatLog(_("Failed adding item for unknown reason."),
+ BY_SERVER);
+ break;
+ }
+ }
+ break;
+
+ case SMSG_TRADE_OK:
+ // 0 means ok from myself, 1 means ok from other;
+ tradeWindow->receivedOk(msg.readInt8() == 0);
+ break;
+
+ case SMSG_TRADE_CANCEL:
+ 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);
+ tradeWindow->setVisible(false);
+ tradeWindow->reset();
+ player_node->setTrading(false);
+ break;
+ }
+}
diff --git a/src/net/ea/tradehandler.h b/src/net/ea/tradehandler.h
new file mode 100644
index 00000000..04335069
--- /dev/null
+++ b/src/net/ea/tradehandler.h
@@ -0,0 +1,37 @@
+/*
+ * 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
+ */
+
+#ifndef NET_TRADEHANDLER_H
+#define NET_TRADEHANDLER_H
+
+#include "../messagehandler.h"
+
+class Network;
+
+class TradeHandler : public MessageHandler
+{
+ public:
+ TradeHandler();
+
+ void handleMessage(MessageIn &msg);
+};
+
+#endif
diff --git a/src/net/effecthandler.cpp b/src/net/effecthandler.cpp
index f7ff2bf2..8411b9e7 100644
--- a/src/net/effecthandler.cpp
+++ b/src/net/effecthandler.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/net/inventoryhandler.h b/src/net/inventoryhandler.h
index 1326ea71..9b457abe 100644
--- a/src/net/inventoryhandler.h
+++ b/src/net/inventoryhandler.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NET_INVENTORYHANDLER_H
-#define _TMW_NET_INVENTORYHANDLER_H
+#ifndef NET_INVENTORYHANDLER_H
+#define NET_INVENTORYHANDLER_H
#include "messagehandler.h"
diff --git a/src/net/itemhandler.cpp b/src/net/itemhandler.cpp
index af06084f..189c6eb9 100644
--- a/src/net/itemhandler.cpp
+++ b/src/net/itemhandler.cpp
@@ -1,26 +1,25 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "itemhandler.h"
-
#include "messagein.h"
#include "protocol.h"
diff --git a/src/net/itemhandler.h b/src/net/itemhandler.h
index e3005a6f..12057bb1 100644
--- a/src/net/itemhandler.h
+++ b/src/net/itemhandler.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NET_ITEMHANDLER_H
-#define _TMW_NET_ITEMHANDLER_H
+#ifndef NET_ITEMHANDLER_H
+#define NET_ITEMHANDLER_H
#include "messagehandler.h"
diff --git a/src/net/messagehandler.cpp b/src/net/messagehandler.cpp
index 973c5555..a765d0e8 100644
--- a/src/net/messagehandler.cpp
+++ b/src/net/messagehandler.cpp
@@ -1,31 +1,54 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "messagehandler.h"
-
#include <cassert>
+#include "messagehandler.h"
+#ifdef TMWSERV_SUPPORT
#include "network.h"
+#else
+#include "ea/network.h"
+#endif
+
+MessageHandler::MessageHandler()
+#ifdef EATHENA_SUPPORT
+ : mNetwork(0)
+#endif
+{
+}
MessageHandler::~MessageHandler()
{
+#ifdef TMWSERV_SUPPORT
Net::unregisterHandler(this);
+#else
+ if (mNetwork)
+ mNetwork->unregisterHandler(this);
+#endif
+}
+
+#ifdef EATHENA_SUPPORT
+void MessageHandler::setNetwork(Network *network)
+{
+ assert(!(network && mNetwork));
+ mNetwork = network;
}
+#endif
diff --git a/src/net/messagehandler.h b/src/net/messagehandler.h
index 74226aa5..261a8351 100644
--- a/src/net/messagehandler.h
+++ b/src/net/messagehandler.h
@@ -1,30 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NET_MESSAGEHANDLER_H
-#define _TMW_NET_MESSAGEHANDLER_H
+#ifndef NET_MESSAGEHANDLER_H
+#define NET_MESSAGEHANDLER_H
#include <SDL_types.h>
class MessageIn;
+#ifdef EATHENA_SUPPORT
+class Network;
+#endif
/**
* \ingroup Network
@@ -34,9 +37,17 @@ class MessageHandler
public:
const Uint16 *handledMessages;
+ MessageHandler();
virtual ~MessageHandler();
virtual void handleMessage(MessageIn &msg) = 0;
+
+#ifdef EATHENA_SUPPORT
+ void setNetwork(Network *network);
+
+ protected:
+ Network *mNetwork;
+#endif
};
#endif
diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp
index 57c268e7..813b440f 100644
--- a/src/net/messagein.cpp
+++ b/src/net/messagein.cpp
@@ -1,29 +1,38 @@
/*
- * The Mana World Server
- * Copyright 2004 The Mana World Development Team
+ * The Mana World
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "messagein.h"
-#include <string>
-
+#ifdef TMWSERV_SUPPORT
#include <enet/enet.h>
+#else
+#include <SDL.h>
+#include <SDL_endian.h>
+#endif
+
+#include <cassert>
+
+#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),
@@ -50,9 +59,17 @@ int MessageIn::readInt16()
int value = -1;
if (mPos + 2 <= mLength)
{
+#ifdef TMWSERV_SUPPORT
uint16_t t;
memcpy(&t, mData + mPos, 2);
value = (unsigned short) ENET_NET_TO_HOST_16(t);
+#else
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ value = SDL_Swap16(*(Sint16*)(mData + mPos));
+#else
+ value = (*(Sint16*)(mData + mPos));
+#endif
+#endif // TMWSERV_SUPPORT
}
mPos += 2;
return value;
@@ -63,9 +80,17 @@ int MessageIn::readInt32()
int value = -1;
if (mPos + 4 <= mLength)
{
+#ifdef TMWSERV_SUPPORT
uint32_t t;
memcpy(&t, mData + mPos, 4);
value = ENET_NET_TO_HOST_32(t);
+#else
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ value = SDL_Swap32(*(Sint32*)(mData + mPos));
+#else
+ value = (*(Sint32*)(mData + mPos));
+#endif
+#endif // TMWSERV_SUPPORT
}
mPos += 4;
return value;
@@ -82,6 +107,83 @@ void MessageIn::readCoordinates(Uint16 &x, Uint16 &y)
mPos += 3;
}
+void MessageIn::readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction)
+{
+ assert(mPos + 3 <= mLength);
+
+ const char *data = mData + mPos;
+ Sint16 temp;
+
+ temp = MAKEWORD(data[1] & 0x00c0, data[0] & 0x00ff);
+ x = temp >> 6;
+ temp = MAKEWORD(data[2] & 0x00f0, data[1] & 0x003f);
+ y = temp >> 4;
+
+ direction = data[2] & 0x000f;
+
+ // Translate from eAthena format
+ switch (direction)
+ {
+ case 0:
+ direction = 1;
+ break;
+ case 1:
+ direction = 3;
+ break;
+ case 2:
+ direction = 2;
+ break;
+ case 3:
+ direction = 6;
+ break;
+ case 4:
+ direction = 4;
+ break;
+ case 5:
+ direction = 12;
+ break;
+ case 6:
+ direction = 8;
+ break;
+ case 7:
+ direction = 9;
+ break;
+ default:
+ // OOPSIE! Impossible or unknown
+ direction = 0;
+ }
+
+ mPos += 3;
+}
+
+void MessageIn::readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
+ Uint16 &dstX, Uint16 &dstY)
+{
+ assert(mPos + 5 <= mLength);
+
+ const char *data = mData + mPos;
+ Sint16 temp;
+
+ temp = MAKEWORD(data[3], data[2] & 0x000f);
+ dstX = temp >> 2;
+
+ dstY = MAKEWORD(data[4], data[3] & 0x0003);
+
+ temp = MAKEWORD(data[1], data[0]);
+ srcX = temp >> 6;
+
+ temp = MAKEWORD(data[2], data[1] & 0x003f);
+ srcY = temp >> 4;
+
+ mPos += 5;
+}
+
+void MessageIn::skip(unsigned int length)
+{
+ assert(mPos + length <= mLength);
+ mPos += length;
+}
+
std::string MessageIn::readString(int length)
{
// Get string length
@@ -89,16 +191,17 @@ std::string MessageIn::readString(int length)
length = readInt16();
}
- // Make sure the string isn't erroneus
+ // Make sure the string isn't erroneous
if (length < 0 || mPos + length > mLength) {
mPos = mLength + 1;
return "";
}
// Read the string
- char const *stringBeg = mData + mPos,
- *stringEnd = (char const *)memchr(stringBeg, '\0', length);
- std::string readString(stringBeg, stringEnd ? stringEnd - stringBeg : length);
+ char const *stringBeg = mData + mPos;
+ char const *stringEnd = (char const *)memchr(stringBeg, '\0', length);
+ std::string readString(stringBeg,
+ stringEnd ? stringEnd - stringBeg : length);
mPos += length;
return readString;
}
diff --git a/src/net/messagein.h b/src/net/messagein.h
index f2390baa..0d0e9981 100644
--- a/src/net/messagein.h
+++ b/src/net/messagein.h
@@ -1,30 +1,29 @@
/*
- * The Mana World Server
- * Copyright 2004 The Mana World Development Team
+ * The Mana World
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMWSERV_MESSAGEIN_H_
-#define _TMWSERV_MESSAGEIN_H_
-
-#include <string>
+#ifndef MESSAGEIN_
+#define MESSAGEIN_
#include <SDL_types.h>
+#include <string>
/**
* Used for parsing an incoming message.
@@ -39,40 +38,60 @@ class MessageIn
*/
MessageIn(const char *data, unsigned int length);
- int getId() { return mId; } /**< Returns the message ID. */
+ /**
+ * Returns the message ID.
+ */
+ int getId() const { return mId; }
+
+ /**
+ * Returns the message length.
+ */
+ unsigned int getLength() const { return mLength; }
+
+ /**
+ * Returns the length of unread data.
+ */
+ unsigned int getUnreadLength() const { return mLength - mPos; }
int readInt8(); /**< Reads a byte. */
int readInt16(); /**< Reads a short. */
int readInt32(); /**< Reads a long. */
/**
- * Reads a 3-byte block containing tile-based coordinates.
+ * Reads a 3-byte block containing tile-based coordinates. Used by
+ * tmwserv.
*/
void readCoordinates(Uint16 &x, Uint16 &y);
/**
- * 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.
+ * Reads a special 3 byte block used by eAthena, containing x and y
+ * coordinates and direction.
*/
- std::string readString(int length = -1);
+ void readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction);
/**
- * Returns the message length.
+ * Reads a special 5 byte block used by eAthena, containing a source
+ * and destination coordinate pair.
*/
- unsigned int
- getLength() const { return mLength; }
+ void readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
+ Uint16 &dstX, Uint16 &dstY);
/**
- * Returns the length of unread data.
+ * Skips a given number of bytes.
*/
- unsigned int
- getUnreadLength() const { return mLength - mPos; }
+ 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);
private:
const char* mData; /**< The message data. */
unsigned int mLength; /**< The length of the data. */
- unsigned short mId; /**< The message ID. */
+ unsigned short mId; /**< The message ID. */
/**
* Actual position in the packet. From 0 to packet->length.
diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp
index b08332b6..f7ab6b41 100644
--- a/src/net/messageout.cpp
+++ b/src/net/messageout.cpp
@@ -1,80 +1,113 @@
/*
- * The Mana World Server
- * Copyright 2004 The Mana World Development Team
+ * The Mana World
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <cstring>
-#include <string>
+#include "messageout.h"
+#ifdef TMWSERV_SUPPORT
#include <enet/enet.h>
+#else
+#include "ea/network.h"
+#include <SDL.h>
+#include <SDL_endian.h>
+#endif
-#include "messageout.h"
+#include <cstring>
+#include <string>
+#ifdef TMWSERV_SUPPORT
MessageOut::MessageOut(short id):
mData(0),
+#else
+MessageOut::MessageOut(Network *network):
+ mNetwork(network),
+#endif
mDataSize(0),
mPos(0)
{
+#ifdef TMWSERV_SUPPORT
writeInt16(id);
+#else
+ mData = mNetwork->mOutBuffer + mNetwork->mOutSize;
+#endif
}
+#ifdef TMWSERV_SUPPORT
MessageOut::~MessageOut()
{
- if (mData) {
- free(mData);
- }
+ free(mData);
}
-void
-MessageOut::expand(size_t bytes)
+void MessageOut::expand(size_t bytes)
{
mData = (char*)realloc(mData, bytes);
mDataSize = bytes;
}
+#endif
-void
-MessageOut::writeInt8(char value)
+void MessageOut::writeInt8(Sint8 value)
{
+#ifdef TMWSERV_SUPPORT
expand(mPos + 1);
+#else
+ mNetwork->mOutSize += 1;
+#endif
mData[mPos] = value;
mPos += 1;
}
-void MessageOut::writeInt16(short value)
+void MessageOut::writeInt16(Sint16 value)
{
+#ifdef TMWSERV_SUPPORT
expand(mPos + 2);
uint16_t t = ENET_HOST_TO_NET_16(value);
memcpy(mData + mPos, &t, 2);
+#else
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ (*(Sint16 *)(mData + mPos)) = SDL_Swap16(value);
+#else
+ (*(Sint16 *)(mData + mPos)) = value;
+#endif
+ mNetwork->mOutSize += 2;
+#endif // TMWSERV_SUPPORT
mPos += 2;
}
-void
-MessageOut::writeInt32(long value)
+void MessageOut::writeInt32(Sint32 value)
{
+#ifdef TMWSERV_SUPPORT
expand(mPos + 4);
uint32_t t = ENET_HOST_TO_NET_32(value);
memcpy(mData + mPos, &t, 4);
+#else
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ (*(Sint32 *)(mData + mPos)) = SDL_Swap32(value);
+#else
+ (*(Sint32 *)(mData + mPos)) = value;
+#endif
+ mNetwork->mOutSize += 4;
+#endif // TMWSERV_SUPPORT
mPos += 4;
}
-void
-MessageOut::writeString(const std::string &string, int length)
+void MessageOut::writeString(const std::string &string, int length)
{
int stringLength = string.length();
if (length < 0)
@@ -88,7 +121,11 @@ MessageOut::writeString(const std::string &string, int length)
// Make sure the length of the string is no longer than specified
stringLength = length;
}
+#ifdef TMWSERV_SUPPORT
expand(mPos + length);
+#else
+ mNetwork->mOutSize += length;
+#endif
// Write the actual string
memcpy(mData + mPos, string.c_str(), stringLength);
@@ -101,14 +138,12 @@ MessageOut::writeString(const std::string &string, int length)
mPos += length;
}
-char*
-MessageOut::getData() const
+char *MessageOut::getData() const
{
return mData;
}
-unsigned int
-MessageOut::getDataSize() const
+unsigned int MessageOut::getDataSize() const
{
return mDataSize;
}
diff --git a/src/net/messageout.h b/src/net/messageout.h
index 4eadda5f..bc701b92 100644
--- a/src/net/messageout.h
+++ b/src/net/messageout.h
@@ -1,32 +1,39 @@
/*
- * The Mana World Server
- * Copyright 2004 The Mana World Development Team
+ * The Mana World
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMWSERV_MESSAGEOUT_H_
-#define _TMWSERV_MESSAGEOUT_H_
+#ifndef MESSAGEOUT_
+#define MESSAGEOUT_
#include <iosfwd>
+#include <SDL_types.h>
+
+#ifdef EATHENA_SUPPORT
+class Network;
+#endif
/**
- * Used for building an outgoing message. When finished, the message is sent
- * using Net::Connection::send().
+ * Used for building an outgoing message.
+ *
+ * With tmwserv, the message is sent using Net::Connection::send() when
+ * finished.
*
* \ingroup Network
*/
@@ -36,16 +43,20 @@ class MessageOut
/**
* Constructor.
*/
+#ifdef TMWSERV_SUPPORT
MessageOut(short id);
/**
* Destructor.
*/
~MessageOut();
+#else
+ MessageOut(Network *network);
+#endif
- void writeInt8(char value); /**< Writes a byte. */
- void writeInt16(short value); /**< Writes a short. */
- void writeInt32(long value); /**< Writes a long. */
+ void writeInt8(Sint8 value); /**< Writes a byte. */
+ void writeInt16(Sint16 value); /**< Writes a short. */
+ void writeInt32(Sint32 value); /**< Writes a long. */
/**
* Writes a string. If a fixed length is not given (-1), it is stored
@@ -64,6 +75,7 @@ class MessageOut
unsigned int getDataSize() const;
private:
+#ifdef TMWSERV_SUPPORT
/**
* Expand the packet data to be able to hold more data.
*
@@ -72,6 +84,9 @@ class MessageOut
* added.
*/
void expand(size_t size);
+#else
+ Network *mNetwork;
+#endif
char *mData; /**< Data building up. */
unsigned int mDataSize; /**< Size of data. */
diff --git a/src/net/npchandler.h b/src/net/npchandler.h
index 5560787e..18ab0a05 100644
--- a/src/net/npchandler.h
+++ b/src/net/npchandler.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NET_NPCHANDLER_H
-#define _TMW_NET_NPCHANDLER_H
+#ifndef NET_NPCHANDLER_H
+#define NET_NPCHANDLER_H
#include "messagehandler.h"
diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp
index beb59250..b4e2f328 100644
--- a/src/net/playerhandler.cpp
+++ b/src/net/playerhandler.cpp
@@ -134,8 +134,8 @@ void PlayerHandler::handleMessage(MessageIn &msg)
if (stat == BASE_ATTR_HP)
{
- player_node->setMaxHP(base);
- player_node->setHP(value);
+ player_node->setMaxHp(base);
+ player_node->setHp(value);
}
else if (stat < NB_CHARACTER_ATTRIBUTES)
{
diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h
index 9c5f87cc..fef767da 100644
--- a/src/net/playerhandler.h
+++ b/src/net/playerhandler.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NET_PLAYERHANDLER_H
-#define _TMW_NET_PLAYERHANDLER_H
+#ifndef NET_PLAYERHANDLER_H
+#define NET_PLAYERHANDLER_H
#include "messagehandler.h"
@@ -29,12 +29,10 @@ class PlayerHandler : public MessageHandler
public:
PlayerHandler();
- void
- handleMessage(MessageIn &msg);
+ void handleMessage(MessageIn &msg);
private:
- void
- handleMapChangeMessage(MessageIn &msg);
+ void handleMapChangeMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/tradehandler.h b/src/net/tradehandler.h
index 1a0fa695..6ffe17b5 100644
--- a/src/net/tradehandler.h
+++ b/src/net/tradehandler.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NET_TRADEHANDLER_H
-#define _TMW_NET_TRADEHANDLER_H
+#ifndef NET_TRADEHANDLER_H
+#define NET_TRADEHANDLER_H
#include "messagehandler.h"
diff --git a/src/npc.cpp b/src/npc.cpp
index 5665ad95..bc25fa5d 100644
--- a/src/npc.cpp
+++ b/src/npc.cpp
@@ -1,43 +1,59 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "npc.h"
-
#include "animatedsprite.h"
-#include "graphics.h"
+#include "npc.h"
#include "particle.h"
+#include "text.h"
-#include "gui/gui.h"
-#include "net/messageout.h"
+#include "gui/npc_text.h"
+
+#ifdef TMWSERV_SUPPORT
#include "net/gameserver/player.h"
+#else
+#include "net/messageout.h"
+#include "net/ea/protocol.h"
+#endif
+
#include "resources/npcdb.h"
+extern NpcTextDialog *npcTextDialog;
+
NPC *current_npc = 0;
-NPC::NPC(Uint16 id, int sprite, Map *map):
- Being(id, sprite, map)
+static const int NAME_X_OFFSET = 15;
+static const int NAME_Y_OFFSET = 30;
+
+#ifdef TMWSERV_SUPPORT
+NPC::NPC(Uint16 id, int job, Map *map):
+ Player(id, job, map)
+#else
+NPC::NPC(Uint32 id, Uint16 job, Map *map, Network *network):
+ Player(id, job, map),
+ mNetwork(network)
+#endif
{
- NPCInfo info = NPCDB::get(sprite);
+ NPCInfo info = NPCDB::get(job);
- //setup NPC sprites
+ // Setup NPC sprites
int c = BASE_SPRITE;
for (std::list<NPCsprite*>::const_iterator i = info.sprites.begin();
i != info.sprites.end();
@@ -51,74 +67,161 @@ NPC::NPC(Uint16 id, int sprite, Map *map):
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, 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;
}
-Being::Type
-NPC::getType() const
+NPC::~NPC()
{
- return Being::NPC;
+ delete mName;
+
+ if (current_npc == this) handleDeath();
+}
+
+void NPC::setName(const std::string &name)
+{
+ const std::string displayName = name.substr(0, name.find('#', 0));
+
+ delete mName;
+ 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::drawName(Graphics *graphics, Sint32 offsetX, Sint32 offsetY)
+void NPC::setGender(Gender gender)
{
- const Vector &pos = getPosition();
- const int px = (int) pos.x + offsetX;
- const int py = (int) pos.y + offsetY;
+ Being::setGender(gender);
+}
- graphics->setFont(speechFont);
- graphics->setColor(gcn::Color(200, 200, 255));
- graphics->drawText(mName, px, py, gcn::Graphics::CENTER);
+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
+{
+ return Being::NPC;
}
-void
-NPC::talk()
+void NPC::talk()
{
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::talkToNPC(mId, true);
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_NPC_TALK);
+ outMsg.writeInt32(mId);
+ outMsg.writeInt8(0);
+#endif
current_npc = this;
}
-void
-NPC::nextDialog()
+void NPC::nextDialog()
{
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::talkToNPC(mId, false);
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_NPC_NEXT_REQUEST);
+ outMsg.writeInt32(mId);
+#endif
}
-void
-NPC::dialogChoice(int choice)
+void NPC::dialogChoice(char choice)
{
+#ifdef TMWSERV_SUPPORT
Net::GameServer::Player::selectFromNPC(mId, choice);
+#else
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_NPC_LIST_CHOICE);
+ outMsg.writeInt32(mId);
+ outMsg.writeInt8(choice);
+#endif
+}
+
+void NPC::integerInput(int value)
+{
+#ifdef EATHENA_SUPPORT
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_NPC_INT_RESPONSE);
+ outMsg.writeInt32(mId);
+ outMsg.writeInt32(value);
+#endif
+}
+
+void NPC::stringInput(const std::string &value)
+{
+#ifdef EATHENA_SUPPORT
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_NPC_STR_RESPONSE);
+ outMsg.writeInt16(value.length() + 9);
+ outMsg.writeInt32(mId);
+ outMsg.writeString(value, value.length());
+ outMsg.writeInt8(0);
+#endif
}
/*
* TODO Unify the buy() and sell() methods, without sacrificing readability of
* the code calling the method. buy(bool buySell) would be bad...
*/
-void
-NPC::buy()
+void NPC::buy()
{
// XXX Convert for new server
- /*
- MessageOut outMsg(CMSG_NPC_BUY_SELL_REQUEST);
+#ifdef EATHENA_SUPPORT
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_NPC_BUY_SELL_REQUEST);
outMsg.writeInt32(mId);
outMsg.writeInt8(0);
- */
+#endif
}
-void
-NPC::sell()
+void NPC::sell()
{
// XXX Convert for new server
- /*
- MessageOut outMsg(CMSG_NPC_BUY_SELL_REQUEST);
+#ifdef EATHENA_SUPPORT
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_NPC_BUY_SELL_REQUEST);
outMsg.writeInt32(mId);
outMsg.writeInt8(1);
- */
+#endif
+}
+
+void NPC::updateCoords()
+{
+ if (mName)
+ {
+#ifdef TMWSERV_SUPPORT
+ const Vector &pos = getPosition();
+ const int px = (int) pos.x + NAME_X_OFFSET;
+ const int py = (int) pos.y + NAME_Y_OFFSET;
+#else
+ const int px = mPx + NAME_X_OFFSET;
+ const int py = mPy + NAME_Y_OFFSET;
+#endif
+ mName->adviseXY(px, py);
+ }
+}
+
+void NPC::handleDeath()
+{
+ printf("NPC::handleDeath\n");
+ if (this != current_npc) return;
+
+ if (npcTextDialog->isVisible())
+ npcTextDialog->showCloseButton();
+ else current_npc = NULL;
}
diff --git a/src/npc.h b/src/npc.h
index 60f9e6d8..b003b82e 100644
--- a/src/npc.h
+++ b/src/npc.h
@@ -1,50 +1,68 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NPC_H
-#define _TMW_NPC_H
+#ifndef NPC_H
+#define NPC_H
-#include "being.h"
+#include "player.h"
+#ifdef EATHENA_SUPPORT
+class Network;
+#endif
class Graphics;
+class Text;
-class NPC : public Being
+class NPC : public Player
{
public:
+#ifdef TMWSERV_SUPPORT
NPC(Uint16 id, int sprite, Map *map);
+#else
+ NPC(Uint32 id, Uint16 job, Map *map, Network *network);
+#endif
- virtual Type
- getType() const;
+ ~NPC();
- virtual void
- drawName(Graphics *graphics, Sint32 offsetX, Sint32 offsetY);
+ void setName(const std::string &name);
+ void setGender(Gender gender);
+ void setSprite(int slot, int id, std::string color);
+
+ virtual Type getType() const;
void talk();
void nextDialog();
- void dialogChoice(int choice);
+ void dialogChoice(char choice);
+ void integerInput(int value);
+ void stringInput(const std::string &value);
void buy();
void sell();
/**
+ * Call this to ease clean up of the current NPC, without causing
+ * interface problems
+ */
+ void handleDeath();
+
+ /**
* Gets the way an NPC is blocked by other things on the map
*/
virtual unsigned char getWalkMask() const
@@ -56,6 +74,13 @@ class NPC : public Being
*/
virtual Map::BlockType getBlockType() const
{ return Map::BLOCKTYPE_CHARACTER; } //blocks like a player character
+
+#ifdef EATHENA_SUPPORT
+ Network *mNetwork;
+#endif
+ void updateCoords();
+ private:
+ Text *mName;
};
extern NPC *current_npc;
diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp
index 48b10a1f..e7e7b204 100644
--- a/src/openglgraphics.cpp
+++ b/src/openglgraphics.cpp
@@ -1,48 +1,41 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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/openglgraphics.h b/src/openglgraphics.h
index ea30e019..566d6252 100644
--- a/src/openglgraphics.h
+++ b/src/openglgraphics.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_OPENGLGRAPHICS_H
-#define _TMW_OPENGLGRAPHICS_H
+#ifndef OPENGLGRAPHICS_H
+#define OPENGLGRAPHICS_H
#include "graphics.h"
diff --git a/src/particle.cpp b/src/particle.cpp
index c6e242bd..f021f6e5 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -1,34 +1,35 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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"
@@ -188,13 +189,13 @@ bool Particle::update()
e++
)
{
- Particles newParticles = (*e)->createParticles();
+ Particles newParticles = (*e)->createParticles(mLifetimePast);
for ( ParticleIterator p = newParticles.begin();
p != newParticles.end();
p++
)
{
- (*p)->moveBy(mPos.x, mPos.y, mPos.z);
+ (*p)->moveBy(mPos);
mChildParticles.push_back (*p);
}
}
@@ -231,6 +232,25 @@ bool Particle::update()
return true;
}
+void Particle::moveBy(const Vector &change)
+{
+ mPos += change;
+ for (ParticleIterator p = mChildParticles.begin();
+ p != mChildParticles.end();
+ p++)
+ {
+ if ((*p)->doesFollow())
+ {
+ (*p)->moveBy(change);
+ }
+ }
+}
+
+void Particle::moveTo(float x, float y)
+{
+ moveTo(Vector(x, y, mPos.z));
+}
+
Particle *Particle::addEffect(const std::string &particleEffectFile,
int pixelX, int pixelY, int rotation)
{
@@ -276,17 +296,15 @@ Particle *Particle::addEffect(const std::string &particleEffectFile,
}
// Read and set the basic properties of the particle
- int offsetX = XML::getProperty(effectChildNode, "position-x", 0);
- int offsetY = XML::getProperty(effectChildNode, "position-y", 0);
- int offsetZ = XML::getProperty(effectChildNode, "position-z", 0);
-
- int particleX = (int) mPos.x + pixelX + offsetX;
- int particleY = (int) mPos.y + pixelY + offsetY;
- int particleZ = (int) mPos.z + offsetZ;
+ float offsetX = XML::getFloatProperty(effectChildNode, "position-x", 0);
+ float offsetY = XML::getFloatProperty(effectChildNode, "position-y", 0);
+ float offsetZ = XML::getFloatProperty(effectChildNode, "position-z", 0);
+ Vector position (mPos.x + (float)pixelX + offsetX,
+ mPos.y + (float)pixelY + offsetY,
+ mPos.z + offsetZ);
+ newParticle->moveTo(position);
int lifetime = XML::getProperty(effectChildNode, "lifetime", -1);
-
- newParticle->setPosition(particleX, particleY, particleZ);
newParticle->setLifetime(lifetime);
// Look for additional emitters for this particle
@@ -312,7 +330,7 @@ Particle *Particle::addTextSplashEffect(const std::string &text,
{
Particle *newParticle = new TextParticle(mMap, text, colorR, colorG, colorB,
font);
- newParticle->setPosition(x, y, 0);
+ newParticle->moveTo(x, y);
newParticle->setVelocity(((rand() % 100) - 50) / 200.0f, // X
((rand() % 100) - 50) / 200.0f, // Y
((rand() % 100) / 200.0f) + 4.0f); // Z
@@ -332,7 +350,7 @@ Particle *Particle::addTextRiseFadeOutEffect(const std::string &text,
int x, int y)
{
Particle *newParticle = new TextParticle(mMap, text, colorR, colorG, colorB, font);
- newParticle->setPosition(x, y, 0);
+ newParticle->moveTo(x, y);
newParticle->setVelocity(0.0f, 0.0f, 0.5f);
newParticle->setGravity(0.0015f);
newParticle->setLifetime(300);
diff --git a/src/particle.h b/src/particle.h
index af0caf21..008c343b 100644
--- a/src/particle.h
+++ b/src/particle.h
@@ -1,32 +1,30 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _PARTICLE_H
-#define _PARTICLE_H
+#ifndef PARTICLE_H
+#define PARTICLE_H
#include <list>
#include <string>
-#include <guichan/color.hpp>
-
#include "guichanfwd.h"
#include "sprite.h"
#include "vector.h"
@@ -128,14 +126,13 @@ class Particle : public Sprite
/**
* Sets the position in 3 dimensional space in pixels relative to map.
*/
- void setPosition(float x, float y, float z)
- { mPos.x = x; mPos.y = y; mPos.z = z; }
+ void moveTo(const Vector &pos)
+ { moveBy (pos - mPos);}
/**
* Sets the position in 2 dimensional space in pixels relative to map.
*/
- void setPosition(float x, float y)
- { mPos.x = x; mPos.y = y; }
+ void moveTo(float x, float y);
/**
* Returns the particle position.
@@ -146,13 +143,7 @@ class Particle : public Sprite
/**
* Changes the particle position relative
*/
- void moveBy(float x, float y, float z)
- { mPos.x += x; mPos.y += y; mPos.z += z; }
-
- void moveChildren(Vector change);
-
- void moveBy (Vector change)
- { mPos += change; }
+ void moveBy (const Vector &change);
/**
* Sets the time in game ticks until the particle is destroyed.
diff --git a/src/particlecontainer.cpp b/src/particlecontainer.cpp
new file mode 100644
index 00000000..63f89079
--- /dev/null
+++ b/src/particlecontainer.cpp
@@ -0,0 +1,174 @@
+/*
+ * The Mana World
+ * 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
+ */
+
+#include <cassert>
+
+#include "particle.h"
+#include "particlecontainer.h"
+
+
+ParticleContainer::ParticleContainer(ParticleContainer *parent,
+ bool delParent):
+ mDelParent(delParent),
+ mNext(parent)
+{}
+
+ParticleContainer::~ParticleContainer()
+{
+ clearLocally();
+ if (mDelParent)
+ delete mNext;
+}
+
+void ParticleContainer::clear()
+{
+ clearLocally();
+ if (mNext)
+ mNext->clear();
+}
+
+void ParticleContainer::moveTo(float x, float y)
+{
+ if (mNext)
+ mNext->moveTo(x, y);
+}
+
+// -- particle list ----------------------------------------
+
+ParticleList::ParticleList(ParticleContainer *parent, bool delParent):
+ ParticleContainer(parent, delParent)
+{}
+
+ParticleList::~ParticleList()
+{}
+
+void ParticleList::addLocally(Particle *particle)
+{
+ if (particle)
+ {
+ // The effect may not die without the beings permission or we segfault
+ particle->disableAutoDelete();
+ mElements.push_back(particle);
+ }
+}
+
+void ParticleList::removeLocally(Particle *particle)
+{
+ for (std::list<Particle *>::iterator it = mElements.begin();
+ it != mElements.end(); it++)
+ {
+ if (*it == particle) {
+ (*it)->kill();
+ mElements.erase(it);
+ }
+ }
+}
+
+void ParticleList::clearLocally()
+{
+ for (std::list<Particle *>::iterator it = mElements.begin();
+ it != mElements.end(); it++)
+ (*it)->kill();
+
+ mElements.clear();
+}
+
+void ParticleList::moveTo(float x, float y)
+{
+ ParticleContainer::moveTo(x, y);
+
+ for (std::list<Particle *>::iterator it = mElements.begin();
+ it != mElements.end();)
+ {
+ (*it)->moveTo(x, y);
+ if ((*it)->isExtinct())
+ {
+ (*it)->kill();
+ it = mElements.erase(it);
+ }
+ else
+ it++;
+ }
+}
+
+// -- particle vector ----------------------------------------
+
+ParticleVector::ParticleVector(ParticleContainer *parent, bool delParent):
+ ParticleContainer(parent, delParent)
+{}
+
+ParticleVector::~ParticleVector()
+{}
+
+void ParticleVector::setLocally(int index, Particle *particle)
+{
+ assert(index >= 0);
+
+ delLocally(index);
+
+ if (mIndexedElements.size() <= (unsigned) index)
+ mIndexedElements.resize(index + 1, NULL);
+
+ if (particle)
+ particle->disableAutoDelete();
+ mIndexedElements[index] = particle;
+}
+
+void ParticleVector::delLocally(int index)
+{
+ assert(index >= 0);
+
+ if (mIndexedElements.size() <= (unsigned) index)
+ return;
+
+ Particle *p = mIndexedElements[index];
+ if (p)
+ {
+ mIndexedElements[index] = NULL;
+ p->kill();
+ }
+}
+
+void ParticleVector::clearLocally()
+{
+ for (unsigned int i = 0; i < mIndexedElements.size(); i++)
+ delLocally(i);
+}
+
+void ParticleVector::moveTo(float x, float y)
+{
+ ParticleContainer::moveTo(x, y);
+
+ for (std::vector<Particle *>::iterator it = mIndexedElements.begin();
+ it != mIndexedElements.end(); it++) {
+ if (*it)
+ {
+ (*it)->moveTo(x, y);
+
+ if ((*it)->isExtinct())
+ {
+ (*it)->kill();
+ *it = NULL;
+ }
+ }
+ }
+}
+
diff --git a/src/particlecontainer.h b/src/particlecontainer.h
new file mode 100644
index 00000000..26539dd7
--- /dev/null
+++ b/src/particlecontainer.h
@@ -0,0 +1,121 @@
+/*
+ * The Mana World
+ * 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 _PARTICLE_CONTAINER_H
+#define _PARTICLE_CONTAINER_H
+
+#include <list>
+#include <vector>
+
+class Particle;
+
+/**
+ * Set of particle effects. May be stacked with other ParticleContainers. All
+ * operations herein affect such stacked containers, unless the operations end
+ * in `Locally'.
+ */
+class ParticleContainer
+{
+public:
+ /**
+ * Constructs a new particle container and assumes responsibility for
+ * its parent (for all operations defined herein, except when ending in `Locally')
+ *
+ * delParent means that the destructor should also free the parent.
+ */
+ ParticleContainer(ParticleContainer *parent = NULL, bool delParent = true);
+ virtual ~ParticleContainer();
+
+ /**
+ * Kills and removes all particle effects
+ */
+ void clear();
+
+ /**
+ * Kills and removes all particle effects (only in this container)
+ */
+ virtual void clearLocally() {};
+
+ /**
+ * Sets the positions of all elements
+ */
+ virtual void moveTo(float x, float y);
+
+protected:
+ bool mDelParent; /**< Delete mNext in destructor */
+ ParticleContainer *mNext; /**< Contained container, if any */
+};
+
+/**
+ * Linked list of particle effects.
+ */
+class ParticleList : public ParticleContainer
+{
+public:
+ ParticleList(ParticleContainer *parent = NULL, bool delParent = true);
+ virtual ~ParticleList();
+
+ /**
+ * Takes control of and adds a particle
+ */
+ void addLocally(Particle *);
+
+ /**
+ * `kills' and removes a particle
+ */
+ void removeLocally(Particle *);
+
+ virtual void clearLocally();
+
+ virtual void moveTo(float x, float y);
+
+protected:
+ std::list<Particle *> mElements; /**< Contained particle effects */
+};
+
+/**
+ * Particle container with indexing facilities
+ */
+class ParticleVector : public ParticleContainer
+{
+public:
+ ParticleVector(ParticleContainer *parent = NULL, bool delParent = true);
+ virtual ~ParticleVector();
+
+ /**
+ * Sets a particle at a specified index. Kills the previous particle
+ * there, if needed.
+ */
+ virtual void setLocally(int index, Particle *particle);
+
+ /**
+ * Removes a particle at a specified index
+ */
+ virtual void delLocally(int index);
+
+ virtual void clearLocally();
+ virtual void moveTo(float x, float y);
+
+protected:
+ std::vector<Particle *> mIndexedElements;
+};
+
+#endif
diff --git a/src/particleemitter.cpp b/src/particleemitter.cpp
index d368237c..25e6ade5 100644
--- a/src/particleemitter.cpp
+++ b/src/particleemitter.cpp
@@ -1,37 +1,35 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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
@@ -43,7 +41,7 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *
mMap = map;
mParticleTarget = target;
- //initializing default values
+ // Initializing default values
mParticlePosX.set(0.0f);
mParticlePosY.set(0.0f);
mParticlePosZ.set(0.0f);
@@ -72,26 +70,28 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *
if (name == "position-x")
{
- mParticlePosX = readMinMax(propertyNode, 0.0f);
+ mParticlePosX = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "position-y")
{
- mParticlePosY = readMinMax(propertyNode, 0.0f);
+ mParticlePosY = readParticleEmitterProp(propertyNode, 0.0f);
mParticlePosY.minVal *= SIN45;
mParticlePosY.maxVal *= SIN45;
+ mParticlePosY.changeAmplitude *= SIN45;
}
else if (name == "position-z")
{
- mParticlePosZ = readMinMax(propertyNode, 0.0f);
+ mParticlePosZ = readParticleEmitterProp(propertyNode, 0.0f);
mParticlePosZ.minVal *= SIN45;
mParticlePosZ.maxVal *= SIN45;
+ mParticlePosZ.changeAmplitude *= SIN45;
}
else if (name == "image")
{
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);
@@ -99,69 +99,74 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *
}
else if (name == "horizontal-angle")
{
- mParticleAngleHorizontal = readMinMax(propertyNode, 0.0f);
- mParticleAngleHorizontal += rotation;
- mParticleAngleHorizontal *= DEG_RAD_FACTOR;
+ 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;
}
else if (name == "vertical-angle")
{
- mParticleAngleVertical = readMinMax(propertyNode, 0.0f);
- mParticleAngleVertical *= DEG_RAD_FACTOR;
+ mParticleAngleVertical = readParticleEmitterProp(propertyNode, 0.0f);
+ mParticleAngleVertical.minVal *= DEG_RAD_FACTOR;
+ mParticleAngleVertical.maxVal *= DEG_RAD_FACTOR;
+ mParticleAngleVertical.changeAmplitude *= DEG_RAD_FACTOR;
}
else if (name == "power")
{
- mParticlePower = readMinMax(propertyNode, 0.0f);
+ mParticlePower = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "gravity")
{
- mParticleGravity = readMinMax(propertyNode, 0.0f);
+ mParticleGravity = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "randomnes" || name == "randomness") // legacy bug
{
- mParticleRandomness = readMinMax(propertyNode, 0);
+ mParticleRandomness = readParticleEmitterProp(propertyNode, 0);
}
else if (name == "bounce")
{
- mParticleBounce = readMinMax(propertyNode, 0.0f);
+ mParticleBounce = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "lifetime")
{
- mParticleLifetime = readMinMax(propertyNode, 0);
+ mParticleLifetime = readParticleEmitterProp(propertyNode, 0);
mParticleLifetime.minVal += 1;
}
else if (name == "output")
{
- mOutput = readMinMax(propertyNode, 0);
+ mOutput = readParticleEmitterProp(propertyNode, 0);
mOutput.maxVal +=1;
}
else if (name == "output-pause")
{
- mOutputPause = readMinMax(propertyNode, 0);
- mOutputPauseLeft = mOutputPause.value();
+ mOutputPause = readParticleEmitterProp(propertyNode, 0);
+ mOutputPauseLeft = mOutputPause.value(0);
}
else if (name == "acceleration")
{
- mParticleAcceleration = readMinMax(propertyNode, 0.0f);
+ mParticleAcceleration = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "die-distance")
{
- mParticleDieDistance = readMinMax(propertyNode, 0.0f);
+ mParticleDieDistance = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "momentum")
{
- mParticleMomentum = readMinMax(propertyNode, 1.0f);
+ mParticleMomentum = readParticleEmitterProp(propertyNode, 1.0f);
}
else if (name == "fade-out")
{
- mParticleFadeOut = readMinMax(propertyNode, 0);
+ mParticleFadeOut = readParticleEmitterProp(propertyNode, 0);
}
else if (name == "fade-in")
{
- mParticleFadeIn = readMinMax(propertyNode, 0);
+ mParticleFadeIn = readParticleEmitterProp(propertyNode, 0);
}
else if (name == "alpha")
{
- mParticleAlpha = readMinMax(propertyNode, 1.0f);
+ mParticleAlpha = readParticleEmitterProp(propertyNode, 1.0f);
}
else if (name == "follow-parent")
{
@@ -296,21 +301,34 @@ ParticleEmitter::~ParticleEmitter()
}
-template <typename T> MinMax<T>
-ParticleEmitter::readMinMax(xmlNodePtr propertyNode, T def)
+template <typename T> ParticleEmitterProp<T>
+ParticleEmitter::readParticleEmitterProp(xmlNodePtr propertyNode, T def)
{
- MinMax<T> retval;
+ ParticleEmitterProp<T> retval;
def = (T) XML::getFloatProperty(propertyNode, "value", (double) 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);
+ }
+
return retval;
}
-std::list<Particle *>
-ParticleEmitter::createParticles()
+std::list<Particle *> ParticleEmitter::createParticles(int tick)
{
std::list<Particle *> newParticles;
@@ -319,9 +337,9 @@ ParticleEmitter::createParticles()
mOutputPauseLeft--;
return newParticles;
}
- mOutputPauseLeft = mOutputPause.value();
+ mOutputPauseLeft = mOutputPause.value(tick);
- for (int i = mOutput.value(); i > 0; i--)
+ for (int i = mOutput.value(tick); i > 0; i--)
{
// Limit maximum particles
if (Particle::particleCount > Particle::maxCount) break;
@@ -341,35 +359,34 @@ ParticleEmitter::createParticles()
newParticle = new Particle(mMap);
}
+ Vector position(mParticlePosX.value(tick),
+ mParticlePosY.value(tick),
+ mParticlePosZ.value(tick));
+ newParticle->moveTo(position);
- newParticle->setPosition(
- mParticlePosX.value(),
- mParticlePosY.value(),
- mParticlePosZ.value());
-
- float angleH = mParticleAngleHorizontal.value();
- float angleV = mParticleAngleVertical.value();
- float power = mParticlePower.value();
+ float angleH = mParticleAngleHorizontal.value(tick);
+ float angleV = mParticleAngleVertical.value(tick);
+ float power = mParticlePower.value(tick);
newParticle->setVelocity(
cos(angleH) * cos(angleV) * power,
sin(angleH) * cos(angleV) * power,
sin(angleV) * power);
- newParticle->setRandomness(mParticleRandomness.value());
- newParticle->setGravity(mParticleGravity.value());
- newParticle->setBounce(mParticleBounce.value());
+ newParticle->setRandomness(mParticleRandomness.value(tick));
+ newParticle->setGravity(mParticleGravity.value(tick));
+ newParticle->setBounce(mParticleBounce.value(tick));
newParticle->setFollow(mParticleFollow);
newParticle->setDestination(mParticleTarget,
- mParticleAcceleration.value(),
- mParticleMomentum.value()
+ mParticleAcceleration.value(tick),
+ mParticleMomentum.value(tick)
);
- newParticle->setDieDistance(mParticleDieDistance.value());
+ newParticle->setDieDistance(mParticleDieDistance.value(tick));
- newParticle->setLifetime(mParticleLifetime.value());
- newParticle->setFadeOut(mParticleFadeOut.value());
- newParticle->setFadeIn(mParticleFadeIn.value());
- newParticle->setAlpha(mParticleAlpha.value());
+ newParticle->setLifetime(mParticleLifetime.value(tick));
+ newParticle->setFadeOut(mParticleFadeOut.value(tick));
+ newParticle->setFadeIn(mParticleFadeIn.value(tick));
+ newParticle->setAlpha(mParticleAlpha.value(tick));
for (std::list<ParticleEmitter>::iterator i = mParticleChildEmitters.begin();
i != mParticleChildEmitters.end();
diff --git a/src/particleemitter.h b/src/particleemitter.h
index 4dc2f6fb..67b35ae2 100644
--- a/src/particleemitter.h
+++ b/src/particleemitter.h
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -25,7 +25,8 @@
#include <list>
#include "utils/xml.h"
-#include "utils/minmax.h"
+
+#include "particleemitterprop.h"
#include "resources/animation.h"
@@ -64,60 +65,59 @@ class ParticleEmitter
* Spawns new particles
* @return: a list of created particles
*/
- std::list<Particle *> createParticles();
+ std::list<Particle *> createParticles(int tick);
/**
* Sets the target of the particles that are created
*/
- void
- setTarget(Particle *target)
+ void setTarget(Particle *target)
{ mParticleTarget = target; };
private:
- template <typename T> MinMax<T> readMinMax(xmlNodePtr propertyNode, T def);
+ template <typename T> ParticleEmitterProp<T> readParticleEmitterProp(xmlNodePtr propertyNode, T def);
/**
* initial position of particles:
*/
- MinMax<float> mParticlePosX, mParticlePosY, mParticlePosZ;
+ ParticleEmitterProp<float> mParticlePosX, mParticlePosY, mParticlePosZ;
/**
* initial vector of particles:
*/
- MinMax<float> mParticleAngleHorizontal, mParticleAngleVertical;
+ ParticleEmitterProp<float> mParticleAngleHorizontal, mParticleAngleVertical;
/**
* Initial velocity of particles
*/
- MinMax<float> mParticlePower;
+ ParticleEmitterProp<float> mParticlePower;
/*
* Vector changing of particles:
*/
- MinMax<float> mParticleGravity;
- MinMax<int> mParticleRandomness;
- MinMax<float> mParticleBounce;
+ ParticleEmitterProp<float> mParticleGravity;
+ ParticleEmitterProp<int> mParticleRandomness;
+ ParticleEmitterProp<float> mParticleBounce;
bool mParticleFollow;
/*
* Properties of targeting particles:
*/
Particle *mParticleTarget;
- MinMax<float> mParticleAcceleration;
- MinMax<float> mParticleDieDistance;
- MinMax<float> mParticleMomentum;
+ ParticleEmitterProp<float> mParticleAcceleration;
+ ParticleEmitterProp<float> mParticleDieDistance;
+ ParticleEmitterProp<float> mParticleMomentum;
/*
* Behavior over time of the particles:
*/
- MinMax<int> mParticleLifetime;
- MinMax<int> mParticleFadeOut;
- MinMax<int> mParticleFadeIn;
+ ParticleEmitterProp<int> mParticleLifetime;
+ ParticleEmitterProp<int> mParticleFadeOut;
+ ParticleEmitterProp<int> mParticleFadeIn;
Map *mMap; /**< Map the particles are spawned on */
- MinMax<int> mOutput; /**< Number of particles spawned per update */
- MinMax<int> mOutputPause; /**< Pause in frames between two spawns */
+ ParticleEmitterProp<int> mOutput; /**< Number of particles spawned per update */
+ ParticleEmitterProp<int> mOutputPause; /**< Pause in frames between two spawns */
int mOutputPauseLeft;
/*
@@ -125,7 +125,7 @@ class ParticleEmitter
*/
Image *mParticleImage; /**< Particle image, if used */
Animation mParticleAnimation; /**< Filename of particle animation file */
- MinMax<float> mParticleAlpha; /**< Opacity of the graphical representation of the particles */
+ ParticleEmitterProp<float> mParticleAlpha; /**< Opacity of the graphical representation of the particles */
/** List of emitters the spawned particles are equipped with */
std::list<ParticleEmitter> mParticleChildEmitters;
diff --git a/src/particleemitterprop.h b/src/particleemitterprop.h
new file mode 100644
index 00000000..e68ac222
--- /dev/null
+++ b/src/particleemitterprop.h
@@ -0,0 +1,109 @@
+/*
+ * The Mana World
+ * Copyright (C) 2006 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 <cmath>
+
+/**
+ * Returns a random numeric value that is larger than or equal min and smaller
+ * than max
+ */
+
+enum ChangeFunc
+{
+ FUNC_NONE,
+ FUNC_SINE,
+ FUNC_SAW,
+ FUNC_TRIANGLE,
+ FUNC_SQUARE
+};
+
+template <typename T> struct ParticleEmitterProp
+{
+ ParticleEmitterProp():
+ changeFunc(FUNC_NONE)
+ {
+ }
+
+ void set(T min, T max)
+ {
+ minVal=min; maxVal=max;
+ }
+
+ void set(T val)
+ {
+ set(val, val);
+ }
+
+ void setFunction(ChangeFunc func, T amplitude, int period, int phase)
+ {
+ changeFunc = func;
+ changeAmplitude = amplitude;
+ changePeriod = period;
+ changePhase = phase;
+ }
+
+ T value(int tick)
+ {
+ tick += changePhase;
+ T val = (T) (minVal + (maxVal - minVal) * (rand() / ((double) RAND_MAX + 1)));
+
+ switch (changeFunc)
+ {
+ case FUNC_SINE:
+ val += (T) std::sin(M_PI * 2 * ((double)(tick%changePeriod) / (double)changePeriod)) * changeAmplitude;
+ break;
+ case FUNC_SAW:
+ val += (T) (changeAmplitude * ((double)(tick%changePeriod) / (double)changePeriod)) * 2 - changeAmplitude;
+ break;
+ case FUNC_TRIANGLE:
+ if ((tick%changePeriod) * 2 < changePeriod)
+ {
+ val += changeAmplitude - (T)((tick%changePeriod) / (double)changePeriod) * changeAmplitude * 4;
+ } else {
+ val += changeAmplitude * -3 + (T)((tick%changePeriod) / (double)changePeriod) * changeAmplitude * 4;
+ // I have no idea why this works but it does
+ }
+ break;
+ case FUNC_SQUARE:
+ if ((tick%changePeriod) * 2 < changePeriod)
+ {
+ val += changeAmplitude;
+ } else {
+ val -= changeAmplitude;
+ }
+ break;
+ case FUNC_NONE:
+ default:
+ //nothing
+ break;
+ }
+
+ return val;
+ }
+
+ T minVal;
+ T maxVal;
+
+ ChangeFunc changeFunc;
+ T changeAmplitude;
+ int changePeriod;
+ int changePhase;
+};
diff --git a/src/party.cpp b/src/party.cpp
new file mode 100644
index 00000000..d22db55f
--- /dev/null
+++ b/src/party.cpp
@@ -0,0 +1,217 @@
+/*
+ * The Mana World
+ * 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 "being.h"
+#include "localplayer.h"
+#include "party.h"
+
+#include "gui/chat.h"
+#include "gui/confirm_dialog.h"
+
+#include "net/messageout.h"
+#include "net/ea/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..0f58b14b
--- /dev/null
+++ b/src/party.h
@@ -0,0 +1,76 @@
+/*
+ * The Mana World
+ * 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 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 19486d6e..09eec0d1 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -1,63 +1,127 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "player.h"
-
#include "animatedsprite.h"
#include "game.h"
-#include "graphics.h"
+#ifdef TMWSERV_SUPPORT
#include "guild.h"
-#include "log.h"
+#endif
+#include "player.h"
+#include "text.h"
+#include "resources/colordb.h"
#include "resources/itemdb.h"
-#include "resources/iteminfo.h"
#include "utils/strprintf.h"
-#include "gui/gui.h"
+static const int NAME_X_OFFSET = 15;
+static const int NAME_Y_OFFSET = 30;
Player::Player(int id, int job, Map *map):
Being(id, job, map)
{
+ mName = NULL;
}
Player::~Player()
{
+ delete mName;
}
-Being::Type
-Player::getType() const
+void Player::setName(const std::string &name)
{
- return PLAYER;
+ if (mName == NULL)
+ {
+ 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);
+ }
}
-void Player::drawName(Graphics *graphics, int offsetX, int offsetY)
+#ifdef EATHENA_SUPPORT
+void Player::logic()
{
- const Vector &pos = getPosition();
- const int px = (int) pos.x + offsetX;
- const int py = (int) pos.y + offsetY;
+ switch (mAction)
+ {
+ case STAND:
+ break;
+
+ case SIT:
+ break;
+
+ case DEAD:
+ break;
+
+ case HURT:
+ break;
+
+ case WALK:
+ mFrame = (get_elapsed_time(mWalkTime) * 6) / getWalkSpeed();
+
+ if (mFrame >= 6)
+ nextStep();
+
+ break;
+
+ case ATTACK:
+ int frames = 4;
+ if (mEquippedWeapon &&
+ mEquippedWeapon->getAttackType() == ACTION_ATTACK_BOW)
+ {
+ frames = 5;
+ }
+
+ mFrame = (get_elapsed_time(mWalkTime) * frames) / mAttackSpeed;
- graphics->setFont(speechFont);
- graphics->setColor(gcn::Color(255, 255, 255));
- graphics->drawText(mName, px, py, gcn::Graphics::CENTER);
+ if (mFrame >= frames)
+ nextStep();
+
+ break;
+ }
+
+ Being::logic();
+}
+#endif
+
+Being::Type Player::getType() const
+{
+ return PLAYER;
+}
+
+void Player::flash(int time)
+{
+ if (mName)
+ mName->flash(time);
}
void Player::setGender(Gender gender)
@@ -76,22 +140,20 @@ void Player::setGender(Gender gender)
for (int i = 1; i < VECTOREND_SPRITE; i++)
{
if (mSpriteIDs.at(i) != 0)
- {
setSprite(i, mSpriteIDs.at(i), mSpriteColors.at(i));
- }
}
}
}
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);
}
@@ -103,6 +165,11 @@ void Player::setSprite(int slot, int id, const std::string &color)
{
delete mSprites[slot];
mSprites[slot] = NULL;
+
+#ifdef EATHENA_SUPPORT
+ if (slot == WEAPON_SPRITE)
+ mEquippedWeapon = NULL;
+#endif
}
else
{
@@ -113,8 +180,9 @@ void Player::setSprite(int slot, int id, const std::string &color)
{
if (!color.empty())
filename += "|" + color;
- equipmentSprite =
- AnimatedSprite::load("graphics/sprites/" + filename);
+
+ equipmentSprite = AnimatedSprite::load("graphics/sprites/" +
+ filename);
}
if (equipmentSprite)
@@ -132,6 +200,14 @@ void Player::setSprite(int slot, int id, const std::string &color)
Being::setSprite(slot, id, color);
}
+void Player::updateCoords()
+{
+ if (mName)
+ mName->adviseXY(mPx + NAME_X_OFFSET, mPy + NAME_Y_OFFSET);
+}
+
+#ifdef TMWSERV_SUPPORT
+
Guild* Player::addGuild(short guildId, short rights)
{
Guild *guild = new Guild(guildId, rights);
@@ -181,4 +257,4 @@ void Player::setInParty(bool value)
mInParty = value;
}
-
+#endif
diff --git a/src/player.h b/src/player.h
index 6880ca20..1904c6d9 100644
--- a/src/player.h
+++ b/src/player.h
@@ -1,32 +1,35 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_PLAYER_H
-#define _TMW_PLAYER_H
+#ifndef PLAYER_H
+#define PLAYER_H
#include "being.h"
+class FlashText;
class Graphics;
class Map;
+#ifdef TMWSERV_SUPPORT
class Guild;
+#endif
/**
* A player being. Players have their name drawn beneath them. This class also
@@ -41,31 +44,45 @@ class Player : public Being
*/
Player(int id, int job, Map *map);
- virtual ~Player();
-
- virtual Type
- getType() const;
-
- virtual void
- drawName(Graphics *graphics, int offsetX, int offsetY);
+ ~Player();
/**
- * Sets the gender for this player.
+ * Set up mName to be the character's name
*/
- void setGender(Gender);
+ virtual void setName(const std::string &name);
+
+#ifdef EATHENA_SUPPORT
+ virtual void logic();
+#endif
+
+ virtual Type getType() const;
+
+ virtual void setGender(Gender gender);
/**
* Sets the hair style and color for this player.
+ *
+ * Only for convenience in 0.0 client. When porting
+ * this to the trunk remove this function and
+ * call setSprite directly instead. The server should
+ * provide the hair ID and coloring in the same way
+ * it does for other equipment pieces.
+ *
*/
void setHairStyle(int style, int color);
/**
* Sets visible equipments for this player.
*/
- virtual void
- setSprite(int slot, int id, const std::string &color = "");
+ virtual void setSprite(int slot, int id, const std::string &color = "");
/**
+ * Flash the player's name
+ */
+ void flash(int time);
+
+#ifdef TMWSERV_SUPPORT
+ /**
* Adds a guild to the player.
*/
Guild* addGuild(short guildId, short rights);
@@ -99,6 +116,7 @@ class Player : public Being
* Returns whether player is in the party
*/
bool getInParty() const { return mInParty; }
+#endif
/**
* Gets the way the character is blocked by other objects.
@@ -113,19 +131,19 @@ class Player : public Being
virtual Map::BlockType getBlockType() const
{ return Map::BLOCKTYPE_CHARACTER; }
+ virtual void updateCoords();
+
+#ifdef TMWSERV_SUPPORT
// Character guild information
std::map<int, Guild*> mGuilds;
+#endif
- /**
- * Triggers a visual/audio effect, such as `level up'
- *
- * \param effect_id ID of the effect to trigger
- */
- virtual void
- triggerEffect(int effectId) { internalTriggerEffect(effectId, true, true); }
+ FlashText *mName;
+#ifdef TMWSERV_SUPPORT
private:
bool mInParty;
+#endif
};
#endif
diff --git a/src/player_relations.cpp b/src/player_relations.cpp
new file mode 100644
index 00000000..c82876e1
--- /dev/null
+++ b/src/player_relations.cpp
@@ -0,0 +1,369 @@
+/*
+ * The Mana World
+ * 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
+ */
+
+#include <algorithm>
+
+#include "being.h"
+#include "beingmanager.h"
+#include "configuration.h"
+#include "graphics.h"
+#include "player.h"
+#include "player_relations.h"
+
+#define PLAYER_IGNORE_STRATEGY_NOP "nop"
+#define PLAYER_IGNORE_STRATEGY_EMOTE0 "emote0"
+#define DEFAULT_IGNORE_STRATEGY PLAYER_IGNORE_STRATEGY_EMOTE0
+
+#define NAME "name" // constant for xml serialisation
+#define RELATION "relation" // constant for xml serialisation
+
+#define IGNORE_EMOTE_TIME 100
+
+
+// (De)serialisation class
+class PlayerConfSerialiser : public ConfigurationListManager<std::pair<std::string, PlayerRelation *>,
+ std::map<std::string, PlayerRelation *> *>
+{
+ virtual ConfigurationObject *writeConfigItem(std::pair<std::string, PlayerRelation *> value,
+ ConfigurationObject *cobj)
+ {
+ if (!value.second)
+ return NULL;
+ cobj->setValue(NAME, value.first);
+ cobj->setValue(RELATION, value.second->mRelation);
+
+ return cobj;
+ }
+
+ virtual std::map<std::string, PlayerRelation *> *
+ readConfigItem(ConfigurationObject *cobj,
+ std::map<std::string, PlayerRelation *> *container)
+ {
+ std::string name = cobj->getValue(NAME, "");
+ if (name.empty())
+ return container;
+
+ if (!(*container)[name]) {
+ int v = (int)cobj->getValue(RELATION, PlayerRelation::NEUTRAL);
+ (*container)[name] = new PlayerRelation(static_cast<PlayerRelation::relation>(v));
+ }
+ // otherwise ignore the duplicate entry
+
+ return container;
+ }
+};
+
+static PlayerConfSerialiser player_conf_serialiser; // stateless singleton
+
+const unsigned int PlayerRelation::RELATION_PERMISSIONS[RELATIONS_NR] = {
+ /* NEUTRAL */ 0, // we always fall back to the defaults anyway
+ /* FRIEND */ EMOTE | SPEECH_FLOAT | SPEECH_LOG | WHISPER | TRADE,
+ /* DISREGARDED*/ EMOTE | SPEECH_FLOAT,
+ /* IGNORED */ 0
+};
+
+PlayerRelation::PlayerRelation(relation relation)
+{
+ mRelation = relation;
+}
+
+PlayerRelationsManager::PlayerRelationsManager() :
+ mPersistIgnores(false),
+ mDefaultPermissions(PlayerRelation::DEFAULT),
+ mIgnoreStrategy(NULL)
+{
+}
+
+void PlayerRelationsManager::clear()
+{
+ std::vector<std::string> *names = getPlayers();
+ for (std::vector<std::string>::const_iterator
+ it = names->begin(); it != names->end(); it++)
+ removePlayer(*it);
+ delete names;
+}
+
+#define PERSIST_IGNORE_LIST "persist-player-list"
+#define PLAYER_IGNORE_STRATEGY "player-ignore-strategy"
+#define DEFAULT_PERMISSIONS "default-player-permissions"
+
+int PlayerRelationsManager::getPlayerIgnoreStrategyIndex(const std::string &name)
+{
+ std::vector<PlayerIgnoreStrategy *> *strategies = getPlayerIgnoreStrategies();
+ for (unsigned int i = 0; i < strategies->size(); i++)
+ if ((*strategies)[i]->mShortName == name)
+ return i;
+
+ return -1;
+}
+
+void PlayerRelationsManager::load()
+{
+ clear();
+
+ mPersistIgnores = config.getValue(PERSIST_IGNORE_LIST, 0);
+ mDefaultPermissions = (int)config.getValue(DEFAULT_PERMISSIONS, mDefaultPermissions);
+ std::string ignore_strategy_name = config.getValue(PLAYER_IGNORE_STRATEGY, DEFAULT_IGNORE_STRATEGY);
+ int ignore_strategy_index = getPlayerIgnoreStrategyIndex(ignore_strategy_name);
+ if (ignore_strategy_index >= 0)
+ setPlayerIgnoreStrategy((*getPlayerIgnoreStrategies())[ignore_strategy_index]);
+
+ config.getList<std::pair<std::string, PlayerRelation *>,
+ std::map<std::string, PlayerRelation *> *>
+ ("player", &(mRelations), &player_conf_serialiser);
+}
+
+
+void PlayerRelationsManager::init()
+{
+ load();
+
+ if (!mPersistIgnores)
+ clear(); // Yes, we still keep them around in the config file until the next update.
+}
+
+void PlayerRelationsManager::store()
+{
+ config.setList<std::map<std::string, PlayerRelation *>::const_iterator,
+ std::pair<std::string, PlayerRelation *>,
+ std::map<std::string, PlayerRelation *> *>
+ ("player",
+ mRelations.begin(), mRelations.end(),
+ &player_conf_serialiser);
+
+ config.setValue(DEFAULT_PERMISSIONS, mDefaultPermissions);
+ config.setValue(PERSIST_IGNORE_LIST, mPersistIgnores);
+ config.setValue(PLAYER_IGNORE_STRATEGY,
+ (mIgnoreStrategy)? mIgnoreStrategy->mShortName : DEFAULT_IGNORE_STRATEGY);
+
+ config.write();
+}
+
+void PlayerRelationsManager::signalUpdate(const std::string &name)
+{
+ store();
+
+ for (std::list<PlayerRelationsListener *>::const_iterator it = mListeners.begin(); it != mListeners.end(); it++)
+ (*it)->updatedPlayer(name);
+}
+
+unsigned int PlayerRelationsManager::checkPermissionSilently(const std::string &player_name, unsigned int flags)
+{
+ PlayerRelation *r = mRelations[player_name];
+ if (!r)
+ return mDefaultPermissions & flags;
+ else {
+ unsigned int permissions = PlayerRelation::RELATION_PERMISSIONS[r->mRelation];
+
+ switch (r->mRelation) {
+ case PlayerRelation::NEUTRAL:
+ permissions = mDefaultPermissions;
+ break;
+
+ case PlayerRelation::FRIEND:
+ permissions |= mDefaultPermissions; // widen
+ break;
+
+ default:
+ permissions &= mDefaultPermissions; // narrow
+ }
+
+ return permissions & 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)
+{
+ unsigned int rejections = flags & ~checkPermissionSilently(name, flags);
+ bool permitted = rejections == 0;
+
+ if (!permitted) {
+ // execute `ignore' strategy, if possible
+ if (mIgnoreStrategy) {
+ Player *to_ignore = dynamic_cast<Player *>(beingManager->findBeingByName(name, Being::PLAYER));
+
+ if (to_ignore)
+ mIgnoreStrategy->ignore(to_ignore,
+ rejections);
+ }
+ }
+
+ return permitted;
+}
+
+void PlayerRelationsManager::setRelation(const std::string &player_name, PlayerRelation::relation relation)
+{
+ PlayerRelation *r = mRelations[player_name];
+ if (r == NULL)
+ mRelations[player_name] = new PlayerRelation(relation);
+ else
+ r->mRelation = relation;
+
+ signalUpdate(player_name);
+}
+
+std::vector<std::string> * PlayerRelationsManager::getPlayers()
+{
+ std::vector<std::string> *retval = new std::vector<std::string>();
+
+ for (std::map<std::string, PlayerRelation *>::const_iterator it = mRelations.begin(); it != mRelations.end(); it++)
+ if (it->second)
+ retval->push_back(it->first);
+
+ sort(retval->begin(), retval->end());
+
+ return retval;
+}
+
+void PlayerRelationsManager::removePlayer(const std::string &name)
+{
+ if (mRelations[name])
+ delete mRelations[name];
+
+ mRelations.erase(name);
+
+ signalUpdate(name);
+}
+
+
+PlayerRelation::relation PlayerRelationsManager::getRelation(const std::string &name)
+{
+ if (mRelations[name])
+ return mRelations[name]->mRelation;
+
+ return PlayerRelation::NEUTRAL;
+}
+
+////////////////////////////////////////
+// defaults
+
+unsigned int PlayerRelationsManager::getDefault() const
+{
+ return mDefaultPermissions;
+}
+
+void PlayerRelationsManager::setDefault(unsigned int permissions)
+{
+ mDefaultPermissions = permissions;
+
+ store();
+ signalUpdate("");
+}
+
+
+////////////////////////////////////////
+// ignore strategies
+
+
+class PIS_nothing : public PlayerIgnoreStrategy
+{
+public:
+ PIS_nothing()
+ {
+ mDescription = "completely ignore";
+ mShortName = PLAYER_IGNORE_STRATEGY_NOP;
+ }
+
+ virtual void ignore(Player *player, unsigned int flags)
+ {
+ }
+};
+
+class PIS_dotdotdot : public PlayerIgnoreStrategy
+{
+public:
+ PIS_dotdotdot()
+ {
+ mDescription = "print '...'";
+ mShortName = "dotdotdot";
+ }
+
+ virtual void ignore(Player *player, unsigned int flags)
+ {
+ player->setSpeech("...", 500);
+ }
+};
+
+
+class PIS_blinkname : public PlayerIgnoreStrategy
+{
+public:
+ PIS_blinkname()
+ {
+ mDescription = "blink name";
+ mShortName = "blinkname";
+ }
+
+ virtual void ignore(Player *player, unsigned int flags)
+ {
+ player->flash(200);
+ }
+};
+
+class PIS_emote : public PlayerIgnoreStrategy
+{
+public:
+ PIS_emote(int emote_nr, const std::string &description, const std::string &shortname) :
+ mEmotion(emote_nr)
+ {
+ mDescription = description;
+ mShortName = shortname;
+ }
+
+ virtual void ignore(Player *player, unsigned int flags)
+ {
+ player->setEmote(mEmotion, IGNORE_EMOTE_TIME);
+ }
+private:
+ int mEmotion;
+};
+
+
+
+static std::vector<PlayerIgnoreStrategy *> player_ignore_strategies;
+
+std::vector<PlayerIgnoreStrategy *> *
+PlayerRelationsManager::getPlayerIgnoreStrategies()
+{
+ if (player_ignore_strategies.size() == 0) {
+ // not initialised yet?
+ player_ignore_strategies.push_back(new PIS_emote(FIRST_IGNORE_EMOTE,
+ "floating '...' bubble",
+ PLAYER_IGNORE_STRATEGY_EMOTE0));
+ player_ignore_strategies.push_back(new PIS_emote(FIRST_IGNORE_EMOTE + 1,
+ "floating bubble",
+ "emote1"));
+ player_ignore_strategies.push_back(new PIS_nothing());
+ player_ignore_strategies.push_back(new PIS_dotdotdot());
+ player_ignore_strategies.push_back(new PIS_blinkname());
+ }
+ return &player_ignore_strategies;
+}
+
+
+PlayerRelationsManager player_relations;
diff --git a/src/player_relations.h b/src/player_relations.h
new file mode 100644
index 00000000..1eb4ede6
--- /dev/null
+++ b/src/player_relations.h
@@ -0,0 +1,241 @@
+/*
+ * The Mana World
+ * 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 PLAYER_RELATIONS_H
+#define PLAYER_RELATIONS_H
+
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+class Being;
+class Player;
+
+struct PlayerRelation
+{
+ static const unsigned int EMOTE = (1 << 0);
+ static const unsigned int SPEECH_FLOAT = (1 << 1);
+ static const unsigned int SPEECH_LOG = (1 << 2);
+ static const unsigned int WHISPER = (1 << 3);
+ static const unsigned int TRADE = (1 << 4);
+
+ static const unsigned int RELATIONS_NR = 4;
+ static const unsigned int RELATION_PERMISSIONS[RELATIONS_NR];
+
+ static const unsigned int DEFAULT = EMOTE
+ | SPEECH_FLOAT
+ | SPEECH_LOG
+ | WHISPER
+ | TRADE;
+ enum relation {
+ NEUTRAL = 0,
+ FRIEND = 1,
+ DISREGARDED = 2,
+ IGNORED = 3
+ };
+
+ PlayerRelation(relation relation);
+
+ relation mRelation; // bitmask for all of the above
+};
+
+
+/**
+ * Ignore strategy: describes how we should handle ignores.
+ */
+class PlayerIgnoreStrategy
+{
+public:
+ std::string mDescription;
+ std::string mShortName;
+
+ virtual ~PlayerIgnoreStrategy() {}
+
+ /**
+ * Handle the ignoring of the indicated action by the indicated player.
+ */
+ virtual void ignore(Player *player, unsigned int flags) = 0;
+};
+
+class PlayerRelationsListener
+{
+public:
+ PlayerRelationsListener() { }
+ virtual ~PlayerRelationsListener() { }
+
+ virtual void updatedPlayer(const std::string &name) = 0;
+};
+
+/**
+ * Player relations class, represents any particular relations and/or
+ * preferences the user of the local client has wrt other players (identified
+ * by std::string).
+ */
+class PlayerRelationsManager
+{
+public:
+ PlayerRelationsManager();
+
+ /**
+ * Initialise player relations manager (load config file etc.)
+ */
+ void init();
+
+ /**
+ * Load configuration from our config file, or substitute defaults.
+ */
+ void load();
+
+ /**
+ * Save configuration to our config file.
+ */
+ void store();
+
+ /**
+ * Determines whether the player in question is being ignored, filtered by
+ * the specified flags.
+ */
+ unsigned int checkPermissionSilently(const std::string &player_name,
+ unsigned int flags);
+
+ /**
+ * Tests whether the player in question is being ignored for any of the
+ * actions in the specified flags. If so, trigger appropriate side effects
+ * if requested by the player.
+ */
+ bool hasPermission(Being *being, unsigned int flags);
+
+ bool hasPermission(const std::string &being, unsigned int flags);
+
+ /**
+ * Updates the relationship with this player.
+ */
+ void setRelation(const std::string &name,
+ PlayerRelation::relation relation);
+
+ /**
+ * Updates the relationship with this player.
+ */
+ PlayerRelation::relation getRelation(const std::string &name);
+
+ /**
+ * Deletes the information recorded for a player.
+ */
+ void removePlayer(const std::string &name);
+
+
+ /**
+ * Retrieves the default permissions.
+ */
+ unsigned int getDefault() const;
+
+ /**
+ * Sets the default permissions.
+ */
+ void setDefault(unsigned int permissions);
+
+
+
+ /**
+ * Retrieves all known player ignore strategies.
+ *
+ * The player ignore strategies are allocated statically and must not be
+ * deleted.
+ */
+ std::vector<PlayerIgnoreStrategy *> *getPlayerIgnoreStrategies();
+
+ /**
+ * Return the current player ignore strategy.
+ *
+ * \return A player ignore strategy, or NULL
+ */
+ PlayerIgnoreStrategy *getPlayerIgnoreStrategy() const
+ {
+ return mIgnoreStrategy;
+ }
+
+ /**
+ * Sets the strategy to call when ignoring players.
+ */
+ void setPlayerIgnoreStrategy(PlayerIgnoreStrategy *strategy)
+ {
+ mIgnoreStrategy = strategy;
+ }
+
+ /**
+ * For a given ignore strategy short name, find the appropriate index in
+ * the ignore strategies vector.
+ *
+ * \param The short name of the ignore strategy to look up
+ * \return The appropriate index, or -1
+ */
+ int getPlayerIgnoreStrategyIndex(const std::string &shortname);
+
+ /**
+ * Retrieves a sorted vector of all players for which we have any relations
+ * recorded.
+ */
+ std::vector<std::string> *getPlayers();
+
+ /**
+ * Removes all recorded player info.
+ */
+ void clear();
+
+ /**
+ * Do we persist our `ignore' setup?
+ */
+ bool getPersistIgnores() const { return mPersistIgnores; }
+
+ /**
+ * Change the `ignore persist' flag.
+ *
+ * @param value Whether to persist ignores
+ */
+ void setPersistIgnores(bool value) { mPersistIgnores = value; }
+
+ void addListener(PlayerRelationsListener *listener)
+ {
+ mListeners.push_back(listener);
+ }
+
+ void removeListener(PlayerRelationsListener *listener)
+ {
+ mListeners.remove(listener);
+ }
+
+private:
+ void signalUpdate(const std::string &name);
+
+ bool mPersistIgnores; // If NOT set, we delete the ignored data upon reloading
+ unsigned int mDefaultPermissions;
+
+ PlayerIgnoreStrategy *mIgnoreStrategy;
+ std::map<std::string, PlayerRelation *> mRelations;
+ std::list<PlayerRelationsListener *> mListeners;
+};
+
+
+extern PlayerRelationsManager player_relations; // singleton representation of player relations
+
+
+#endif /* !defined(PLAYER_RELATIONS_H) */
diff --git a/src/position.cpp b/src/position.cpp
index cc39a1af..69d50476 100644
--- a/src/position.cpp
+++ b/src/position.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/position.h b/src/position.h
index 7beb3ef7..cbcf8c99 100644
--- a/src/position.h
+++ b/src/position.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2008 The Mana World 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef TMW_POSITION_H
-#define TMW_POSITION_H
+#ifndef POSITION_H
+#define POSITION_H
#include <list>
#include <iostream>
@@ -55,4 +55,4 @@ std::ostream& operator <<(std::ostream &os, const Position &p);
*/
std::ostream& operator <<(std::ostream &os, const Path &path);
-#endif // TMW_POSITION_H
+#endif // POSITION_H
diff --git a/src/properties.h b/src/properties.h
index a593e8c2..a2ce5b88 100644
--- a/src/properties.h
+++ b/src/properties.h
@@ -1,30 +1,30 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_PROPERTIES_H_
-#define _TMW_PROPERTIES_H_
+#ifndef PROPERTIES_H
+#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 bbea45c9..e2cb11f2 100644
--- a/src/resources/action.cpp
+++ b/src/resources/action.cpp
@@ -1,31 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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 09eb066e..649d3828 100644
--- a/src/resources/action.h
+++ b/src/resources/action.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ACTION_H
-#define _TMW_ACTION_H
+#ifndef ACTION_H
+#define ACTION_H
#include <map>
@@ -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 9eee57f0..32ed47d1 100644
--- a/src/resources/ambientoverlay.cpp
+++ b/src/resources/ambientoverlay.cpp
@@ -1,26 +1,25 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ambientoverlay.h"
-
#include "image.h"
#include "../graphics.h"
diff --git a/src/resources/ambientoverlay.h b/src/resources/ambientoverlay.h
index 56c70066..65f9891d 100644
--- a/src/resources/ambientoverlay.h
+++ b/src/resources/ambientoverlay.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_RESOURCES_AMBIENTOVERLAY_H_
-#define _TMW_RESOURCES_AMBIENTOVERLAY_H_
+#ifndef RESOURCES_AMBIENTOVERLAY_H
+#define RESOURCES_AMBIENTOVERLAY_H
class Graphics;
class Image;
diff --git a/src/resources/animation.cpp b/src/resources/animation.cpp
index d2794e61..54c319de 100644
--- a/src/resources/animation.cpp
+++ b/src/resources/animation.cpp
@@ -1,28 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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 8dfe8614..0c461ebe 100644
--- a/src/resources/animation.h
+++ b/src/resources/animation.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ANIMATION_H
-#define _TMW_ANIMATION_H
+#ifndef ANIMATION_H
+#define ANIMATION_H
#include <vector>
@@ -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/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 d180d725..22bd2411 100644
--- a/src/resources/dye.cpp
+++ b/src/resources/dye.cpp
@@ -1,25 +1,24 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 f0bd7aab..3cef334a 100644
--- a/src/resources/dye.h
+++ b/src/resources/dye.h
@@ -1,27 +1,28 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_DYE_H
-#define _TMW_DYE_H
+#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..5e9a146c
--- /dev/null
+++ b/src/resources/emotedb.cpp
@@ -0,0 +1,140 @@
+/*
+ * Emote database
+ * 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 "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..ad21722a
--- /dev/null
+++ b/src/resources/emotedb.h
@@ -0,0 +1,60 @@
+/*
+ * Emote database
+ * 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 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 77d77f96..7a7e6ac8 100644
--- a/src/resources/image.cpp
+++ b/src/resources/image.cpp
@@ -1,29 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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_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 3677696f..3160add8 100644
--- a/src/resources/image.h
+++ b/src/resources/image.h
@@ -1,30 +1,31 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_IMAGE_H
-#define _TMW_IMAGE_H
+#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
@@ -54,8 +55,7 @@ class Image : public Resource
/**
* Destructor.
*/
- virtual
- ~Image();
+ virtual ~Image();
/**
* Loads an image from a buffer in memory.
@@ -78,7 +78,8 @@ class Image : public Resource
* @return <code>NULL</code> if an error occurred, a valid pointer
* otherwise.
*/
- static Resource *load(void *buffer, unsigned bufferSize, Dye const &dye);
+ static Resource *load(void *buffer, unsigned bufferSize,
+ Dye const &dye);
/**
* Loads an image from an SDL surface.
@@ -88,21 +89,19 @@ class Image : public Resource
/**
* Frees the resources created by SDL.
*/
- virtual void
- unload();
+ virtual void unload();
/**
* Returns the width of the image.
*/
- virtual int
- getWidth() const { return mBounds.w; }
-
+ virtual int getWidth() const
+ { return mBounds.w; }
/**
* Returns the height of the image.
*/
- virtual int
- getHeight() const { return mBounds.h; }
+ virtual int getHeight() const
+ { return mBounds.h; }
/**
* Creates a new image with the desired clipping rectangle.
@@ -110,20 +109,17 @@ class Image : public Resource
* @return <code>NULL</code> if creation failed and a valid
* object otherwise.
*/
- virtual Image*
- getSubImage(int x, int y, int width, int height);
+ virtual Image *getSubImage(int x, int y, int width, int height);
/**
* Sets the alpha value of this image.
*/
- void
- setAlpha(float alpha);
+ virtual void setAlpha(float alpha);
/**
* Returns the alpha value of this image.
*/
- float
- getAlpha();
+ float getAlpha();
#ifdef USE_OPENGL
/**
@@ -133,7 +129,6 @@ class Image : public Resource
static void setLoadAsOpenGL(bool useOpenGL);
#endif
-
protected:
/**
* Constructor.
@@ -145,8 +140,7 @@ class Image : public Resource
/**
* Returns the first power of two equal or bigger than the input.
*/
- static int
- powerOfTwo(int input);
+ static int powerOfTwo(int input);
#endif
Image(SDL_Surface *image);
@@ -192,8 +186,7 @@ class SubImage : public Image
* @return <code>NULL</code> if creation failed and a valid
* image otherwise.
*/
- Image*
- getSubImage(int x, int y, int width, int height);
+ Image *getSubImage(int x, int y, int width, int height);
private:
Image *mParent;
diff --git a/src/resources/imageloader.cpp b/src/resources/imageloader.cpp
index 835ba100..40d62797 100644
--- a/src/resources/imageloader.cpp
+++ b/src/resources/imageloader.cpp
@@ -1,32 +1,31 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 <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/imageloader.h b/src/resources/imageloader.h
index 821a0254..1d6c9ae4 100644
--- a/src/resources/imageloader.h
+++ b/src/resources/imageloader.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_IMAGELOADER_H
-#define _TMW_IMAGELOADER_H
+#ifndef IMAGELOADER_H
+#define IMAGELOADER_H
#include <string>
diff --git a/src/resources/imageset.cpp b/src/resources/imageset.cpp
index 1c0f9373..92bb3242 100644
--- a/src/resources/imageset.cpp
+++ b/src/resources/imageset.cpp
@@ -1,30 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 58b7a8ea..f59c76bb 100644
--- a/src/resources/imageset.h
+++ b/src/resources/imageset.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_IMAGESET_H
-#define _TMW_IMAGESET_H
+#ifndef IMAGESET_H
+#define IMAGESET_H
#include <vector>
@@ -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 d6d8a6c2..c350ac07 100644
--- a/src/resources/imagewriter.cpp
+++ b/src/resources/imagewriter.cpp
@@ -1,29 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 632e2ae4..039d3afb 100644
--- a/src/resources/imagewriter.h
+++ b/src/resources/imagewriter.h
@@ -1,31 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 5dfcfb87..7304f8a7 100644
--- a/src/resources/itemdb.cpp
+++ b/src/resources/itemdb.cpp
@@ -1,30 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 <libxml/tree.h>
#include "itemdb.h"
-
-#include "iteminfo.h"
#include "resourcemanager.h"
#include "../log.h"
@@ -32,6 +31,7 @@
#include "../utils/dtor.h"
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
+#include "../utils/stringutils.h"
#include "../utils/xml.h"
namespace
@@ -95,13 +95,13 @@ void ItemDB::load()
logger->log("Initializing item database...");
- mUnknown = new ItemInfo();
- mUnknown->setName("Unknown item");
+ mUnknown = new ItemInfo;
+ 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"))
@@ -126,27 +126,37 @@ void ItemDB::load()
logger->log("ItemDB: Redefinition of item ID %d", id);
}
- int type = itemTypeFromString(XML::getProperty(node, "type", ""));
+ std::string typeStr = XML::getProperty(node, "type", "other");
int weight = XML::getProperty(node, "weight", 0);
int view = XML::getProperty(node, "view", 0);
std::string name = XML::getProperty(node, "name", "");
std::string image = XML::getProperty(node, "image", "");
std::string description = XML::getProperty(node, "description", "");
+#ifdef TMWSERV_SUPPORT
int weaponType = weaponTypeFromString(XML::getProperty(node, "weapon-type", ""));
+#else
+ int weaponType = XML::getProperty(node, "weapon_type", 0);
+#endif
int attackRange = XML::getProperty(node, "attack-range", 0);
ItemInfo *itemInfo = new ItemInfo;
itemInfo->setId(id);
itemInfo->setImageName(image);
- itemInfo->setName(name.empty() ? "Unnamed" : name);
+ itemInfo->setName(name.empty() ? _("Unnamed") : name);
itemInfo->setDescription(description);
+#ifdef TMWSERV_SUPPORT
+ int type = itemTypeFromString(typeStr);
itemInfo->setType(type);
+#else
+ itemInfo->setType(typeStr);
+#endif
itemInfo->setView(view);
itemInfo->setWeight(weight);
itemInfo->setWeaponType(weaponType);
itemInfo->setAttackRange(attackRange);
+#ifdef TMWSERV_SUPPORT
std::string effect;
for (int i = 0; i < int(sizeof(fields) / sizeof(fields[0])); ++i)
{
@@ -155,6 +165,9 @@ void ItemDB::load()
if (!effect.empty()) effect += " / ";
effect += strprintf(gettext(fields[i][1]), value);
}
+#else
+ std::string effect = XML::getProperty(node, "effect", "");
+#endif
itemInfo->setEffect(effect);
@@ -176,7 +189,10 @@ void ItemDB::load()
NamedItemInfoIterator itr = mNamedItemInfos.find(name);
if (itr == mNamedItemInfos.end())
{
- mNamedItemInfos[name] = itemInfo;
+ std::string temp = name;
+ toLower(trim(temp));
+
+ mNamedItemInfos[temp] = itemInfo;
}
else
{
@@ -191,7 +207,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);
@@ -216,7 +232,7 @@ void ItemDB::unload()
const ItemInfo& ItemDB::get(int id)
{
- assert(mLoaded && id);
+ assert(mLoaded);
ItemInfoIterator i = mItemInfos.find(id);
@@ -257,7 +273,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 1d814f34..68f3b039 100644
--- a/src/resources/itemdb.h
+++ b/src/resources/itemdb.h
@@ -1,30 +1,32 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ITEM_MANAGER_H
-#define _TMW_ITEM_MANAGER_H
+#ifndef ITEM_MANAGER_H
+#define ITEM_MANAGER_H
+
+#include <map>
#include "iteminfo.h"
-#include <map>
+class ItemInfo;
/**
* Item information database.
diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp
index cc7a6afc..f7118755 100644
--- a/src/resources/iteminfo.cpp
+++ b/src/resources/iteminfo.cpp
@@ -1,30 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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)
{
@@ -43,8 +41,10 @@ ItemInfo::getSprite(Gender gender) const
void ItemInfo::setWeaponType(int type)
{
+ // See server item.hpp file for type values.
switch (type)
{
+#ifdef TMWSERV_SUPPORT
case WPNTYPE_NONE:
mAttackType = ACTION_DEFAULT;
break;
@@ -63,18 +63,35 @@ void ItemInfo::setWeaponType(int type)
break;
default:
mAttackType = ACTION_ATTACK;
+#else
+ case 0: // none
+ mAttackType = ACTION_DEFAULT;
+ break;
+ case 1: // knife
+ case 2: // sword
+ mAttackType = ACTION_ATTACK_STAB;
+ break;
+ case 8: // projectile
+ mAttackType = ACTION_ATTACK_THROW;
+ break;
+ case 10: // bow
+ mAttackType = ACTION_ATTACK_BOW;
+ break;
+ case 11: // sickle
+ mAttackType = ACTION_ATTACK_SWING;
+ break;
+ default:
+ mAttackType = ACTION_ATTACK;
+#endif
}
}
-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 1c1d8467..10749c9e 100644
--- a/src/resources/iteminfo.h
+++ b/src/resources/iteminfo.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_ITEMINFO_H_
-#define _TMW_ITEMINFO_H_
+#ifndef ITEMINFO_H
+#define ITEMINFO_H
#include <map>
#include <string>
@@ -28,7 +28,7 @@
#include "spritedef.h"
-#include "../player.h"
+#include "../being.h"
enum EquipmentSoundEvent
{
@@ -115,7 +115,11 @@ class ItemInfo
* Constructor.
*/
ItemInfo():
+#ifdef TMWSERV_SUPPORT
mType(ITEM_UNUSABLE),
+#else
+ mType(""),
+#endif
mWeight(0),
mView(0),
mAttackType(ACTION_DEFAULT)
@@ -149,14 +153,20 @@ class ItemInfo
void setEffect(const std::string &effect)
{ mEffect = effect; }
- const std::string&
- getEffect() const { return mEffect; }
+ const std::string& getEffect() const { return mEffect; }
+#ifdef TMWSERV_SUPPORT
void setType(short type)
{ mType = type; }
short getType() const
{ return mType; }
+#else
+ void setType(const std::string& type)
+ { mType = type; }
+
+ const std::string& getType() const { return mType; }
+#endif
void setWeight(short weight)
{ mWeight = weight; }
@@ -192,7 +202,11 @@ class ItemInfo
std::string mName;
std::string mDescription; /**< Short description. */
std::string mEffect; /**< Description of effects. */
+#ifdef TMWSERV_SUPPORT
char mType; /**< Item type. */
+#else
+ std::string mType; /**< Item type. */
+#endif
short mWeight; /**< Weight in grams. */
int mView; /**< Item ID of how this item looks. */
int mId; /**< Item ID */
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index b812b2ce..c4cb7447 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -1,39 +1,39 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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"
#include "../tileset.h"
#include "../utils/base64.h"
-#include "../utils/tostring.h"
+#include "../utils/stringutils.h"
#include "../utils/xml.h"
const unsigned int DEFAULT_TILE_WIDTH = 32;
@@ -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)
{
@@ -233,6 +230,12 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path)
}
else if (xmlStrEqual(childNode->name, BAD_CAST "objectgroup"))
{
+ // 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 * tilew;
+ const int offsetY = tileOffsetY * tileh;
+
for_each_xml_child_node(objectNode, childNode)
{
if (xmlStrEqual(objectNode->name, BAD_CAST "object"))
@@ -253,7 +256,8 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path)
const int objY = XML::getProperty(objectNode, "y", 0);
logger->log("- Loading object name: %s type: %s at %d:%d",
- objName.c_str(), objType.c_str(), objX, objY);
+ objName.c_str(), objType.c_str(),
+ objX, objY);
if (objType == "PARTICLE_EFFECT")
{
@@ -262,7 +266,9 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path)
continue;
}
- map->addParticleEffect(objName, objX, objY);
+ map->addParticleEffect(objName,
+ objX + offsetX,
+ objY + offsetY);
}
else
{
@@ -297,7 +303,8 @@ void MapReader::readProperties(xmlNodePtr node, Properties *props)
static void setTile(Map *map, MapLayer *layer, int x, int y, int gid)
{
const Tileset * const set = map->getTilesetWithGid(gid);
- if (layer) {
+ if (layer)
+ {
// Set regular tile on a layer
Image * const img = set ? set->get(gid - set->getFirstGid()) : 0;
layer->setTile(x, y, img);
@@ -313,12 +320,12 @@ void MapReader::readLayer(xmlNodePtr node, Map *map)
// Layers are not necessarily the same size as the map
const int w = XML::getProperty(node, "width", map->getWidth());
const int h = XML::getProperty(node, "height", map->getHeight());
- const int offsetX = XML::getProperty(node, "xoffset", 0);
- const int offsetY = XML::getProperty(node, "yoffset", 0);
+ const int offsetX = XML::getProperty(node, "x", 0);
+ 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;
@@ -361,7 +368,7 @@ void MapReader::readLayer(xmlNodePtr node, Map *map)
while (*charStart) {
if (*charStart != ' ' && *charStart != '\t' &&
- *charStart != '\n')
+ *charStart != '\n')
{
*charIndex = *charStart;
charIndex++;
@@ -401,6 +408,12 @@ void MapReader::readLayer(xmlNodePtr node, Map *map)
setTile(map, layer, x, y, gid);
+ TileAnimation* ani = map->getAnimationForGid(gid);
+ if (ani)
+ {
+ ani->addAffectedTile(layer, x + y * w);
+ }
+
x++;
if (x == w) {
x = 0; y++;
@@ -446,46 +459,96 @@ 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 NULL;
+ 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());
for_each_xml_child_node(childNode, node)
{
- if (!xmlStrEqual(childNode->name, BAD_CAST "image"))
- continue;
+ if (xmlStrEqual(childNode->name, BAD_CAST "image"))
+ {
+ const std::string source = XML::getProperty(childNode, "source", "");
- const std::string source = XML::getProperty(childNode, "source", "");
+ if (!source.empty())
+ {
+ std::string sourceStr = source;
+ sourceStr.erase(0, 3); // Remove "../"
+
+ ResourceManager *resman = ResourceManager::getInstance();
+ Image* tilebmp = resman->getImage(sourceStr);
- if (!source.empty())
+ if (tilebmp)
+ {
+ set = new Tileset(tilebmp, tw, th, firstGid);
+ tilebmp->decRef();
+ }
+ else {
+ logger->log("Warning: Failed to load tileset (%s)",
+ source.c_str());
+ }
+ }
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "tile"))
{
- std::string sourceStr = source;
- sourceStr.erase(0, 3); // Remove "../"
+ for_each_xml_child_node(tileNode, childNode)
+ {
+ if (!xmlStrEqual(tileNode->name, BAD_CAST "properties")) continue;
- ResourceManager *resman = ResourceManager::getInstance();
- Image* tilebmp = resman->getImage(sourceStr);
+ int tileGID = firstGid + XML::getProperty(childNode, "id", 0);
- if (tilebmp)
- {
- Tileset *set = new Tileset(tilebmp, tw, th, firstGid);
- tilebmp->decRef();
- return set;
- }
- else {
- logger->log("Warning: Failed to load tileset (%s)",
- source.c_str());
+ // read tile properties to a map for simpler handling
+ std::map<std::string, int> tileProperties;
+ for_each_xml_child_node(propertyNode, tileNode)
+ {
+ if (!xmlStrEqual(propertyNode->name, BAD_CAST "property")) continue;
+ std::string name = XML::getProperty(propertyNode, "name", "");
+ int value = XML::getProperty(propertyNode, "value", 0);
+ tileProperties[name] = value;
+ logger->log("Tile Prop of %d \"%s\" = \"%d\"", tileGID, name.c_str(), value);
+ }
+
+ // create animation
+ if (!set) continue;
+
+ Animation *ani = new Animation;
+ for (int i = 0; ;i++)
+ {
+ std::map<std::string, int>::iterator iFrame, iDelay;
+ iFrame = tileProperties.find("animation-frame" + toString(i));
+ iDelay = tileProperties.find("animation-delay" + toString(i));
+ if (iFrame != tileProperties.end() && iDelay != tileProperties.end())
+ {
+ ani->addFrame(set->get(iFrame->second), iDelay->second, 0, 0);
+ } else {
+ break;
+ }
+ }
+
+ if (ani->getLength() > 0)
+ {
+ map->addAnimation(tileGID, new TileAnimation(ani));
+ logger->log("Animation length: %d", ani->getLength());
+ } else {
+ delete ani;
+ }
}
}
-
- // Only one image element expected
- break;
}
- return NULL;
+ delete doc;
+
+ return set;
}
diff --git a/src/resources/mapreader.h b/src/resources/mapreader.h
index 04e83b99..0ed553c3 100644
--- a/src/resources/mapreader.h
+++ b/src/resources/mapreader.h
@@ -1,33 +1,31 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_MAPREADER_H_
-#define _TMW_MAPREADER_H_
-
-#include <iosfwd>
+#ifndef MAPREADER_H
+#define MAPREADER_H
#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 ed4acd38..cee9eea5 100644
--- a/src/resources/monsterdb.cpp
+++ b/src/resources/monsterdb.cpp
@@ -1,32 +1,31 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "monsterdb.h"
-
-#include "resourcemanager.h"
-#include "spritedef.h"
+#include "monsterinfo.h"
#include "../log.h"
#include "../utils/dtor.h"
+#include "../utils/gettext.h"
#include "../utils/xml.h"
namespace
@@ -36,18 +35,17 @@ 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"))
@@ -59,11 +57,13 @@ MonsterDB::load()
for_each_xml_child_node(monsterNode, rootNode)
{
if (!xmlStrEqual(monsterNode->name, BAD_CAST "monster"))
+ {
continue;
+ }
- MonsterInfo *currentInfo = new MonsterInfo();
+ MonsterInfo *currentInfo = new MonsterInfo;
- currentInfo->setName(XML::getProperty(monsterNode, "name", "unnamed"));
+ currentInfo->setName(XML::getProperty(monsterNode, "name", _("unnamed")));
std::string targetCursor;
targetCursor = XML::getProperty(monsterNode, "targetCursor", "medium");
@@ -81,8 +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);
}
else if (xmlStrEqual(spriteNode->name, BAD_CAST "sound"))
{
diff --git a/src/resources/monsterdb.h b/src/resources/monsterdb.h
index f1d69e72..0a218661 100644
--- a/src/resources/monsterdb.h
+++ b/src/resources/monsterdb.h
@@ -1,41 +1,39 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_MONSTER_DB_H
-#define _TMW_MONSTER_DB_H
+#ifndef MONSTER_DB_H
+#define MONSTER_DB_H
#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 1e982213..2fc16bef 100644
--- a/src/resources/monsterinfo.cpp
+++ b/src/resources/monsterinfo.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -34,8 +34,7 @@ MonsterInfo::~MonsterInfo()
mSounds.clear();
}
-void
-MonsterInfo::addSound(MonsterSoundEvent event, const std::string &filename)
+void MonsterInfo::addSound(MonsterSoundEvent event, const std::string &filename)
{
if (mSounds.find(event) == mSounds.end())
{
@@ -45,8 +44,7 @@ MonsterInfo::addSound(MonsterSoundEvent event, const std::string &filename)
mSounds[event]->push_back("sfx/" + filename);
}
-const std::string &
-MonsterInfo::getSound(MonsterSoundEvent event) const
+const std::string &MonsterInfo::getSound(MonsterSoundEvent event) const
{
static std::string empty("");
std::map<MonsterSoundEvent, std::vector<std::string>* >::const_iterator i =
@@ -55,8 +53,7 @@ MonsterInfo::getSound(MonsterSoundEvent event) const
i->second->at(rand() % i->second->size());
}
-const std::string &
-MonsterInfo::getAttackParticleEffect(int attackType) const
+const std::string &MonsterInfo::getAttackParticleEffect(int attackType) const
{
static std::string empty("");
std::map<int, MonsterAttack*>::const_iterator i =
@@ -64,18 +61,16 @@ MonsterInfo::getAttackParticleEffect(int attackType) const
return (i == mMonsterAttacks.end()) ? empty : (*i).second->particleEffect;
}
-SpriteAction
-MonsterInfo::getAttackAction(int attackType) const
+SpriteAction MonsterInfo::getAttackAction(int attackType) const
{
std::map<int, MonsterAttack*>::const_iterator i =
mMonsterAttacks.find(attackType);
return (i == mMonsterAttacks.end()) ? ACTION_ATTACK : (*i).second->action;
}
-void
-MonsterInfo::addMonsterAttack(int id,
- const std::string &particleEffect,
- SpriteAction action)
+void MonsterInfo::addMonsterAttack(int id,
+ const std::string &particleEffect,
+ SpriteAction action)
{
MonsterAttack *a = new MonsterAttack;
a->particleEffect = particleEffect;
diff --git a/src/resources/monsterinfo.h b/src/resources/monsterinfo.h
index 88f6fb2b..02574147 100644
--- a/src/resources/monsterinfo.h
+++ b/src/resources/monsterinfo.h
@@ -1,35 +1,34 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_MONSTERINFO_H_
-#define _TMW_MONSTERINFO_H_
+#ifndef MONSTERINFO_H
+#define MONSTERINFO_H
+#include <list>
#include <map>
#include <string>
#include <vector>
-#include <list>
#include "../being.h"
-
enum MonsterSoundEvent
{
MONSTER_EVENT_HIT,
@@ -63,47 +62,39 @@ class MonsterInfo
*/
~MonsterInfo();
- void
- setName(const std::string &name) { mName = name; }
+ void setName(const std::string &name) { mName = name; }
- void
- addSprite(const std::string &filename)
+ void addSprite(const std::string &filename)
{ mSprites.push_back(filename); }
- void
- setTargetCursorSize(Being::TargetCursorSize targetCursorSize)
+ void setTargetCursorSize(Being::TargetCursorSize targetCursorSize)
{ mTargetCursorSize = targetCursorSize; }
- void
- addSound(MonsterSoundEvent event, const std::string &filename);
+ void addSound(MonsterSoundEvent event, const std::string &filename);
- void
- addParticleEffect(const std::string &filename);
+ void addParticleEffect(const std::string &filename);
- const std::string&
- getName() const { return mName; }
+ const std::string& getName() const
+ { return mName; }
- const std::list<std::string>&
- getSprites() const { return mSprites; }
+ const std::list<std::string>& getSprites() const
+ { return mSprites; }
- Being::TargetCursorSize
- getTargetCursorSize() const { return mTargetCursorSize; }
+ Being::TargetCursorSize getTargetCursorSize() const
+ { return mTargetCursorSize; }
- const std::string&
- getSound(MonsterSoundEvent event) const;
+ const std::string &getSound(MonsterSoundEvent event) const;
void addMonsterAttack(int id,
const std::string &particleEffect,
SpriteAction action);
- const std::string&
- getAttackParticleEffect(int attackType) const;
+ const std::string &getAttackParticleEffect(int attackType) const;
- SpriteAction
- getAttackAction(int attackType) const;
+ SpriteAction getAttackAction(int attackType) const;
- const std::list<std::string>&
- getParticleEffects() const { return mParticleEffects; }
+ const std::list<std::string>& getParticleEffects() const
+ { return mParticleEffects; }
private:
std::string mName;
diff --git a/src/resources/music.cpp b/src/resources/music.cpp
index 2386aa43..ed78a541 100644
--- a/src/resources/music.cpp
+++ b/src/resources/music.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -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 d50150b8..34907cf1 100644
--- a/src/resources/music.h
+++ b/src/resources/music.h
@@ -1,29 +1,32 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_MUSIC_H
-#define _TMW_MUSIC_H
+#ifndef MUSIC_H
+#define MUSIC_H
+#ifdef __APPLE__
+#include <SDL_mixer/SDL_mixer.h>
+#else
#include <SDL_mixer.h>
-
+#endif
#include "resource.h"
/**
@@ -56,14 +59,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 2f8d78d4..ee65136a 100644
--- a/src/resources/npcdb.cpp
+++ b/src/resources/npcdb.cpp
@@ -1,31 +1,29 @@
/*
* The Mana World
- * Copyright 2008 The Mana World 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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 00b4f99b..af6764bf 100644
--- a/src/resources/npcdb.h
+++ b/src/resources/npcdb.h
@@ -1,29 +1,29 @@
/*
* The Mana World
- * Copyright 2008 The Mana World 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_NPC_DB_H
-#define _TMW_NPC_DB_H
+#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 449caf55..d1c3ada4 100644
--- a/src/resources/resource.cpp
+++ b/src/resources/resource.cpp
@@ -1,42 +1,39 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 "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 e85e3147..7c5f989e 100644
--- a/src/resources/resource.h
+++ b/src/resources/resource.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_RESOURCE_H
-#define _TMW_RESOURCE_H
+#ifndef RESOURCE_H
+#define RESOURCE_H
#include <ctime>
#include <string>
@@ -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 3d42d92e..50eda0ce 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -1,43 +1,41 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * 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 <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;
@@ -381,7 +379,7 @@ ResourceManager *ResourceManager::getInstance()
{
// Create a new instance if necessary.
if (!instance)
- instance = new ResourceManager();
+ instance = new ResourceManager;
return instance;
}
@@ -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 e70dfb9d..c3c68d88 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -1,37 +1,37 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_RESOURCE_MANAGER_H
-#define _TMW_RESOURCE_MANAGER_H
+#ifndef RESOURCE_MANAGER_H
+#define RESOURCE_MANAGER_H
#include <ctime>
#include <map>
#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 e21fd2b0..3a285730 100644
--- a/src/resources/soundeffect.cpp
+++ b/src/resources/soundeffect.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -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 c3ff6668..fc2d4a69 100644
--- a/src/resources/soundeffect.h
+++ b/src/resources/soundeffect.h
@@ -1,28 +1,32 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SOUND_EFFECT_H
-#define _TMW_SOUND_EFFECT_H
+#ifndef SOUND_EFFECT_H
+#define SOUND_EFFECT_H
+#ifdef __APPLE__
+#include <SDL_mixer/SDL_mixer.h>
+#else
#include <SDL_mixer.h>
+#endif
#include "resource.h"
@@ -35,8 +39,7 @@ class SoundEffect : public Resource
/**
* Destructor.
*/
- virtual
- ~SoundEffect();
+ virtual ~SoundEffect();
/**
* Loads a sample from a buffer in memory.
@@ -58,8 +61,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 f5b763ea..390bd3d0 100644
--- a/src/resources/spritedef.cpp
+++ b/src/resources/spritedef.cpp
@@ -1,34 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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"
@@ -167,7 +166,7 @@ void SpriteDef::loadAction(xmlNodePtr node, int variant_offset)
actionName.c_str(), getIdPath().c_str());
return;
}
- Action *action = new Action();
+ Action *action = new Action;
mActions[actionType] = action;
// When first action set it as default direction
@@ -201,7 +200,7 @@ void SpriteDef::loadAnimation(xmlNodePtr animationNode,
return;
}
- Animation *animation = new Animation();
+ Animation *animation = new Animation;
action->setAnimation(directionType, animation);
// Get animation frames
@@ -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") {
@@ -349,6 +348,7 @@ SpriteAction SpriteDef::makeSpriteAction(const std::string &action)
else if (action == "attack_throw") {
return ACTION_ATTACK_THROW;
}
+#ifdef TMWSERV_SUPPORT
else if (action == "special0") {
return ACTION_SPECIAL_0;
}
@@ -379,6 +379,7 @@ SpriteAction SpriteDef::makeSpriteAction(const std::string &action)
else if (action == "special9") {
return ACTION_SPECIAL_9;
}
+#endif
else if (action == "cast_magic") {
return ACTION_CAST_MAGIC;
}
@@ -404,7 +405,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 0c3e443b..c3db8d64 100644
--- a/src/resources/spritedef.h
+++ b/src/resources/spritedef.h
@@ -1,34 +1,34 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SPRITEDEF_H
-#define _TMW_SPRITEDEF_H
+#ifndef SPRITEDEF_H
+#define SPRITEDEF_H
#include <map>
#include <string>
-#include "resource.h"
-
#include <libxml/tree.h>
+#include "resource.h"
+
class Action;
class ImageSet;
@@ -43,6 +43,7 @@ enum SpriteAction
ACTION_ATTACK_STAB,
ACTION_ATTACK_BOW,
ACTION_ATTACK_THROW,
+#ifdef TMWSERV_SUPPORT
ACTION_SPECIAL_0,
ACTION_SPECIAL_1,
ACTION_SPECIAL_2,
@@ -53,6 +54,7 @@ enum SpriteAction
ACTION_SPECIAL_7,
ACTION_SPECIAL_8,
ACTION_SPECIAL_9,
+#endif
ACTION_CAST_MAGIC,
ACTION_USE_ITEM,
ACTION_SIT,
@@ -93,6 +95,12 @@ class SpriteDef : public Resource
*/
static SpriteAction makeSpriteAction(const std::string &action);
+ /**
+ * Converts a string into a SpriteDirection enum.
+ */
+ static SpriteDirection
+ makeSpriteDirection(const std::string &direction);
+
private:
/**
* Constructor.
@@ -143,13 +151,6 @@ class SpriteDef : public Resource
*/
void substituteAction(SpriteAction complete, SpriteAction with);
- /**
- * Converts a string into a SpriteDirection enum.
- */
- static SpriteDirection
- makeSpriteDirection(const std::string &direction);
-
-
typedef std::map<std::string, ImageSet*> ImageSets;
typedef ImageSets::iterator ImageSetIterator;
diff --git a/src/serverinfo.h b/src/serverinfo.h
index 4d2bb525..c38d13c7 100644
--- a/src/serverinfo.h
+++ b/src/serverinfo.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SERVERINFO_
-#define _TMW_SERVERINFO_
+#ifndef SERVERINFO_
+#define SERVERINFO_
#include <string>
diff --git a/src/shopitem.cpp b/src/shopitem.cpp
index 9888f829..6547aaf1 100644
--- a/src/shopitem.cpp
+++ b/src/shopitem.cpp
@@ -1,31 +1,32 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "shopitem.h"
-#include "utils/tostring.h"
+#include "units.h"
ShopItem::ShopItem(int id, int quantity, int price):
Item(id, quantity),
mPrice(price)
{
- mDisplayName = getInfo().getName() + " (" + toString(mPrice) + " GP)";
+ mDisplayName = getInfo().getName() +
+ " (" + Units::formatCurrency(mPrice).c_str() + ")";
}
diff --git a/src/shopitem.h b/src/shopitem.h
index 05a0a67d..50af4991 100644
--- a/src/shopitem.h
+++ b/src/shopitem.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _SHOPITEM_H_
-#define _SHOPITEM_H_
+#ifndef _SHOPITEM_H
+#define _SHOPITEM_H
#include "item.h"
diff --git a/src/simpleanimation.cpp b/src/simpleanimation.cpp
index e8c26df1..65d8e8e2 100644
--- a/src/simpleanimation.cpp
+++ b/src/simpleanimation.cpp
@@ -1,39 +1,46 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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),
mAnimationPhase(0)
{
- mAnimation = new Animation();
+ mAnimation = new Animation;
ImageSet *imageset = ResourceManager::getInstance()->getImageSet(
XML::getProperty(animationNode, "imageset", ""),
@@ -43,7 +50,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);
@@ -106,17 +113,34 @@ SimpleAnimation::SimpleAnimation(xmlNodePtr animationNode):
mCurrentFrame = mAnimation->getFrame(0);
}
+bool SimpleAnimation::draw(Graphics* graphics, int posX, int posY) const
+{
+ if (!mCurrentFrame || !mCurrentFrame->image)
+ return false;
+
+ return graphics->drawImage(mCurrentFrame->image,
+ posX + mCurrentFrame->offsetX,
+ posY + mCurrentFrame->offsetY);
+}
+
+void SimpleAnimation::reset()
+{
+ mAnimationTime = 0;
+ mAnimationPhase = 0;
+}
+
void SimpleAnimation::update(unsigned int timePassed)
{
mAnimationTime += timePassed;
- while (mAnimationTime > mCurrentFrame->delay)
+
+ while (mAnimationTime > mCurrentFrame->delay && mCurrentFrame->delay > 0)
{
mAnimationTime -= mCurrentFrame->delay;
mAnimationPhase++;
+
if (mAnimationPhase >= mAnimation->getLength())
- {
mAnimationPhase = 0;
- }
+
mCurrentFrame = mAnimation->getFrame(mAnimationPhase);
}
}
diff --git a/src/simpleanimation.h b/src/simpleanimation.h
index 577268a8..e48644d4 100644
--- a/src/simpleanimation.h
+++ b/src/simpleanimation.h
@@ -1,33 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SIMPLEANIMAION_H
-#define _TMW_SIMPLEANIMAION_H
-
-#include "resources/animation.h"
+#ifndef SIMPLEANIMAION_H
+#define SIMPLEANIMAION_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.
@@ -55,6 +50,13 @@ class SimpleAnimation
void update(unsigned int timePassed);
+ bool draw(Graphics* graphics, int posX, int posY) const;
+
+ /**
+ * Resets the animation.
+ */
+ void reset();
+
Image *getCurrentImage() const;
private:
diff --git a/src/sound.cpp b/src/sound.cpp
index 888dcc31..6e0b0da0 100644
--- a/src/sound.cpp
+++ b/src/sound.cpp
@@ -1,29 +1,29 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 0c2af74b..c30ef7cd 100644
--- a/src/sound.h
+++ b/src/sound.h
@@ -1,28 +1,33 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SOUND_H
-#define _TMW_SOUND_H
+#ifndef SOUND_H
+#define SOUND_H
+#ifdef __APPLE__
+#include <SDL_mixer/SDL_mixer.h>
+#else
#include <SDL_mixer.h>
+#endif
+#include <string>
#include <string>
diff --git a/src/sprite.h b/src/sprite.h
index 0e0a95db..a6384e94 100644
--- a/src/sprite.h
+++ b/src/sprite.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_SPRITE_H_
-#define _TMW_SPRITE_H_
+#ifndef SPRITE_H
+#define SPRITE_H
class Graphics;
@@ -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
new file mode 100644
index 00000000..c0d689f0
--- /dev/null
+++ b/src/statuseffect.cpp
@@ -0,0 +1,170 @@
+/*
+ * The Mana World
+ * 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
+ */
+
+#include <map>
+
+#include "gui/chat.h"
+#include "statuseffect.h"
+
+#include "log.h"
+#include "utils/xml.h"
+
+
+#define STATUS_EFFECTS_FILE "status-effects.xml"
+
+StatusEffect::StatusEffect() :
+ mPersistentParticleEffect(false)
+{}
+
+StatusEffect::~StatusEffect()
+{}
+
+void StatusEffect::playSFX()
+{
+ if (!mSFXEffect.empty())
+ sound.playSfx(mSFXEffect);
+}
+
+void StatusEffect::deliverMessage()
+{
+ if (!mMessage.empty())
+ chatWindow->chatLog(mMessage, BY_SERVER);
+}
+
+Particle *StatusEffect::getParticle()
+{
+ if (mParticleEffect.empty())
+ return NULL;
+ else
+ return particleEngine->addEffect(mParticleEffect, 0, 0);
+}
+
+AnimatedSprite *StatusEffect::getIcon()
+{
+ if (mIcon.empty())
+ return NULL;
+ else {
+ AnimatedSprite *sprite = AnimatedSprite::load(
+ "graphics/sprites/" + mIcon);
+ if (false && sprite) {
+ sprite->play(ACTION_DEFAULT);
+ sprite->reset();
+ }
+ return sprite;
+ }
+}
+
+SpriteAction StatusEffect::getAction()
+{
+ if (mAction.empty())
+ return ACTION_INVALID;
+ else
+ return SpriteDef::makeSpriteAction(mAction);
+}
+
+
+// -- initialisation and static parts --
+
+
+typedef std::map<int, StatusEffect *> status_effect_map[2];
+
+static status_effect_map statusEffects;
+static status_effect_map stunEffects;
+static std::map<int, int> blockEffectIndexMap;
+
+int StatusEffect::blockEffectIndexToEffectIndex(int blockIndex)
+{
+ load();
+ if (blockEffectIndexMap.find(blockIndex) == blockEffectIndexMap.end())
+ return -1;
+ return blockEffectIndexMap[blockIndex];
+}
+
+StatusEffect *StatusEffect::getStatusEffect(int index, bool enabling)
+{
+ load();
+ return statusEffects[enabling][index];
+}
+
+StatusEffect *StatusEffect::getStunEffect(int index, bool enabling)
+{
+ load();
+ return stunEffects[enabling][index];
+}
+
+static bool status_effects_loaded = false;
+
+
+
+void StatusEffect::load()
+{
+ if (status_effects_loaded)
+ return;
+
+ status_effects_loaded = true;
+
+ XML::Document doc(STATUS_EFFECTS_FILE);
+ xmlNodePtr rootNode = doc.rootNode();
+
+ if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "status-effects"))
+ {
+ logger->log("Error loading status effects file: "
+ STATUS_EFFECTS_FILE);
+ return;
+ }
+
+ for_each_xml_child_node(node, rootNode)
+ {
+ status_effect_map *the_map = NULL;
+
+ int index = atoi(XML::getProperty(node, "id", "-1").c_str());
+
+ if (xmlStrEqual(node->name, BAD_CAST "status-effect"))
+ {
+ the_map = &statusEffects;
+ int block_index = atoi(XML::getProperty(node, "block-id", "-1").c_str());
+
+ if (index >= 0 && block_index >= 0)
+ blockEffectIndexMap[block_index] = index;
+
+ } else if (xmlStrEqual(node->name, BAD_CAST "stun-effect"))
+ the_map = &stunEffects;
+
+ if (the_map) {
+ StatusEffect *startEffect = new StatusEffect;
+ StatusEffect *endEffect = new StatusEffect;
+
+ startEffect->mMessage = XML::getProperty(node, "start-message", "");
+ startEffect->mSFXEffect = XML::getProperty(node, "start-audio", "");
+ startEffect->mParticleEffect = XML::getProperty(node, "start-particle", "");
+ startEffect->mIcon = XML::getProperty(node, "icon", "");
+ startEffect->mAction = XML::getProperty(node, "action", "");
+ startEffect->mPersistentParticleEffect = (XML::getProperty(node, "persistent-particle-effect", "no")) != "no";
+
+ endEffect->mMessage = XML::getProperty(node, "end-message", "");
+ endEffect->mSFXEffect = XML::getProperty(node, "end-audio", "");
+ endEffect->mParticleEffect = XML::getProperty(node, "end-particle", "");
+
+ (*the_map)[1][index] = startEffect;
+ (*the_map)[0][index] = endEffect;
+ }
+ }
+}
diff --git a/src/statuseffect.h b/src/statuseffect.h
new file mode 100644
index 00000000..16fed69a
--- /dev/null
+++ b/src/statuseffect.h
@@ -0,0 +1,108 @@
+/*
+ * The Mana World
+ * 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 STATUS_EFFECT_H
+#define STATUS_EFFECT_H
+
+#include "resources/animation.h"
+#include "particle.h"
+#include "animatedsprite.h"
+#include "sound.h"
+
+class StatusEffect
+{
+public:
+ StatusEffect();
+ ~StatusEffect();
+
+ /**
+ * Plays the sound effect associated with this status effect, if possible.
+ */
+ void playSFX();
+
+ /**
+ * Delivers the chat message associated with this status effect, if
+ * possible.
+ */
+ void deliverMessage();
+
+ /**
+ * Creates the particle effect associated with this status effect, if
+ * possible.
+ */
+ Particle *getParticle();
+
+ /**
+ * Retrieves the status icon for this effect, if applicable
+ */
+ AnimatedSprite *getIcon();
+
+ /**
+ * Retrieves an action to perform, or ACTION_INVALID
+ */
+ SpriteAction getAction();
+
+ /**
+ * Determines whether the particle effect should be restarted when the
+ * being changes maps
+ */
+ bool particleEffectIsPersistent() const { return mPersistentParticleEffect; }
+
+
+ /**
+ * Retrieves a status effect.
+ *
+ * \param index Index of the status effect.
+ * \param enabling Whether to retrieve the activating effect (true) or
+ * the deactivating effect (false).
+ */
+ static StatusEffect *getStatusEffect(int index, bool enabling);
+
+ /**
+ * Retrieves a stun effect.
+ *
+ * \param index Index of the stun effect.
+ * \param enabling Whether to retrieve the activating effect (true) or
+ * the deactivating effect (false).
+ */
+ static StatusEffect *getStunEffect(int index, bool enabling);
+
+ /**
+ * Maps a block effect index to its corresponding effect index. Block
+ * effect indices are used for opt2/opt3/status.option blocks; their
+ * mapping to regular effect indices is handled in the config file.
+ *
+ * Returns -1 on failure.
+ */
+ static int blockEffectIndexToEffectIndex(int blocKIndex);
+
+private:
+ static void load();
+
+ std::string mMessage;
+ std::string mSFXEffect;
+ std::string mParticleEffect;
+ std::string mIcon;
+ std::string mAction;
+ bool mPersistentParticleEffect;
+};
+
+#endif // !defined(STATUS_EFFECT_H)
diff --git a/src/text.cpp b/src/text.cpp
new file mode 100644
index 00000000..cb4587d3
--- /dev/null
+++ b/src/text.cpp
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ *
+ * 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 "text.h"
+
+#include <guichan/font.hpp>
+
+#include "configuration.h"
+#include "textmanager.h"
+#include "resources/resourcemanager.h"
+#include "resources/image.h"
+
+#include "gui/gui.h"
+
+int Text::mInstances = 0;
+ImageRect Text::mBubble;
+Image *Text::mBubbleArrow;
+
+Text::Text(const std::string &text, int x, int y,
+ gcn::Graphics::Alignment alignment,
+ gcn::Color color, bool isSpeech) :
+ mText(text),
+ mColor(color),
+ mIsSpeech(isSpeech)
+{
+ if (textManager == 0)
+ {
+ textManager = new TextManager;
+ ResourceManager *resman = ResourceManager::getInstance();
+ Image *sbImage = resman->getImage("graphics/gui/bubble.png|W:#"
+ + 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);
+ mBubble.grid[3] = sbImage->getSubImage(0, 5, 5, 5);
+ mBubble.grid[4] = sbImage->getSubImage(5, 5, 5, 5);
+ mBubble.grid[5] = sbImage->getSubImage(10, 5, 5, 5);
+ mBubble.grid[6] = sbImage->getSubImage(0, 10, 5, 5);
+ mBubble.grid[7] = sbImage->getSubImage(5, 10, 5, 5);
+ mBubble.grid[8] = sbImage->getSubImage(10, 10, 5, 5);
+ mBubbleArrow = sbImage->getSubImage(0, 15, 15, 10);
+ const float bubbleAlpha = config.getValue("speechBubbleAlpha", 1.0);
+ for (int i = 0; i < 9; i++)
+ {
+ mBubble.grid[i]->setAlpha(bubbleAlpha);
+ }
+ mBubbleArrow->setAlpha(bubbleAlpha);
+ sbImage->decRef();
+ }
+ ++mInstances;
+ mHeight = boldFont->getHeight();
+ mWidth = boldFont->getWidth(text);
+
+ switch (alignment)
+ {
+ case gcn::Graphics::LEFT:
+ mXOffset = 0;
+ break;
+ case gcn::Graphics::CENTER:
+ mXOffset = mWidth / 2;
+ break;
+ case gcn::Graphics::RIGHT:
+ mXOffset = mWidth;
+ break;
+ }
+ mX = x - mXOffset;
+ mY = y;
+ textManager->addText(this);
+}
+
+Text::~Text()
+{
+ textManager->removeText(this);
+ if (--mInstances == 0)
+ {
+ delete textManager;
+ textManager = 0;
+ delete mBubble.grid[0];
+ delete mBubble.grid[1];
+ delete mBubble.grid[2];
+ delete mBubble.grid[3];
+ delete mBubble.grid[4];
+ delete mBubble.grid[5];
+ delete mBubble.grid[6];
+ delete mBubble.grid[7];
+ delete mBubble.grid[8];
+ delete mBubbleArrow;
+ }
+}
+
+void Text::adviseXY(int x, int y)
+{
+ textManager->moveText(this, x - mXOffset, y);
+}
+
+void Text::draw(gcn::Graphics *graphics, int xOff, int yOff)
+{
+ graphics->setFont(boldFont);
+
+ if (mIsSpeech) {
+ static_cast<Graphics*>(graphics)->drawImageRect(
+ mX - xOff - 5, mY - yOff - 5, mWidth + 10, mHeight + 10,
+ mBubble);
+ /*
+ if (mWidth >= 15) {
+ static_cast<Graphics*>(graphics)->drawImage(
+ mBubbleArrow, mX - xOff - 7 + mWidth / 2,
+ mY - yOff + mHeight + 4);
+ }
+ */
+ }
+
+ // Text shadow
+ graphics->setColor(gcn::Color(0, 0, 0));
+ graphics->drawText(mText, mX - xOff + 1, mY - yOff + 1,
+ gcn::Graphics::LEFT);
+
+ if (!mIsSpeech) {
+ graphics->setColor(gcn::Color(0, 0, 0, 64));
+ /*
+ // TODO: Reanable when we can draw it nicely in software mode
+ graphics->drawText(mText, mX - xOff + 2, mY - yOff + 2,
+ gcn::Graphics::LEFT);
+ graphics->drawText(mText, mX - xOff + 1, mY - yOff + 2,
+ gcn::Graphics::LEFT);
+ graphics->drawText(mText, mX - xOff + 2, mY - yOff + 1,
+ gcn::Graphics::LEFT);
+ */
+
+ // Text outline
+ graphics->setColor(gcn::Color(0, 0, 0));
+ graphics->drawText(mText, mX - xOff + 1, mY - yOff,
+ gcn::Graphics::LEFT);
+ graphics->drawText(mText, mX - xOff - 1, mY - yOff,
+ gcn::Graphics::LEFT);
+ graphics->drawText(mText, mX - xOff, mY - yOff + 1,
+ gcn::Graphics::LEFT);
+ graphics->drawText(mText, mX - xOff, mY - yOff - 1,
+ gcn::Graphics::LEFT);
+ }
+
+ 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 color) :
+ Text(text, x, y, alignment, color),
+ mTime(0)
+{
+}
+
+void FlashText::draw(gcn::Graphics *graphics, int xOff, int yOff)
+{
+ if (mTime)
+ {
+ if ((--mTime & 4) == 0)
+ {
+ return;
+ }
+ }
+ Text::draw(graphics, xOff, yOff);
+}
diff --git a/src/text.h b/src/text.h
new file mode 100644
index 00000000..6e121da7
--- /dev/null
+++ b/src/text.h
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ *
+ * 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 TEXT_H
+#define TEXT_H
+
+#include <guichan/color.hpp>
+
+#include "graphics.h"
+#include "guichanfwd.h"
+
+class TextManager;
+
+class Text
+{
+ friend class TextManager;
+
+ public:
+ /**
+ * Constructor creates a text object to display on the screen.
+ */
+ Text(const std::string &text, int x, int y,
+ gcn::Graphics::Alignment alignment,
+ gcn::Color color, bool isSpeech = false);
+
+ /**
+ * Destructor. The text is removed from the screen.
+ */
+ virtual ~Text();
+
+ /**
+ * Allows the originator of the text to specify the ideal coordinates.
+ */
+ void adviseXY(int x, int y);
+
+ /**
+ * Draws the text.
+ */
+ virtual void draw(gcn::Graphics *graphics, int xOff, int yOff);
+
+ private:
+ int mX; /**< Actual x-value of left of text written. */
+ int mY; /**< Actual y-value of top of text written. */
+ int mWidth; /**< The width of the text. */
+ int mHeight; /**< The height of the 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 mColor; /**< The color of the text. */
+ bool mIsSpeech; /**< Is this text a speech bubble? */
+
+ protected:
+ static ImageRect mBubble; /**< Speech bubble graphic */
+ static Image *mBubbleArrow; /**< Speech bubble arrow graphic */
+};
+
+class FlashText : public Text
+{
+ public:
+ FlashText(const std::string &text, int x, int y,
+ gcn::Graphics::Alignment alignment,
+ gcn::Color color);
+
+ /**
+ * Remove the text from the screen
+ */
+ virtual ~FlashText() {}
+
+ /**
+ * Flash the text for so many refreshes.
+ */
+ void flash(int time) {mTime = time; }
+
+ /**
+ * Draws the text.
+ */
+ virtual void draw(gcn::Graphics *graphics, int xOff, int yOff);
+
+ private:
+ int mTime; /**< Time left for flashing */
+};
+
+#endif // TEXT_H
diff --git a/src/textmanager.cpp b/src/textmanager.cpp
new file mode 100644
index 00000000..6bc8f8b6
--- /dev/null
+++ b/src/textmanager.cpp
@@ -0,0 +1,169 @@
+/*
+ * Support for non-overlapping floating text
+ * 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 "textmanager.h"
+
+#include <cstring>
+
+#include "text.h"
+
+TextManager *textManager = 0;
+
+TextManager::TextManager()
+{
+}
+
+void TextManager::addText(Text *text)
+{
+ place(text, 0, text->mX, text->mY, text->mHeight);
+ mTextList.push_back(text);
+}
+
+void TextManager::moveText(Text *text, int x, int y)
+{
+ text->mX = x;
+ text->mY = y;
+ place(text, text, text->mX, text->mY, text->mHeight);
+}
+
+void TextManager::removeText(const Text *text)
+{
+ for (TextList::iterator ptr = mTextList.begin(),
+ pEnd = mTextList.end(); ptr != pEnd; ++ptr)
+ {
+ if (*ptr == text)
+ {
+ mTextList.erase(ptr);
+ return;
+ }
+ }
+}
+
+TextManager::~TextManager()
+{
+}
+
+void TextManager::draw(gcn::Graphics *graphics, int xOff, int yOff)
+{
+ for (TextList::iterator bPtr = mTextList.begin(), ePtr = mTextList.end();
+ bPtr != ePtr; ++bPtr)
+ {
+ (*bPtr)->draw(graphics, xOff, yOff);
+ }
+}
+
+void TextManager::place(const Text *textObj, const Text *omit,
+ int &x, int &y, int h)
+{
+ int xLeft = textObj->mX;
+ int xRight = xLeft + textObj->mWidth - 1;
+ const int TEST = 100; // Number of lines to test for text
+ bool occupied[TEST]; // is some other text obscuring this line?
+ std::memset(&occupied, 0, sizeof(occupied)); // set all to false
+ int wantedTop = (TEST - h) / 2; // Entry in occupied at top of text
+ int occupiedTop = y - wantedTop; // Line in map representing to of occupied
+
+ for (TextList::const_iterator ptr = mTextList.begin(),
+ pEnd = mTextList.end(); ptr != pEnd; ++ptr)
+ {
+ if (*ptr != omit &&
+ (*ptr)->mX <= xRight &&
+ (*ptr)->mX + (*ptr)->mWidth > xLeft)
+ {
+ 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;
+ for (int i = wantedTop; i < wantedTop + h; ++i)
+ {
+ 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
+ for (int seek = wantedTop + h - 2; seek >= 0; --seek)
+ {
+ if (occupied[seek])
+ {
+ consec = 0;
+ }
+ else
+ {
+ if (++consec == h)
+ {
+ upSlot = seek;
+ break;
+ }
+ }
+ }
+ int downSlot = -1;
+ consec = 0;
+ for (int seek = wantedTop + 1; seek < TEST; ++seek)
+ {
+ if (occupied[seek])
+ {
+ consec = 0;
+ }
+ else
+ {
+ if (++consec == h)
+ {
+ downSlot = seek - h + 1;
+ break;
+ }
+ }
+ }
+ if (upSlot == -1 && downSlot == -1) // no good solution, so leave as is
+ {
+ return;
+ }
+ if (upSlot == -1) // must go down
+ {
+ y += downSlot - wantedTop;
+ return;
+ }
+ if (downSlot == -1) // must go up
+ {
+ y -= wantedTop - upSlot;
+ return;
+ }
+ if (wantedTop - upSlot > downSlot - wantedTop) // down is better
+ {
+ y += downSlot - wantedTop;
+ }
+ else
+ {
+ y -= wantedTop - upSlot;
+ }
+}
diff --git a/src/textmanager.h b/src/textmanager.h
new file mode 100644
index 00000000..ee8e1209
--- /dev/null
+++ b/src/textmanager.h
@@ -0,0 +1,77 @@
+/*
+ * Support for non-overlapping floating text
+ * 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 TEXTMANAGER_H
+#define TEXTMANAGER_H
+
+#include <list>
+
+#include "guichanfwd.h"
+
+class Text;
+
+class TextManager
+{
+ public:
+ /**
+ * Constructor
+ */
+ TextManager();
+
+ /**
+ * Add text to the manager
+ */
+ void addText(Text *text);
+
+ /**
+ * Move the text around the screen
+ */
+ void moveText(Text *text, int x, int y);
+
+ /**
+ * Remove the text from the manager
+ */
+ void removeText(const Text *text);
+
+ /**
+ * Destroy the manager
+ */
+ ~TextManager();
+
+ /**
+ * Draw the text
+ */
+ void draw(gcn::Graphics *graphics, int xOff, int yOff);
+
+ private:
+ /**
+ * Position the text so as to avoid conflict
+ */
+ void place(const Text *textObj, const Text *omit,
+ int &x, int &y, int h);
+
+ typedef std::list<Text *> TextList; /**< The container type */
+ TextList mTextList; /**< The container */
+};
+
+extern TextManager *textManager;
+
+#endif // TEXTMANAGER_H
diff --git a/src/textparticle.cpp b/src/textparticle.cpp
index 308c043d..f38c32ce 100644
--- a/src/textparticle.cpp
+++ b/src/textparticle.cpp
@@ -1,27 +1,28 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* 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 d56dbf84..76c247bf 100644
--- a/src/textparticle.h
+++ b/src/textparticle.h
@@ -1,32 +1,29 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright (C) 2006 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TEXTPARTICLE_H
-#define _TEXTPARTICLE_H
-
-#include "particle.h"
-
-#include <guichan/color.hpp>
+#ifndef TEXTPARTICLE_H
+#define TEXTPARTICLE_H
#include "guichanfwd.h"
+#include "particle.h"
class TextParticle : public Particle
{
diff --git a/src/tileset.h b/src/tileset.h
index fb855831..d4de7ba5 100644
--- a/src/tileset.h
+++ b/src/tileset.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_TILESET_H_
-#define _TMW_TILESET_H_
+#ifndef TILESET_H
+#define TILESET_H
#include "resources/imageset.h"
diff --git a/src/tmw.rc b/src/tmw.rc
index 9661ac6b..d9689f28 100644
--- a/src/tmw.rc
+++ b/src/tmw.rc
@@ -13,7 +13,7 @@ FILETYPE VFT_APP {
VALUE "CompanyName", "The Mana World Development Team"
VALUE "FileVersion", PACKAGE_VERSION
VALUE "FileDescription", "The Mana World"
- VALUE "LegalCopyright", "2004-2006 (C)"
+ VALUE "LegalCopyright", "2004-2009 (C)"
VALUE "OriginalFilename", "tmw.exe"
VALUE "ProductName", "The Mana World MMORPG"
VALUE "ProductVersion", PACKAGE_VERSION
diff --git a/src/units.cpp b/src/units.cpp
new file mode 100644
index 00000000..4f8b95f0
--- /dev/null
+++ b/src/units.cpp
@@ -0,0 +1,232 @@
+/*
+ * Support for custom units
+ * Copyright (C) 2009 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 "units.h"
+
+#include <cmath>
+#include <climits>
+#include <vector>
+
+#include "log.h"
+
+#include "utils/strprintf.h"
+#include "utils/stringutils.h"
+#include "utils/xml.h"
+
+struct UnitLevel {
+ std::string symbol;
+ int count;
+ int round;
+};
+
+struct UnitDescription {
+ std::vector<struct UnitLevel> levels;
+ double conversion;
+ bool mix;
+};
+
+enum UnitType {
+ UNIT_WEIGHT = 0,
+ UNIT_CURRENCY = 1,
+ UNIT_END
+};
+
+struct UnitDescription units[UNIT_END];
+
+void Units::loadUnits()
+{
+ int level;
+ std::string type;
+ XML::Document doc("units.xml");
+ xmlNodePtr root = doc.rootNode();
+
+ { // Setup default weight
+ struct UnitDescription ud;
+
+ ud.conversion = 1.0;
+ ud.mix = false;
+
+ struct UnitLevel bu;
+ bu.symbol = "g";
+ bu.count = 1;
+ bu.round = 0;
+
+ ud.levels.push_back(bu);
+
+ struct UnitLevel ul;
+ ul.symbol = "kg";
+ ul.count = 1000;
+ ul.round = 2;
+
+ ud.levels.push_back(ul);
+
+ units[UNIT_WEIGHT] = ud;
+ }
+
+ { // Setup default currency
+ struct UnitDescription ud;
+
+ ud.conversion = 1.0;
+ ud.mix = false;
+
+ struct UnitLevel bu;
+ bu.symbol = "¤";
+ bu.count = 1;
+ bu.round = 0;
+
+ ud.levels.push_back(bu);
+
+ units[UNIT_CURRENCY] = ud;
+ }
+
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "units"))
+ {
+ logger->log("Error loading unit definition file: units.xml");
+ return;
+ }
+
+ for_each_xml_child_node(node, root)
+ {
+ if (xmlStrEqual(node->name, BAD_CAST "unit"))
+ {
+ struct UnitDescription ud;
+ level = 1;
+ type = XML::getProperty(node, "type", "");
+ ud.conversion = XML::getProperty(node, "conversion", 1.0);
+ ud.mix = XML::getProperty(node, "mix", "no") == "yes";
+
+ struct UnitLevel bu;
+ bu.symbol = XML::getProperty(node, "base", "¤");
+ bu.count = 1;
+ bu.round = XML::getProperty(node, "round", 2);
+
+ ud.levels.push_back(bu);
+
+ for_each_xml_child_node(uLevel, node)
+ {
+ if (xmlStrEqual(uLevel->name, BAD_CAST "level"))
+ {
+ struct UnitLevel ul;
+ ul.symbol = XML::getProperty(uLevel, "symbol",
+ strprintf("¤%d",level));
+ ul.count = XML::getProperty(uLevel, "count", -1);
+ ul.round = XML::getProperty(uLevel, "round", bu.round);
+
+ if (ul.count > 0)
+ {
+ ud.levels.push_back(ul);
+ level++;
+ }
+ else
+ {
+ logger->log("Error bad unit count: %d for %s in %s",
+ ul.count, ul.symbol.c_str(), bu.symbol.c_str());
+ }
+ }
+ }
+
+ // Add one more level for saftey
+ struct UnitLevel ll;
+ ll.symbol = "";
+ ll.count = INT_MAX;
+ ll.round = 0;
+
+ ud.levels.push_back(ll);
+
+ if (type == "weight") units[UNIT_WEIGHT] = ud;
+ else if (type =="currency") units[UNIT_CURRENCY] = ud;
+ else logger->log("Error unknown unit type: %s", type.c_str());
+ }
+ }
+}
+
+std::string formatUnit(int value, int type)
+{
+ struct UnitDescription ud = units[type];
+ struct UnitLevel ul;
+ double amount = ud.conversion * value;
+
+ // Shortcut for 0
+ if (value == 0) {
+ ul = ud.levels[0];
+ return strprintf("0%s", ul.symbol.c_str());
+ } else {
+ // If only the first level is needed, act like mix if false
+ if (ud.mix && ud.levels.size() > 0 && ud.levels[1].count < amount)
+ {
+ std::string output;
+ struct UnitLevel pl = ud.levels[0];
+ ul = ud.levels[1];
+ int levelAmount = (int) amount;
+ int nextAmount;
+
+ levelAmount /= ul.count;
+
+ amount -= levelAmount * ul.count;
+
+ if (amount > 0) {
+ output = strprintf("%.*f%s", pl.round, amount,
+ pl.symbol.c_str());
+ }
+
+ for (unsigned int i = 2; i < ud.levels.size(); i++)
+ {
+ pl = ul;
+ ul = ud.levels[i];
+
+ nextAmount = levelAmount / ul.count;
+ levelAmount %= ul.count;
+
+ if (levelAmount > 0) output = strprintf("%d%s",
+ levelAmount, pl.symbol.c_str()) + output;
+
+ if (!nextAmount) break;
+ levelAmount = nextAmount;
+ }
+
+ return output;
+ }
+ else
+ {
+ for (unsigned int i = 0; i < ud.levels.size(); i++)
+ {
+ ul = ud.levels[i];
+ if (amount < ul.count && ul.count > 0) {
+ ul = ud.levels[i - 1];
+ break;
+ }
+ amount /= ul.count;
+ }
+
+ return strprintf("%.*f%s", ul.round, amount, ul.symbol.c_str());
+ }
+ }
+}
+
+std::string Units::formatCurrency(int value)
+{
+ return formatUnit(value, UNIT_CURRENCY);
+}
+
+std::string Units::formatWeight(int value)
+{
+ return formatUnit(value, UNIT_WEIGHT);
+}
diff --git a/src/units.h b/src/units.h
new file mode 100644
index 00000000..6aa07b70
--- /dev/null
+++ b/src/units.h
@@ -0,0 +1,46 @@
+/*
+ * Support for custom units
+ * Copyright (C) 2009 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 UNITS_H
+#define UNITS_H
+
+#include <string>
+
+class Units
+{
+ public:
+ /**
+ * Loads and parses the units.xml file (if found).
+ */
+ static void loadUnits();
+
+ /**
+ * Formats the given number in the correct currency format.
+ */
+ static std::string formatCurrency(int value);
+
+ /**
+ * Formats the given number in the correct weight/mass format.
+ */
+ static std::string formatWeight(int value);
+};
+
+#endif // UNITS_H
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/base64.h b/src/utils/base64.h
index c802207b..92c23016 100644
--- a/src/utils/base64.h
+++ b/src/utils/base64.h
@@ -27,10 +27,10 @@
+----------------------------------------------------------------------+
*/
-#ifndef _TMW_BASE64_H
-#define _TMW_BASE64_H
+#ifndef BASE64_H
+#define BASE64_H
extern unsigned char *php3_base64_encode(const unsigned char *, int, int *);
extern unsigned char *php3_base64_decode(const unsigned char *, int, int *);
-#endif /* _TMW_BASE64_H */
+#endif /* BASE64_H */
diff --git a/src/utils/dtor.h b/src/utils/dtor.h
index 9aa92c84..8dbc441f 100644
--- a/src/utils/dtor.h
+++ b/src/utils/dtor.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_UTILS_DTOR_H
-#define _TMW_UTILS_DTOR_H
+#ifndef UTILS_DTOR_H
+#define UTILS_DTOR_H
#include <algorithm>
#include <functional>
diff --git a/src/utils/gettext.h b/src/utils/gettext.h
index 0cd9114b..5281d491 100644
--- a/src/utils/gettext.h
+++ b/src/utils/gettext.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_UTILS_GETTEXT_H
-#define _TMW_UTILS_GETTEXT_H
+#ifndef UTILS_GETTEXT_H
+#define UTILS_GETTEXT_H
#ifdef HAVE_CONFIG_H
#include "config.h"
diff --git a/src/utils/minmax.h b/src/utils/minmax.h
deleted file mode 100644
index 7e3d84f2..00000000
--- a/src/utils/minmax.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * The Mana World
- * Copyright 2006 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 <cstdlib>
-
-/**
- * Returns a random numeric value that is larger than or equal min and smaller
- * than max
- */
-
-template <typename T> struct MinMax
-{
- void set(T min, T max)
- {
- minVal=min; maxVal=max;
- }
-
- void set(T val)
- {
- set(val, val);
- }
-
- bool operator+= (T arg)
- {
- minVal += arg;
- maxVal += arg;
- return true;
- }
-
- bool operator-= (T arg)
- {
- minVal -= arg;
- maxVal -= arg;
- return true;
- }
-
- bool operator*= (T arg)
- {
- minVal *= arg;
- maxVal *= arg;
- return true;
- }
-
- T value()
- {
- return (T)(minVal + (maxVal - minVal) * (rand() / ((double) RAND_MAX + 1)));
- }
-
- T minVal;
- T maxVal;
-};
diff --git a/src/utils/mutex.h b/src/utils/mutex.h
index 62c6b4e1..5e5df8f8 100644
--- a/src/utils/mutex.h
+++ b/src/utils/mutex.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2008 The Mana World 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef TMW_MUTEX_H
-#define TMW_MUTEX_H
+#ifndef MUTEX_H
+#define MUTEX_H
#include <SDL_thread.h>
@@ -94,4 +94,4 @@ inline MutexLocker::~MutexLocker()
mMutex->unlock();
}
-#endif // TMW_MUTEX_H
+#endif // MUTEX_H
diff --git a/src/utils/sha256.h b/src/utils/sha256.h
index 66152caf..0aa5ba1f 100644
--- a/src/utils/sha256.h
+++ b/src/utils/sha256.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_UTILS_SHA256_H_
-#define _TMW_UTILS_SHA256_H_
+#ifndef UTILS_SHA256_H
+#define UTILS_SHA256_H
#include <string>
@@ -32,4 +32,4 @@
*/
std::string sha256(const std::string& string);
-#endif // _TMW_UTILS_SHA256_H_
+#endif // UTILS_SHA256_H
diff --git a/src/utils/trim.h b/src/utils/stringutils.cpp
index a7c40ca2..04a54149 100644
--- a/src/utils/trim.h
+++ b/src/utils/stringutils.cpp
@@ -1,35 +1,29 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_UTILS_TRIM_H_
-#define _TMW_UTILS_TRIM_H_
+#include "stringutils.h"
-#include <string>
+#include <algorithm>
-/**
- * Trims spaces off the end and the beginning of the given string.
- *
- * @param str the string to trim spaces off
- */
-inline void trim(std::string &str)
+std::string &trim(std::string &str)
{
std::string::size_type pos = str.find_last_not_of(' ');
if (pos != std::string::npos)
@@ -46,6 +40,24 @@ inline void trim(std::string &str)
// There is nothing else but whitespace in the string
str.clear();
}
+ return str;
+}
+
+std::string &toLower(std::string &str)
+{
+ std::transform(str.begin(), str.end(), str.begin(), tolower);
+ return str;
}
-#endif
+const 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;
+}
diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h
new file mode 100644
index 00000000..8b8b7bc2
--- /dev/null
+++ b/src/utils/stringutils.h
@@ -0,0 +1,68 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 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 UTILS_STRINGUTILS_H
+#define UTILS_STRINGUTILS_H
+
+#include <string>
+#include <sstream>
+
+/**
+ * Trims spaces off the end and the beginning of the given string.
+ *
+ * @param str the string to trim spaces off
+ * @return a reference to the trimmed string
+ */
+std::string &trim(std::string &str);
+
+/**
+ * Converts the given string to lower case.
+ *
+ * @param str the string to convert to lower case
+ * @return a reference to the given string converted to lower case
+ */
+std::string &toLower(std::string &str);
+
+/**
+ * Converts the given value to a string using std::stringstream.
+ *
+ * @param arg the value to convert to a string
+ * @return the string representation of arg
+ */
+template<typename T> std::string toString(const T &arg)
+{
+ std::stringstream ss;
+ ss << arg;
+ return ss.str();
+}
+
+/**
+ * Converts the given IP address to a string.
+ *
+ * The returned string is statically allocated, and shouldn't be freed. It is
+ * changed upon the next use of this method.
+ *
+ * @param address the address to convert to a string
+ * @return the string representation of the address
+ */
+const char *ipToString(int address);
+
+#endif // UTILS_STRINGUTILS_H
diff --git a/src/utils/strprintf.cpp b/src/utils/strprintf.cpp
index c5d7a595..bed4a7c4 100644
--- a/src/utils/strprintf.cpp
+++ b/src/utils/strprintf.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/utils/strprintf.h b/src/utils/strprintf.h
index 382ab6e0..78e7a04c 100644
--- a/src/utils/strprintf.h
+++ b/src/utils/strprintf.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_UTILS_STRPRINTF_H
-#define _TMW_UTILS_STRPRINTF_H
+#ifndef UTILS_STRPRINTF_H
+#define UTILS_STRPRINTF_H
#include <string>
diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp
index 05df9f1d..d5dd54be 100644
--- a/src/utils/xml.cpp
+++ b/src/utils/xml.cpp
@@ -1,26 +1,28 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "xml.h"
+
#include "../log.h"
+
#include "../resources/resourcemanager.h"
namespace XML
diff --git a/src/utils/xml.h b/src/utils/xml.h
index d0aba62e..76a63ff4 100644
--- a/src/utils/xml.h
+++ b/src/utils/xml.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2004 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_XML_H
-#define _TMW_XML_H
+#ifndef XML_H
+#define XML_H
#include <libxml/tree.h>
diff --git a/src/vector.cpp b/src/vector.cpp
index 7d5f055a..9b573e88 100644
--- a/src/vector.cpp
+++ b/src/vector.cpp
@@ -1,21 +1,21 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/src/vector.h b/src/vector.h
index f32b201a..6dd461ac 100644
--- a/src/vector.h
+++ b/src/vector.h
@@ -1,26 +1,26 @@
/*
* The Mana World
- * Copyright 2007 The Mana World Development Team
+ * Copyright (C) 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
+ * 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.
*
- * The Mana World is distributed in the hope that it will be useful,
+ * 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 The Mana World; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _TMW_VECTOR_H_
-#define _TMW_VECTOR_H_
+#ifndef VECTOR_H
+#define VECTOR_H
#include <math.h>
@@ -187,4 +187,4 @@ class Vector
*/
std::ostream& operator <<(std::ostream &os, const Vector &v);
-#endif // _TMW_VECTOR_H_
+#endif // VECTOR_H