summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt47
-rw-r--r--src/Makefile.am49
-rw-r--r--src/actor.cpp58
-rw-r--r--src/actor.h128
-rw-r--r--src/actorsprite.cpp478
-rw-r--r--src/actorsprite.h248
-rw-r--r--src/actorspritelistener.h (renamed from src/flooritemmanager.h)46
-rw-r--r--src/actorspritemanager.cpp315
-rw-r--r--src/actorspritemanager.h (renamed from src/beingmanager.h)80
-rw-r--r--src/animatedsprite.cpp56
-rw-r--r--src/animatedsprite.h57
-rw-r--r--src/being.cpp866
-rw-r--r--src/being.h385
-rw-r--r--src/beingmanager.cpp296
-rw-r--r--src/chatlog.cpp176
-rw-r--r--src/chatlog.h73
-rw-r--r--src/client.cpp86
-rw-r--r--src/client.h1
-rw-r--r--src/commandhandler.cpp4
-rw-r--r--src/compoundsprite.cpp367
-rw-r--r--src/compoundsprite.h105
-rw-r--r--src/configuration.cpp120
-rw-r--r--src/configuration.h28
-rw-r--r--src/defaults.cpp182
-rw-r--r--src/defaults.h34
-rw-r--r--src/event.cpp187
-rw-r--r--src/event.h207
-rw-r--r--src/flooritem.cpp57
-rw-r--r--src/flooritem.h76
-rw-r--r--src/flooritemmanager.cpp80
-rw-r--r--src/game.cpp102
-rw-r--r--src/graphics.cpp10
-rw-r--r--src/graphics.h12
-rw-r--r--src/gui/beingpopup.cpp12
-rw-r--r--src/gui/beingpopup.h4
-rw-r--r--src/gui/buy.cpp13
-rw-r--r--src/gui/buy.h5
-rw-r--r--src/gui/buysell.cpp7
-rw-r--r--src/gui/buysell.h5
-rw-r--r--src/gui/charcreatedialog.cpp2
-rw-r--r--src/gui/charcreatedialog.h4
-rw-r--r--src/gui/charselectdialog.cpp6
-rw-r--r--src/gui/charselectdialog.h2
-rw-r--r--src/gui/chat.cpp66
-rw-r--r--src/gui/chat.h24
-rw-r--r--src/gui/emotepopup.cpp5
-rw-r--r--src/gui/equipmentwindow.cpp2
-rw-r--r--src/gui/gui.cpp8
-rw-r--r--src/gui/help.cpp4
-rw-r--r--src/gui/inventorywindow.cpp37
-rw-r--r--src/gui/inventorywindow.h18
-rw-r--r--src/gui/itempopup.cpp10
-rw-r--r--src/gui/minimap.cpp71
-rw-r--r--src/gui/ministatus.cpp148
-rw-r--r--src/gui/ministatus.h21
-rw-r--r--src/gui/npcdialog.cpp205
-rw-r--r--src/gui/npcdialog.h18
-rw-r--r--src/gui/npcpostdialog.cpp20
-rw-r--r--src/gui/npcpostdialog.h5
-rw-r--r--src/gui/outfitwindow.cpp13
-rw-r--r--src/gui/popupmenu.cpp54
-rw-r--r--src/gui/recorder.cpp12
-rw-r--r--src/gui/register.h2
-rw-r--r--src/gui/sell.cpp12
-rw-r--r--src/gui/sell.h5
-rw-r--r--src/gui/serverdialog.cpp11
-rw-r--r--src/gui/setup_audio.cpp14
-rw-r--r--src/gui/setup_colors.cpp5
-rw-r--r--src/gui/setup_joystick.cpp2
-rw-r--r--src/gui/setup_players.cpp33
-rw-r--r--src/gui/setup_players.h3
-rw-r--r--src/gui/setup_video.cpp68
-rw-r--r--src/gui/skilldialog.cpp20
-rw-r--r--src/gui/skilldialog.h4
-rw-r--r--src/gui/socialwindow.cpp59
-rw-r--r--src/gui/specialswindow.cpp179
-rw-r--r--src/gui/specialswindow.h20
-rw-r--r--src/gui/speechbubble.cpp6
-rw-r--r--src/gui/speechbubble.h4
-rw-r--r--src/gui/statuswindow.cpp266
-rw-r--r--src/gui/statuswindow.h14
-rw-r--r--src/gui/textpopup.cpp6
-rw-r--r--src/gui/trade.cpp19
-rw-r--r--src/gui/updatewindow.cpp2
-rw-r--r--src/gui/viewport.cpp101
-rw-r--r--src/gui/viewport.h12
-rw-r--r--src/gui/widgets/avatarlistbox.cpp2
-rw-r--r--src/gui/widgets/browserbox.cpp4
-rw-r--r--src/gui/widgets/button.cpp6
-rw-r--r--src/gui/widgets/chattab.cpp14
-rw-r--r--src/gui/widgets/chattab.h17
-rw-r--r--src/gui/widgets/checkbox.cpp6
-rw-r--r--src/gui/widgets/dropdown.cpp6
-rw-r--r--src/gui/widgets/emoteshortcutcontainer.cpp8
-rw-r--r--src/gui/widgets/itemcontainer.cpp2
-rw-r--r--src/gui/widgets/itemshortcutcontainer.cpp18
-rw-r--r--src/gui/widgets/label.cpp5
-rw-r--r--src/gui/widgets/listbox.cpp7
-rw-r--r--src/gui/widgets/playerbox.cpp25
-rw-r--r--src/gui/widgets/playerbox.h8
-rw-r--r--src/gui/widgets/popup.cpp2
-rw-r--r--src/gui/widgets/progressbar.cpp6
-rw-r--r--src/gui/widgets/progressindicator.cpp3
-rw-r--r--src/gui/widgets/radiobutton.cpp7
-rw-r--r--src/gui/widgets/resizegrip.cpp7
-rw-r--r--src/gui/widgets/scrollarea.cpp13
-rw-r--r--src/gui/widgets/shoplistbox.cpp6
-rw-r--r--src/gui/widgets/slider.cpp7
-rw-r--r--src/gui/widgets/tab.cpp6
-rw-r--r--src/gui/widgets/table.cpp7
-rw-r--r--src/gui/widgets/textbox.cpp2
-rw-r--r--src/gui/widgets/textfield.cpp8
-rw-r--r--src/gui/widgets/textpreview.cpp4
-rw-r--r--src/gui/widgets/whispertab.cpp11
-rw-r--r--src/gui/widgets/whispertab.h2
-rw-r--r--src/gui/widgets/window.cpp6
-rw-r--r--src/gui/windowmenu.cpp2
-rw-r--r--src/guild.cpp9
-rw-r--r--src/imageparticle.cpp10
-rw-r--r--src/imageparticle.h2
-rw-r--r--src/imagesprite.cpp44
-rw-r--r--src/imagesprite.h73
-rw-r--r--src/item.cpp9
-rw-r--r--src/itemshortcut.cpp4
-rw-r--r--src/joystick.cpp10
-rw-r--r--src/listener.cpp43
-rw-r--r--src/listener.h45
-rw-r--r--src/localplayer.cpp462
-rw-r--r--src/localplayer.h254
-rw-r--r--src/main.cpp8
-rw-r--r--src/map.cpp161
-rw-r--r--src/map.h49
-rw-r--r--src/monster.cpp203
-rw-r--r--src/monster.h98
-rw-r--r--src/net/adminhandler.h4
-rw-r--r--src/net/charhandler.h13
-rw-r--r--src/net/chathandler.h4
-rw-r--r--src/net/download.cpp4
-rw-r--r--src/net/gamehandler.h11
-rw-r--r--src/net/generalhandler.h6
-rw-r--r--src/net/guildhandler.h5
-rw-r--r--src/net/inventoryhandler.h4
-rw-r--r--src/net/logindata.h2
-rw-r--r--src/net/manaserv/beinghandler.cpp46
-rw-r--r--src/net/manaserv/buysellhandler.cpp14
-rw-r--r--src/net/manaserv/charhandler.cpp17
-rw-r--r--src/net/manaserv/charhandler.h6
-rw-r--r--src/net/manaserv/chathandler.cpp40
-rw-r--r--src/net/manaserv/connection.cpp2
-rw-r--r--src/net/manaserv/connection.h6
-rw-r--r--src/net/manaserv/defines.h76
-rw-r--r--src/net/manaserv/effecthandler.cpp4
-rw-r--r--src/net/manaserv/gamehandler.cpp10
-rw-r--r--src/net/manaserv/gamehandler.h9
-rw-r--r--src/net/manaserv/generalhandler.cpp51
-rw-r--r--src/net/manaserv/generalhandler.h10
-rw-r--r--src/net/manaserv/guildhandler.cpp19
-rw-r--r--src/net/manaserv/guildhandler.h2
-rw-r--r--src/net/manaserv/inventoryhandler.cpp18
-rw-r--r--src/net/manaserv/itemhandler.cpp9
-rw-r--r--src/net/manaserv/network.cpp2
-rw-r--r--src/net/manaserv/npchandler.cpp232
-rw-r--r--src/net/manaserv/npchandler.h31
-rw-r--r--src/net/manaserv/partyhandler.cpp17
-rw-r--r--src/net/manaserv/partyhandler.h4
-rw-r--r--src/net/manaserv/playerhandler.cpp84
-rw-r--r--src/net/manaserv/tradehandler.cpp27
-rw-r--r--src/net/npchandler.h17
-rw-r--r--src/net/partyhandler.h10
-rw-r--r--src/net/playerhandler.h4
-rw-r--r--src/net/specialhandler.h4
-rw-r--r--src/net/tmwa/adminhandler.cpp9
-rw-r--r--src/net/tmwa/beinghandler.cpp213
-rw-r--r--src/net/tmwa/buysellhandler.cpp27
-rw-r--r--src/net/tmwa/charserverhandler.cpp57
-rw-r--r--src/net/tmwa/charserverhandler.h8
-rw-r--r--src/net/tmwa/chathandler.cpp120
-rw-r--r--src/net/tmwa/chathandler.h6
-rw-r--r--src/net/tmwa/gamehandler.cpp33
-rw-r--r--src/net/tmwa/gamehandler.h14
-rw-r--r--src/net/tmwa/generalhandler.cpp82
-rw-r--r--src/net/tmwa/generalhandler.h12
-rw-r--r--src/net/tmwa/gui/guildtab.cpp10
-rw-r--r--src/net/tmwa/gui/guildtab.h2
-rw-r--r--src/net/tmwa/gui/partytab.cpp10
-rw-r--r--src/net/tmwa/gui/partytab.h2
-rw-r--r--src/net/tmwa/guildhandler.cpp8
-rw-r--r--src/net/tmwa/guildhandler.h2
-rw-r--r--src/net/tmwa/inventoryhandler.cpp11
-rw-r--r--src/net/tmwa/inventoryhandler.h10
-rw-r--r--src/net/tmwa/itemhandler.cpp8
-rw-r--r--src/net/tmwa/npchandler.cpp219
-rw-r--r--src/net/tmwa/npchandler.h32
-rw-r--r--src/net/tmwa/partyhandler.cpp42
-rw-r--r--src/net/tmwa/partyhandler.h4
-rw-r--r--src/net/tmwa/playerhandler.cpp234
-rw-r--r--src/net/tmwa/specialhandler.cpp13
-rw-r--r--src/net/tmwa/token.h2
-rw-r--r--src/net/tmwa/tradehandler.cpp54
-rw-r--r--src/net/tradehandler.h4
-rw-r--r--src/npc.cpp108
-rw-r--r--src/npc.h73
-rw-r--r--src/particle.cpp25
-rw-r--r--src/particle.h52
-rw-r--r--src/party.cpp9
-rw-r--r--src/player.cpp360
-rw-r--r--src/player.h161
-rw-r--r--src/playerinfo.cpp405
-rw-r--r--src/playerinfo.h273
-rw-r--r--src/playerrelations.cpp26
-rw-r--r--src/playerrelations.h3
-rw-r--r--src/resources/beinginfo.cpp107
-rw-r--r--src/resources/beinginfo.h132
-rw-r--r--src/resources/emotedb.cpp5
-rw-r--r--src/resources/itemdb.cpp56
-rw-r--r--src/resources/iteminfo.cpp30
-rw-r--r--src/resources/iteminfo.h48
-rw-r--r--src/resources/mapreader.cpp8
-rw-r--r--src/resources/monsterdb.cpp76
-rw-r--r--src/resources/monsterdb.h9
-rw-r--r--src/resources/monsterinfo.cpp100
-rw-r--r--src/resources/monsterinfo.h106
-rw-r--r--src/resources/npcdb.cpp54
-rw-r--r--src/resources/npcdb.h22
-rw-r--r--src/resources/specialdb.cpp132
-rw-r--r--src/resources/specialdb.h72
-rw-r--r--src/resources/spritedef.cpp128
-rw-r--r--src/resources/spritedef.h83
-rw-r--r--src/resources/theme.cpp (renamed from src/gui/theme.cpp)12
-rw-r--r--src/resources/theme.h (renamed from src/gui/theme.h)0
-rw-r--r--src/resources/userpalette.cpp (renamed from src/gui/userpalette.cpp)2
-rw-r--r--src/resources/userpalette.h (renamed from src/gui/userpalette.h)0
-rw-r--r--src/resources/wallpaper.cpp18
-rw-r--r--src/simpleanimation.cpp48
-rw-r--r--src/simpleanimation.h3
-rw-r--r--src/sound.cpp6
-rw-r--r--src/sprite.h89
-rw-r--r--src/statuseffect.cpp15
-rw-r--r--src/statuseffect.h4
-rw-r--r--src/text.cpp19
-rw-r--r--src/text.h6
-rw-r--r--src/textparticle.cpp6
-rw-r--r--src/textparticle.h2
-rw-r--r--src/textrenderer.h2
-rw-r--r--src/utils/copynpaste.cpp1
-rw-r--r--src/utils/stringutils.cpp16
-rw-r--r--src/utils/stringutils.h8
-rw-r--r--src/utils/xml.cpp19
-rw-r--r--src/utils/xml.h13
-rw-r--r--src/variabledata.h100
250 files changed, 7973 insertions, 5546 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 38589505..6963663d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -301,8 +301,6 @@ SET(SRCS
gui/textdialog.h
gui/textpopup.cpp
gui/textpopup.h
- gui/theme.cpp
- gui/theme.h
gui/trade.cpp
gui/trade.h
gui/truetypefont.cpp
@@ -311,8 +309,6 @@ SET(SRCS
gui/unregisterdialog.h
gui/updatewindow.cpp
gui/updatewindow.h
- gui/userpalette.cpp
- gui/userpalette.h
gui/viewport.cpp
gui/viewport.h
gui/windowmenu.cpp
@@ -353,6 +349,8 @@ SET(SRCS
resources/ambientoverlay.h
resources/animation.cpp
resources/animation.h
+ resources/beinginfo.cpp
+ resources/beinginfo.h
resources/colordb.cpp
resources/colordb.h
resources/dye.cpp
@@ -375,8 +373,6 @@ SET(SRCS
resources/mapreader.h
resources/monsterdb.cpp
resources/monsterdb.h
- resources/monsterinfo.cpp
- resources/monsterinfo.h
resources/music.cpp
resources/music.h
resources/npcdb.cpp
@@ -387,8 +383,14 @@ SET(SRCS
resources/resourcemanager.h
resources/soundeffect.h
resources/soundeffect.cpp
+ resources/specialdb.cpp
+ resources/specialdb.h
resources/spritedef.h
resources/spritedef.cpp
+ resources/theme.cpp
+ resources/theme.h
+ resources/userpalette.cpp
+ resources/userpalette.h
resources/wallpaper.cpp
resources/wallpaper.h
utils/base64.cpp
@@ -409,6 +411,13 @@ SET(SRCS
utils/xml.h
utils/zlib.cpp
utils/zlib.h
+ actor.cpp
+ actor.h
+ actorsprite.cpp
+ actorsprite.h
+ actorspritelistener.h
+ actorspritemanager.cpp
+ actorspritemanager.h
animatedsprite.cpp
animatedsprite.h
animationparticle.cpp
@@ -417,8 +426,8 @@ SET(SRCS
avatar.h
being.cpp
being.h
- beingmanager.cpp
- beingmanager.h
+ chatlog.cpp
+ chatlog.h
client.cpp
client.h
channel.cpp
@@ -427,18 +436,22 @@ SET(SRCS
channelmanager.h
commandhandler.cpp
commandhandler.h
+ compoundsprite.cpp
+ compoundsprite.h
configlistener.h
configuration.cpp
configuration.h
+ defaults.cpp
+ defaults.h
effectmanager.cpp
effectmanager.h
emoteshortcut.cpp
emoteshortcut.h
equipment.h
+ event.cpp
+ event.h
flooritem.cpp
flooritem.h
- flooritemmanager.cpp
- flooritemmanager.h
game.cpp
game.h
graphics.cpp
@@ -448,6 +461,8 @@ SET(SRCS
guild.h
imageparticle.cpp
imageparticle.h
+ imagesprite.cpp
+ imagesprite.h
inventory.cpp
inventory.h
item.cpp
@@ -458,6 +473,8 @@ SET(SRCS
joystick.h
keyboardconfig.cpp
keyboardconfig.h
+ listener.cpp
+ listener.h
localplayer.cpp
localplayer.h
log.cpp
@@ -466,10 +483,6 @@ SET(SRCS
main.h
map.cpp
map.h
- monster.cpp
- monster.h
- npc.cpp
- npc.h
openglgraphics.cpp
openglgraphics.h
particle.cpp
@@ -481,8 +494,8 @@ SET(SRCS
particleemitterprop.h
party.cpp
party.h
- player.cpp
- player.h
+ playerinfo.cpp
+ playerinfo.h
playerrelations.cpp
playerrelations.h
position.cpp
@@ -509,6 +522,7 @@ SET(SRCS
tileset.h
units.cpp
units.h
+ variabledata.h
vector.cpp
vector.h
)
@@ -575,6 +589,7 @@ SET(SRCS_MANA
net/manaserv/chathandler.h
net/manaserv/connection.cpp
net/manaserv/connection.h
+ net/manaserv/defines.h
net/manaserv/effecthandler.cpp
net/manaserv/effecthandler.h
net/manaserv/gamehandler.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index 1f2391a8..fa72eb08 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -193,8 +193,6 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
gui/textdialog.h \
gui/textpopup.cpp \
gui/textpopup.h \
- gui/theme.cpp \
- gui/theme.h \
gui/trade.cpp \
gui/trade.h \
gui/truetypefont.cpp \
@@ -203,8 +201,6 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
gui/unregisterdialog.h \
gui/updatewindow.cpp \
gui/updatewindow.h \
- gui/userpalette.cpp \
- gui/userpalette.h \
gui/viewport.cpp \
gui/viewport.h \
gui/windowmenu.cpp \
@@ -228,9 +224,9 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
net/messagein.h \
net/messageout.cpp \
net/messageout.h \
- net/npchandler.h \
net/net.cpp \
net/net.h \
+ net/npchandler.h \
net/partyhandler.h \
net/playerhandler.h \
net/serverinfo.h \
@@ -245,6 +241,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
resources/ambientoverlay.h \
resources/animation.cpp \
resources/animation.h \
+ resources/beinginfo.cpp \
+ resources/beinginfo.h \
resources/colordb.cpp \
resources/colordb.h \
resources/dye.cpp \
@@ -267,8 +265,6 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
resources/mapreader.h \
resources/monsterdb.cpp \
resources/monsterdb.h \
- resources/monsterinfo.cpp \
- resources/monsterinfo.h \
resources/music.cpp \
resources/music.h \
resources/npcdb.cpp \
@@ -279,8 +275,14 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
resources/resourcemanager.h \
resources/soundeffect.h \
resources/soundeffect.cpp \
+ resources/specialdb.h \
+ resources/specialdb.cpp \
resources/spritedef.h \
resources/spritedef.cpp \
+ resources/theme.cpp \
+ resources/theme.h \
+ resources/userpalette.cpp \
+ resources/userpalette.h \
resources/wallpaper.cpp \
resources/wallpaper.h \
utils/base64.cpp \
@@ -303,6 +305,13 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
utils/xml.h \
utils/zlib.cpp \
utils/zlib.h \
+ actor.cpp \
+ actor.h \
+ actorsprite.cpp \
+ actorsprite.h \
+ actorspritelistener.h \
+ actorspritemanager.cpp \
+ actorspritemanager.h \
animatedsprite.cpp \
animatedsprite.h \
animationparticle.cpp \
@@ -311,8 +320,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
avatar.h \
being.cpp \
being.h \
- beingmanager.cpp \
- beingmanager.h \
+ chatlog.cpp \
+ chatlog.h \
client.cpp \
client.h \
channel.cpp \
@@ -321,18 +330,22 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
channelmanager.h \
commandhandler.cpp \
commandhandler.h \
+ compoundsprite.cpp \
+ compoundsprite.h \
configlistener.h \
configuration.cpp \
configuration.h \
+ defaults.cpp \
+ defaults.h \
effectmanager.cpp \
effectmanager.h \
emoteshortcut.cpp \
emoteshortcut.h \
equipment.h \
+ event.cpp \
+ event.h \
flooritem.cpp \
flooritem.h \
- flooritemmanager.cpp \
- flooritemmanager.h \
game.cpp \
game.h \
graphics.cpp \
@@ -342,6 +355,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
guild.h \
imageparticle.cpp \
imageparticle.h \
+ imagesprite.cpp \
+ imagesprite.h \
inventory.cpp \
inventory.h \
item.cpp \
@@ -352,6 +367,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
joystick.h \
keyboardconfig.cpp \
keyboardconfig.h \
+ listener.cpp \
+ listener.h \
localplayer.cpp \
localplayer.h \
log.cpp \
@@ -360,10 +377,6 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
main.h \
map.cpp\
map.h \
- monster.cpp\
- monster.h \
- npc.cpp \
- npc.h \
openglgraphics.cpp\
openglgraphics.h \
particle.cpp \
@@ -375,8 +388,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
particleemitterprop.h \
party.cpp \
party.h \
- player.cpp \
- player.h \
+ playerinfo.cpp \
+ playerinfo.h \
playerrelations.cpp \
playerrelations.h \
position.cpp \
@@ -403,6 +416,7 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
tileset.h \
units.cpp \
units.h \
+ variabledata.h \
vector.cpp \
vector.h \
winver.h
@@ -420,6 +434,7 @@ mana_SOURCES += \
net/manaserv/chathandler.h \
net/manaserv/connection.cpp \
net/manaserv/connection.h \
+ net/manaserv/defines.h \
net/manaserv/effecthandler.cpp \
net/manaserv/effecthandler.h \
net/manaserv/gamehandler.cpp \
diff --git a/src/actor.cpp b/src/actor.cpp
new file mode 100644
index 00000000..44a89600
--- /dev/null
+++ b/src/actor.cpp
@@ -0,0 +1,58 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "actor.h"
+
+#include "map.h"
+
+#include "resources/image.h"
+#include "resources/resourcemanager.h"
+
+Actor::Actor():
+ mMap(NULL)
+{}
+
+Actor::~Actor()
+{
+ setMap(NULL);
+}
+
+void Actor::setMap(Map *map)
+{
+ // Remove Actor from potential previous map
+ if (mMap)
+ mMap->removeActor(mMapActor);
+
+ mMap = map;
+
+ // Add Actor to potential new map
+ if (mMap)
+ mMapActor = mMap->addActor(this);
+}
+
+int Actor::getTileX() const
+{
+ return getPixelX() / mMap->getTileWidth();
+}
+
+int Actor::getTileY() const
+{
+ return getPixelY() / mMap->getTileHeight();
+}
diff --git a/src/actor.h b/src/actor.h
new file mode 100644
index 00000000..367bcd75
--- /dev/null
+++ b/src/actor.h
@@ -0,0 +1,128 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ACTOR_H
+#define ACTOR_H
+
+#include "vector.h"
+
+#include <list>
+
+class Actor;
+class Graphics;
+class Image;
+class Map;
+
+typedef std::list<Actor*> Actors;
+
+class Actor
+{
+public:
+ Actor();
+
+ virtual ~Actor();
+
+ /**
+ * Draws the Actor to the given graphics context.
+ *
+ * Note: this function could be simplified if the graphics context
+ * would support setting a translation offset. It already does this
+ * partly with the clipping rectangle support.
+ */
+ virtual bool draw(Graphics *graphics, int offsetX, int offsetY) const = 0;
+
+ /**
+ * Returns the horizontal size of the actors graphical representation
+ * in pixels or 0 when it is undefined.
+ */
+ virtual int getWidth() const
+ { return 0; }
+
+ /**
+ * Returns the vertical size of the actors graphical representation
+ * in pixels or 0 when it is undefined.
+ */
+ virtual int getHeight() const
+ { return 0; }
+
+ /**
+ * Returns the pixel position of this actor.
+ */
+ const Vector &getPosition() const
+ { return mPos; }
+
+ /**
+ * Sets the pixel position of this actor.
+ */
+ virtual void setPosition(const Vector &pos)
+ { mPos = pos; }
+
+ /**
+ * Returns the pixels X coordinate of the actor.
+ */
+ int getPixelX() const
+ { return (int) mPos.x; }
+
+ /**
+ * Returns the pixel Y coordinate of the actor.
+ */
+ virtual int getPixelY() const
+ { return (int) mPos.y; }
+
+ /**
+ * Returns the x coordinate in tiles of the actor.
+ */
+ virtual int getTileX() const;
+
+ /**
+ * Returns the y coordinate in tiles of the actor.
+ */
+ virtual int getTileY() const;
+
+ /**
+ * Returns the number of Image layers used to draw the actor.
+ */
+ virtual int getNumberOfLayers() const
+ { return 0; }
+
+ /**
+ * Returns the current alpha value used to draw the actor.
+ */
+ virtual float getAlpha() const = 0;
+
+ /**
+ * Sets the alpha value used to draw the actor.
+ */
+ virtual void setAlpha(float alpha) = 0;
+
+ void setMap(Map *map);
+
+ Map* getMap() const
+ { return mMap; }
+
+protected:
+ Map *mMap;
+ Vector mPos; /**< Position in pixels relative to map. */
+
+private:
+ Actors::iterator mMapActor;
+};
+
+#endif // ACTOR_H
diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp
new file mode 100644
index 00000000..cdc23dc6
--- /dev/null
+++ b/src/actorsprite.cpp
@@ -0,0 +1,478 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "actorsprite.h"
+#include "actorspritelistener.h"
+
+#include "client.h"
+#include "effectmanager.h"
+#include "event.h"
+#include "imagesprite.h"
+#include "localplayer.h"
+#include "log.h"
+#include "simpleanimation.h"
+#include "sound.h"
+#include "statuseffect.h"
+
+#include "net/net.h"
+
+#include "resources/image.h"
+#include "resources/imageset.h"
+#include "resources/resourcemanager.h"
+#include "resources/theme.h"
+
+#include <cassert>
+
+#define EFFECTS_FILE "effects.xml"
+
+ImageSet *ActorSprite::targetCursorImages[2][NUM_TC];
+SimpleAnimation *ActorSprite::targetCursor[2][NUM_TC];
+bool ActorSprite::loaded = false;
+
+ActorSprite::ActorSprite(int id):
+ mId(id),
+ mStunMode(0),
+ mStatusParticleEffects(&mStunParticleEffects, false),
+ mChildParticleEffects(&mStatusParticleEffects, false),
+ mMustResetParticles(false),
+ mUsedTargetCursor(NULL)
+{}
+
+ActorSprite::~ActorSprite()
+{
+ setMap(NULL);
+
+ mUsedTargetCursor = NULL;
+
+ if (player_node && player_node->getTarget() == this)
+ player_node->setTarget(NULL);
+
+ // Notify listeners of the destruction.
+ for (ActorSpriteListenerIterator iter = mActorSpriteListeners.begin(),
+ end = mActorSpriteListeners.end(); iter != end; ++iter)
+ (*iter)->actorSpriteDestroyed(*this);
+}
+
+bool ActorSprite::draw(Graphics *graphics, int offsetX, int offsetY) const
+{
+ // TODO: Eventually, we probably should fix all sprite offsets so that
+ // these translations aren't necessary anymore. The sprites know
+ // best where their base point should be.
+ const int px = getPixelX() + offsetX - 16;
+ // Temporary fix to the Y offset.
+ const int py = getPixelY() + offsetY -
+ ((Net::getNetworkType() == ServerInfo::MANASERV) ? 15 : 32);
+
+ if (mUsedTargetCursor)
+ {
+ mUsedTargetCursor->reset();
+ mUsedTargetCursor->update(tick_time * MILLISECONDS_IN_A_TICK);
+ mUsedTargetCursor->draw(graphics, px, py);
+ }
+
+ return drawSpriteAt(graphics, px, py);
+}
+
+bool ActorSprite::drawSpriteAt(Graphics *graphics, int x, int y) const
+{
+ return CompoundSprite::draw(graphics, x, y);
+}
+
+void ActorSprite::logic()
+{
+ // Update sprite animations
+ update(tick_time * MILLISECONDS_IN_A_TICK);
+
+ // 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
+ mChildParticleEffects.moveTo(mPos.x, mPos.y);
+}
+
+void ActorSprite::actorLogic()
+{
+}
+
+void ActorSprite::setMap(Map* map)
+{
+ Actor::setMap(map);
+
+ // Clear particle effect list because child particles became invalid
+ mChildParticleEffects.clear();
+ mMustResetParticles = true; // Reset status particles on next redraw
+}
+
+void ActorSprite::controlParticle(Particle *particle)
+{
+ mChildParticleEffects.addLocally(particle);
+}
+
+void ActorSprite::setTargetType(TargetCursorType type)
+{
+ if (type == TCT_NONE)
+ untarget();
+ else
+ mUsedTargetCursor = targetCursor[type][getTargetCursorSize()];
+}
+
+struct EffectDescription {
+ std::string mGFXEffect;
+ std::string mSFXEffect;
+};
+
+static EffectDescription *default_effect = NULL;
+static std::map<int, EffectDescription *> effects;
+static bool effects_initialized = false;
+
+static EffectDescription *getEffectDescription(xmlNodePtr node, int *id)
+{
+ EffectDescription *ed = new EffectDescription;
+
+ *id = atoi(XML::getProperty(node, "id", "-1").c_str());
+ ed->mSFXEffect = XML::getProperty(node, "audio", "");
+ ed->mGFXEffect = XML::getProperty(node, "particle", "");
+
+ return ed;
+}
+
+static EffectDescription *getEffectDescription(int effectId)
+{
+ if (!effects_initialized)
+ {
+ XML::Document doc(EFFECTS_FILE);
+ xmlNodePtr root = doc.rootNode();
+
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "being-effects"))
+ {
+ logger->log("Error loading being effects file: "
+ EFFECTS_FILE);
+ return NULL;
+ }
+
+ for_each_xml_child_node(node, root)
+ {
+ int id;
+
+ if (xmlStrEqual(node->name, BAD_CAST "effect"))
+ {
+ EffectDescription *EffectDescription =
+ getEffectDescription(node, &id);
+ effects[id] = EffectDescription;
+ }
+ else if (xmlStrEqual(node->name, BAD_CAST "default"))
+ {
+ EffectDescription *effectDescription =
+ getEffectDescription(node, &id);
+
+ if (default_effect)
+ delete default_effect;
+
+ default_effect = effectDescription;
+ }
+ }
+
+ effects_initialized = true;
+ } // done initializing
+
+ EffectDescription *ed = effects[effectId];
+
+ return ed ? ed : default_effect;
+}
+
+void ActorSprite::setStatusEffect(int index, bool active)
+{
+ const bool wasActive = mStatusEffects.find(index) != mStatusEffects.end();
+
+ if (active != wasActive)
+ {
+ updateStatusEffect(index, active);
+ if (active)
+ mStatusEffects.insert(index);
+ else
+ mStatusEffects.erase(index);
+ }
+}
+
+void ActorSprite::setStatusEffectBlock(int offset, Uint16 newEffects)
+{
+ for (int i = 0; i < STATUS_EFFECTS; i++)
+ {
+ int index = StatusEffect::blockEffectIndexToEffectIndex(offset + i);
+
+ if (index != -1)
+ setStatusEffect(index, (newEffects & (1 << i)) > 0);
+ }
+}
+
+void ActorSprite::internalTriggerEffect(int effectId, bool sfx, bool gfx)
+{
+ logger->log("Special effect #%d on %s", effectId,
+ getId() == player_node->getId() ? "self" : "other");
+
+ EffectDescription *ed = getEffectDescription(effectId);
+
+ if (!ed)
+ {
+ logger->log("Unknown special effect and no default recorded");
+ return;
+ }
+
+ if (gfx && !ed->mGFXEffect.empty())
+ {
+ Particle *selfFX;
+
+ selfFX = particleEngine->addEffect(ed->mGFXEffect, 0, 0);
+ controlParticle(selfFX);
+ }
+
+ if (sfx && !ed->mSFXEffect.empty())
+ sound.playSfx(ed->mSFXEffect);
+}
+
+void ActorSprite::updateStunMode(int oldMode, int newMode)
+{
+ if (this == player_node)
+ {
+ Mana::Event event("Stun");
+ event.setInt("oldMode", oldMode);
+ event.setInt("newMode", newMode);
+ event.trigger("ActorSprite");
+ }
+
+ handleStatusEffect(StatusEffect::getStatusEffect(oldMode, false), -1);
+ handleStatusEffect(StatusEffect::getStatusEffect(newMode, true), -1);
+}
+
+void ActorSprite::updateStatusEffect(int index, bool newStatus)
+{
+ if (this == player_node)
+ {
+ Mana::Event event("UpdateStatusEffect");
+ event.setInt("index", index);
+ event.setBool("newStatus", newStatus);
+ event.trigger("ActorSprite");
+ }
+
+ handleStatusEffect(StatusEffect::getStatusEffect(index, newStatus), index);
+}
+
+void ActorSprite::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();
+
+ if (effectId >= 0)
+ {
+ mStatusParticleEffects.setLocally(effectId, particle);
+ }
+ else
+ {
+ mStunParticleEffects.clearLocally();
+ if (particle)
+ mStunParticleEffects.addLocally(particle);
+ }
+}
+
+void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display,
+ bool forceDisplay)
+{
+ clear();
+
+ SpriteRefs it, it_end;
+
+ for (it = display.sprites.begin(), it_end = display.sprites.end();
+ it != it_end; it++)
+ {
+ std::string file = "graphics/sprites/" + (*it)->sprite;
+ int variant = (*it)->variant;
+ addSprite(AnimatedSprite::load(file, variant));
+ }
+
+ // Ensure that something is shown, if desired
+ if (size() == 0 && forceDisplay)
+ {
+ if (display.image.empty())
+ addSprite(AnimatedSprite::load("graphics/sprites/error.xml"));
+ else
+ {
+ ResourceManager *resman = ResourceManager::getInstance();
+ std::string imagePath = "graphics/items/" + display.image;
+ Image *img = resman->getImage(imagePath);
+
+ if (!img)
+ img = Theme::getImageFromTheme("unknown-item.png");
+
+ addSprite(new ImageSprite(img));
+ }
+ }
+
+ mChildParticleEffects.clear();
+
+ //setup particle effects
+ if (Particle::enabled)
+ {
+ std::list<std::string>::const_iterator it, it_end;
+ for (it = display.particles.begin(), it_end = display.particles.end();
+ it != it_end; it++)
+ {
+ Particle *p = particleEngine->addEffect(*it, 0, 0);
+ controlParticle(p);
+ }
+ }
+
+ mMustResetParticles = true;
+}
+
+void ActorSprite::load()
+{
+ if (loaded)
+ unload();
+
+ initTargetCursor();
+
+ loaded = true;
+}
+
+void ActorSprite::unload()
+{
+ if (!loaded)
+ return;
+
+ cleanupTargetCursors();
+ loaded = false;
+}
+
+void ActorSprite::addActorSpriteListener(ActorSpriteListener *listener)
+{
+ mActorSpriteListeners.push_front(listener);
+}
+
+void ActorSprite::removeActorSpriteListener(ActorSpriteListener *listener)
+{
+ mActorSpriteListeners.remove(listener);
+}
+
+static const char *cursorType(int type)
+{
+ switch (type)
+ {
+ case ActorSprite::TCT_IN_RANGE:
+ return "in-range";
+ case ActorSprite::TCT_NORMAL:
+ return "normal";
+ default:
+ assert(false);
+ }
+}
+
+static const char *cursorSize(int size)
+{
+ switch (size)
+ {
+ case ActorSprite::TC_LARGE:
+ return "l";
+ case ActorSprite::TC_MEDIUM:
+ return "m";
+ case ActorSprite::TC_SMALL:
+ return "s";
+ default:
+ assert(false);
+ }
+}
+
+void ActorSprite::initTargetCursor()
+{
+ static std::string targetCursor = "graphics/target-cursor-%s-%s.png";
+ static int targetWidths[NUM_TC] = {44, 62, 82};
+ static int targetHeights[NUM_TC] = {35, 44, 60};
+
+ // Load target cursors
+ for (int size = TC_SMALL; size < NUM_TC; size++)
+ {
+ for (int type = TCT_NORMAL; type < NUM_TCT; type++)
+ {
+ loadTargetCursor(strprintf(targetCursor.c_str(), cursorType(type),
+ cursorSize(size)), targetWidths[size],
+ targetHeights[size], type, size);
+ }
+ }
+}
+
+void ActorSprite::cleanupTargetCursors()
+{
+ for (int size = TC_SMALL; size < NUM_TC; size++)
+ {
+ for (int type = TCT_NORMAL; type < NUM_TCT; type++)
+ {
+ delete targetCursor[type][size];
+ if (targetCursorImages[type][size])
+ targetCursorImages[type][size]->decRef();
+ }
+ }
+}
+
+void ActorSprite::loadTargetCursor(const std::string &filename,
+ int width, int height, int type, int size)
+{
+ assert(size > -1);
+ assert(size < 3);
+
+ ResourceManager *resman = ResourceManager::getInstance();
+ ImageSet *currentImageSet = resman->getImageSet(filename, width, height);
+
+ if (!currentImageSet)
+ {
+ logger->log("Error loading target cursor: %s", filename.c_str());
+ return;
+ }
+
+ 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)));
+ }
+
+ SimpleAnimation *currentCursor = new SimpleAnimation(anim);
+
+ targetCursorImages[type][size] = currentImageSet;
+ targetCursor[type][size] = currentCursor;
+}
diff --git a/src/actorsprite.h b/src/actorsprite.h
new file mode 100644
index 00000000..7cc91c53
--- /dev/null
+++ b/src/actorsprite.h
@@ -0,0 +1,248 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ACTORSPRITE_H
+#define ACTORSPRITE_H
+
+#include "actor.h"
+#include "compoundsprite.h"
+#include "map.h"
+#include "particlecontainer.h"
+
+#include <SDL_types.h>
+
+#include <set>
+#include <list>
+
+class SimpleAnimation;
+class StatusEffect;
+class ActorSpriteListener;
+
+class ActorSprite : public CompoundSprite, public Actor
+{
+public:
+ enum Type
+ {
+ UNKNOWN,
+ PLAYER,
+ NPC,
+ MONSTER,
+ FLOOR_ITEM
+ };
+
+ enum TargetCursorSize
+ {
+ TC_SMALL = 0,
+ TC_MEDIUM,
+ TC_LARGE,
+ NUM_TC
+ };
+
+ enum TargetCursorType
+ {
+ TCT_NONE = -1,
+ TCT_NORMAL = 0,
+ TCT_IN_RANGE,
+ NUM_TCT
+ };
+
+ ActorSprite(int id);
+
+ ~ActorSprite();
+
+ int getId() const
+ { return mId; }
+
+ void setId(int id) { mId = id; }
+
+ /**
+ * Returns the type of the ActorSprite.
+ */
+ virtual Type getType() const { return UNKNOWN; }
+
+ virtual bool draw(Graphics *graphics, int offsetX, int offsetY) const;
+
+ virtual bool drawSpriteAt(Graphics *graphics, int x, int y) const;
+
+ virtual void logic();
+
+ static void actorLogic();
+
+ void setMap(Map* map);
+
+ /**
+ * Gets the way the object blocks pathfinding for other objects
+ */
+ virtual Map::BlockType getBlockType() const
+ { return Map::BLOCKTYPE_NONE; }
+
+ /**
+ * Take control of a particle.
+ */
+ void controlParticle(Particle *particle);
+
+ /**
+ * Returns the required size of a target cursor for this being.
+ */
+ virtual TargetCursorSize getTargetCursorSize() const
+ { return TC_MEDIUM; }
+
+ /**
+ * Sets the target animation for this actor.
+ */
+ void setTargetType(TargetCursorType type);
+
+ /**
+ * Untargets the actor.
+ */
+ void untarget() { mUsedTargetCursor = NULL; }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Sets the actor'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);
+
+ virtual void setAlpha(float alpha)
+ { CompoundSprite::setAlpha(alpha); }
+
+ virtual float getAlpha() const
+ { return CompoundSprite::getAlpha(); }
+
+ virtual int getWidth() const
+ { return CompoundSprite::getWidth(); }
+
+ virtual int getHeight() const
+ { return CompoundSprite::getHeight(); }
+
+ static void load();
+
+ static void unload();
+
+ /**
+ * Add an ActorSprite listener.
+ */
+ void addActorSpriteListener(ActorSpriteListener *listener);
+
+ /**
+ * Remove an ActorSprite listener.
+ */
+ void removeActorSpriteListener(ActorSpriteListener *listener);
+
+protected:
+ /**
+ * Trigger visual effect, with components
+ *
+ * \param effectId ID of the effect to trigger
+ * \param sfx Whether to trigger sound effects
+ * \param gfx Whether to trigger graphical effects
+ */
+ void internalTriggerEffect(int effectId, bool sfx, bool gfx);
+
+ /**
+ * 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);
+
+ void setupSpriteDisplay(const SpriteDisplay &display,
+ bool forceDisplay = true);
+
+ int mId;
+ Uint16 mStunMode; /**< Stun mode; zero if not stunned */
+ std::set<int> mStatusEffects; /**< set of active status effects */
+
+ ParticleList mStunParticleEffects;
+ ParticleVector mStatusParticleEffects;
+ ParticleList mChildParticleEffects;
+
+private:
+ /** Reset particle status effects on next redraw? */
+ bool mMustResetParticles;
+
+ /** Load the target cursors into memory */
+ static void initTargetCursor();
+
+ /** Remove the target cursors from memory */
+ static void cleanupTargetCursors();
+
+ /**
+ * Helper function for loading target cursors
+ */
+ static void loadTargetCursor(const std::string &filename,
+ int width, int height, int type, int size);
+
+ /** Images of the target cursor. */
+ static ImageSet *targetCursorImages[NUM_TCT][NUM_TC];
+
+ /** Animated target cursors. */
+ static SimpleAnimation *targetCursor[NUM_TCT][NUM_TC];
+
+ static bool loaded;
+
+ /** Target cursor being used */
+ SimpleAnimation *mUsedTargetCursor;
+
+ typedef std::list<ActorSpriteListener*> ActorSpriteListeners;
+ typedef ActorSpriteListeners::iterator ActorSpriteListenerIterator;
+ ActorSpriteListeners mActorSpriteListeners;
+};
+
+#endif // ACTORSPRITE_H
diff --git a/src/flooritemmanager.h b/src/actorspritelistener.h
index 62ca8dc2..994494f4 100644
--- a/src/flooritemmanager.h
+++ b/src/actorspritelistener.h
@@ -1,7 +1,6 @@
/*
* The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2010 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -19,36 +18,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef FLOORITEMMANAGER_H
-#define FLOORITEMMANAGER_H
+#ifndef ACTORSPRITELISTENER_H
+#define ACTORSPRITELISTENER_H
-#include <list>
+class ActorSprite;
-class FloorItem;
-class Map;
-
-class FloorItemManager
+class ActorSpriteListener
{
public:
- ~FloorItemManager();
-
- FloorItem *create(int id, int itemId, int x, int y);
-
- void destroy(FloorItem *item);
-
- void clear();
-
- FloorItem *findById(int id) const;
- FloorItem *findByCoordinates(int x, int y) const;
-
- private:
- typedef std::list<FloorItem*> FloorItems;
- typedef FloorItems::iterator FloorItemIterator;
- FloorItems mFloorItems;
-
+ /**
+ * Destructor.
+ */
+ virtual ~ActorSpriteListener() {}
+
+ /**
+ * Called when the ActorSprite has been destroyed. The listener will
+ * have to be registered first.
+ * @param actorSprite the ActorSprite being destroyed.
+ */
+ virtual void actorSpriteDestroyed(const ActorSprite &actorSprite) = 0;
};
-// TODO Get rid of the global?
-extern FloorItemManager *floorItemManager;
-
-#endif
+#endif // ACTORSPRITELISTENER_H
diff --git a/src/actorspritemanager.cpp b/src/actorspritemanager.cpp
new file mode 100644
index 00000000..dd979c63
--- /dev/null
+++ b/src/actorspritemanager.cpp
@@ -0,0 +1,315 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "actorspritemanager.h"
+
+#include "localplayer.h"
+
+#include "utils/stringutils.h"
+#include "utils/dtor.h"
+
+#include <cassert>
+
+#define for_actors ActorSpritesConstIterator it, it_end; \
+for (it = mActors.begin(), it_end = mActors.end() ; it != it_end; it++)
+
+class FindBeingFunctor
+{
+ public:
+ bool operator() (ActorSprite *actor)
+ {
+ if (actor->getType() == ActorSprite::FLOOR_ITEM)
+ return false;
+ Being* b = static_cast<Being*>(actor);
+
+ Uint16 other_y = y + ((b->getType() == ActorSprite::NPC) ? 1 : 0);
+ const Vector &pos = b->getPosition();
+ return ((int) pos.x / 32 == x &&
+ ((int) pos.y / 32 == y || (int) pos.y / 32 == other_y) &&
+ b->isAlive() &&
+ (type == ActorSprite::UNKNOWN || b->getType() == type));
+ }
+
+ Uint16 x, y;
+ ActorSprite::Type type;
+} beingFinder;
+
+ActorSpriteManager::ActorSpriteManager()
+{
+}
+
+ActorSpriteManager::~ActorSpriteManager()
+{
+ clear();
+}
+
+void ActorSpriteManager::setMap(Map *map)
+{
+ mMap = map;
+
+ if (player_node)
+ player_node->setMap(map);
+}
+
+void ActorSpriteManager::setPlayer(LocalPlayer *player)
+{
+ player_node = player;
+ mActors.insert(player);
+}
+
+Being *ActorSpriteManager::createBeing(int id, ActorSprite::Type type, int subtype)
+{
+ Being *being = new Being(id, type, subtype, mMap);
+
+ mActors.insert(being);
+ return being;
+}
+
+FloorItem *ActorSpriteManager::createItem(int id, int itemId, int x, int y)
+{
+ FloorItem *floorItem = new FloorItem(id, itemId, x, y, mMap);
+
+ mActors.insert(floorItem);
+ return floorItem;
+}
+
+void ActorSpriteManager::destroy(ActorSprite *actor)
+{
+ if (!actor || actor == player_node)
+ return;
+
+ mDeleteActors.insert(actor);
+}
+
+Being *ActorSpriteManager::findBeing(int id) const
+{
+ for_actors
+ {
+ ActorSprite *actor = *it;
+ if (actor->getId() == id &&
+ actor->getType() != ActorSprite::FLOOR_ITEM)
+ return static_cast<Being*>(actor);
+ }
+
+ return NULL;
+}
+
+Being *ActorSpriteManager::findBeing(int x, int y, ActorSprite::Type type) const
+{
+ beingFinder.x = x;
+ beingFinder.y = y;
+ beingFinder.type = type;
+
+ ActorSpritesConstIterator it = find_if(mActors.begin(), mActors.end(),
+ beingFinder);
+
+ return (it == mActors.end()) ? NULL : static_cast<Being*>(*it);
+}
+
+Being *ActorSpriteManager::findBeingByPixel(int x, int y) const
+{
+ for_actors
+ {
+ if ((*it)->getType() == ActorSprite::FLOOR_ITEM)
+ continue;
+
+ Being *being = static_cast<Being*>(*it);
+
+ int xtol = being->getWidth() / 2;
+ int uptol = being->getHeight();
+
+ if ((being->isAlive()) &&
+ (being != player_node) &&
+ (being->getPixelX() - xtol <= x) &&
+ (being->getPixelX() + xtol >= x) &&
+ (being->getPixelY() - uptol <= y) &&
+ (being->getPixelY() >= y))
+ return being;
+ }
+
+ return NULL;
+}
+
+FloorItem *ActorSpriteManager::findItem(int id) const
+{
+ for_actors
+ {
+ if ((*it)->getId() == id &&
+ (*it)->getType() == ActorSprite::FLOOR_ITEM)
+ {
+ return static_cast<FloorItem*>(*it);
+ }
+ }
+
+ return NULL;
+}
+
+FloorItem *ActorSpriteManager::findItem(int x, int y) const
+{
+ for_actors
+ {
+ if ((*it)->getTileX() == x && (*it)->getTileY() == y &&
+ (*it)->getType() == ActorSprite::FLOOR_ITEM)
+ {
+ return static_cast<FloorItem*>(*it);
+ }
+ }
+
+ return NULL;
+}
+
+Being *ActorSpriteManager::findBeingByName(const std::string &name,
+ ActorSprite::Type type) const
+{
+ for_actors
+ {
+ if ((*it)->getType() == ActorSprite::FLOOR_ITEM)
+ continue;
+
+ Being *being = static_cast<Being*>(*it);
+ if (being->getName() == name &&
+ (type == ActorSprite::UNKNOWN || type == being->getType()))
+ return being;
+ }
+ return NULL;
+}
+
+const ActorSprites &ActorSpriteManager::getAll() const
+{
+ return mActors;
+}
+
+void ActorSpriteManager::logic()
+{
+ for_actors
+ (*it)->logic();
+
+ for (it = mDeleteActors.begin(), it_end = mDeleteActors.end();
+ it != it_end; ++it)
+ {
+ mActors.erase(*it);
+ delete *it;
+ }
+
+ mDeleteActors.clear();
+}
+
+void ActorSpriteManager::clear()
+{
+ if (player_node)
+ {
+ player_node->setTarget(0);
+ mActors.erase(player_node);
+ }
+
+ for_actors
+ delete *it;
+ mActors.clear();
+ mDeleteActors.clear();
+
+ if (player_node)
+ mActors.insert(player_node);
+}
+
+Being *ActorSpriteManager::findNearestLivingBeing(int x, int y,
+ int maxTileDist,
+ ActorSprite::Type type,
+ Being *excluded) const
+{
+ Being *closestBeing = 0;
+ int dist = 0;
+
+ const int maxDist = maxTileDist * 32;
+
+ for_actors
+ {
+ if ((*it)->getType() == ActorSprite::FLOOR_ITEM)
+ continue;
+
+ Being *being = static_cast<Being*>(*it);
+ const Vector &pos = being->getPosition();
+ int d = abs(((int) pos.x) - x) + abs(((int) pos.y) - y);
+
+ if ((being->getType() == type || type == ActorSprite::UNKNOWN)
+ && (d < dist || !closestBeing) // it is closer
+ && being->isAlive() // no dead beings
+ && being != excluded)
+ {
+ dist = d;
+ closestBeing = being;
+ }
+ }
+
+ return (maxDist >= dist) ? closestBeing : 0;
+}
+
+Being *ActorSpriteManager::findNearestLivingBeing(Being *aroundBeing,
+ int maxDist,
+ ActorSprite::Type type) const
+{
+ const Vector &pos = aroundBeing->getPosition();
+ return findNearestLivingBeing((int)pos.x, (int)pos.y, maxDist, type,
+ aroundBeing);
+}
+
+bool ActorSpriteManager::hasActorSprite(ActorSprite *actor) const
+{
+ for_actors
+ {
+ if (actor == *it)
+ return true;
+ }
+
+ return false;
+}
+
+void ActorSpriteManager::getPlayerNames(std::vector<std::string> &names,
+ bool npcNames)
+{
+ names.clear();
+
+ for_actors
+ {
+ if ((*it)->getType() == ActorSprite::FLOOR_ITEM)
+ continue;
+
+ Being *being = static_cast<Being*>(*it);
+ if ((being->getType() == ActorSprite::PLAYER
+ || (being->getType() == ActorSprite::NPC && npcNames))
+ && being->getName() != "")
+ {
+ names.push_back(being->getName());
+ }
+ }
+}
+
+void ActorSpriteManager::updatePlayerNames()
+{
+ for_actors
+ {
+ if ((*it)->getType() == ActorSprite::FLOOR_ITEM)
+ continue;
+
+ Being *being = static_cast<Being*>(*it);
+ if (being->getType() == ActorSprite::PLAYER && being->getName() != "")
+ being->updateName();
+ }
+}
diff --git a/src/beingmanager.h b/src/actorspritemanager.h
index 7fd63afe..d9d5b534 100644
--- a/src/beingmanager.h
+++ b/src/actorspritemanager.h
@@ -19,25 +19,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef BEINGMANAGER_H
-#define BEINGMANAGER_H
+#ifndef ACTORSPRITEMANAGER_H
+#define ACTORSPRITEMANAGER_H
+#include "actorsprite.h"
#include "being.h"
+#include "flooritem.h"
class LocalPlayer;
class Map;
-typedef std::list<Being*> Beings;
+typedef std::set<ActorSprite*> ActorSprites;
+typedef ActorSprites::iterator ActorSpritesIterator;
+typedef ActorSprites::const_iterator ActorSpritesConstIterator;
-class BeingManager
+class ActorSpriteManager
{
public:
- BeingManager();
+ ActorSpriteManager();
- ~BeingManager();
+ ~ActorSpriteManager();
/**
- * Sets the map on which beings are created.
+ * Sets the map on which ActorSprites are created.
*/
void setMap(Map *map);
@@ -47,27 +51,48 @@ class BeingManager
void setPlayer(LocalPlayer *player);
/**
- * Create a being and add it to the list of beings.
+ * Create a Being and add it to the list of ActorSprites.
*/
- Being *createBeing(int id, Being::Type type, int subtype);
+ Being *createBeing(int id, ActorSprite::Type type, int subtype);
/**
- * Remove a Being.
+ * Create a FloorItem and add it to the list of ActorSprites.
*/
- void destroyBeing(Being *being);
+ FloorItem *createItem(int id, int itemId, int x, int y);
/**
- * Returns a specific id Being.
+ * Destroys the given ActorSprite at the end of
+ * ActorSpriteManager::logic.
+ */
+ void destroy(ActorSprite *actor);
+
+ /**
+ * Returns a specific Being, by id;
*/
Being *findBeing(int id) const;
/**
* Returns a being at specific coordinates.
*/
- Being *findBeing(int x, int y, Being::Type type = Being::UNKNOWN) const;
+ Being *findBeing(int x, int y,
+ ActorSprite::Type type = ActorSprite::UNKNOWN) const;
+
+ /**
+ * Returns a being at the specific pixel.
+ */
Being *findBeingByPixel(int x, int y) const;
/**
+ * Returns a specific FloorItem, by id.
+ */
+ FloorItem *findItem(int id) const;
+
+ /**
+ * Returns a FloorItem at specific coordinates.
+ */
+ FloorItem *findItem(int x, int y) const;
+
+ /**
* Returns a being nearest to specific coordinates.
*
* @param x X coordinate in pixels.
@@ -78,7 +103,7 @@ class BeingManager
* @param excluded The being to exclude from the search.
*/
Being *findNearestLivingBeing(int x, int y, int maxTileDist,
- Being::Type type = Being::UNKNOWN,
+ ActorSprite::Type type = Being::UNKNOWN,
Being *excluded = 0) const;
/**
@@ -90,35 +115,35 @@ class BeingManager
* @param type The type of being to look for.
*/
Being *findNearestLivingBeing(Being *aroundBeing, int maxTileDist,
- Being::Type type = Being::UNKNOWN) const;
+ ActorSprite::Type type = Being::UNKNOWN) const;
/**
* Finds a being by name and (optionally) by type.
*/
Being *findBeingByName(const std::string &name,
- Being::Type type = Being::UNKNOWN) const;
+ ActorSprite::Type type = Being::UNKNOWN) const;
/**
* Returns the whole list of beings.
*/
- const Beings &getAll() const;
+ const ActorSprites &getAll() const;
/**
- * Returns true if the given being is in the manager's list, false
- * otherwise.
+ * Returns true if the given ActorSprite is in the manager's list,
+ * false otherwise.
*
- * \param being the being to search for
+ * \param actor the ActorSprite to search for
*/
- bool hasBeing(Being *being) const;
+ bool hasActorSprite(ActorSprite *actor) const;
/**
- * Performs being logic and deletes dead beings when they have been
- * dead long enough.
+ * Performs ActorSprite logic and deletes ActorSprite scheduled to be
+ * deleted.
*/
void logic();
/**
- * Destroys all beings except the local player
+ * Destroys all ActorSprites except the local player
*/
void clear();
@@ -128,10 +153,11 @@ class BeingManager
void updatePlayerNames();
protected:
- Beings mBeings;
+ ActorSprites mActors;
+ ActorSprites mDeleteActors;
Map *mMap;
};
-extern BeingManager *beingManager;
+extern ActorSpriteManager *actorSpriteManager;
-#endif
+#endif // ACTORSPRITEMANAGER_H
diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp
index 59bf2f88..ec666d80 100644
--- a/src/animatedsprite.cpp
+++ b/src/animatedsprite.cpp
@@ -41,16 +41,17 @@ AnimatedSprite::AnimatedSprite(SpriteDef *sprite):
mSprite(sprite),
mAction(0),
mAnimation(0),
- mFrame(0),
- mAlpha(1.0f)
+ mFrame(0)
{
assert(mSprite);
+ mAlpha = 1.0f;
+
// Take possession of the sprite
mSprite->incRef();
// Play the stand animation by default
- play(ACTION_STAND);
+ play(SpriteAction::STAND);
}
AnimatedSprite *AnimatedSprite::load(const std::string &filename, int variant)
@@ -69,18 +70,22 @@ AnimatedSprite::~AnimatedSprite()
mSprite->decRef();
}
-void AnimatedSprite::reset()
+bool AnimatedSprite::reset()
{
+ bool ret = mFrameIndex !=0 || mFrameTime != 0 || mLastTime != 0;
+
mFrameIndex = 0;
mFrameTime = 0;
mLastTime = 0;
+
+ return ret;
}
-void AnimatedSprite::play(SpriteAction spriteAction)
+bool AnimatedSprite::play(std::string spriteAction)
{
Action *action = mSprite->getAction(spriteAction);
if (!action)
- return;
+ return false;
mAction = action;
Animation *animation = mAction->getAnimation(mDirection);
@@ -91,10 +96,14 @@ void AnimatedSprite::play(SpriteAction spriteAction)
mFrame = mAnimation->getFrame(0);
reset();
+
+ return true;
}
+
+ return false;
}
-void AnimatedSprite::update(int time)
+bool AnimatedSprite::update(int time)
{
// Avoid freaking out at first frame or when tick_time overflows
if (time < mLastTime || mLastTime == 0)
@@ -102,16 +111,22 @@ void AnimatedSprite::update(int time)
// If not enough time has passed yet, do nothing
if (time <= mLastTime || !mAnimation)
- return;
+ return false;
unsigned int dt = time - mLastTime;
mLastTime = time;
+ Animation *animation = mAnimation;
+ Frame *frame = mFrame;
+
if (!updateCurrentAnimation(dt))
{
// Animation finished, reset to default
- play(ACTION_STAND);
+ play(SpriteAction::STAND);
}
+
+ // Make sure something actually changed
+ return animation != mAnimation || frame != mFrame;
}
bool AnimatedSprite::updateCurrentAnimation(unsigned int time)
@@ -158,14 +173,14 @@ bool AnimatedSprite::draw(Graphics *graphics, int posX, int posY) const
posY + mFrame->offsetY);
}
-void AnimatedSprite::setDirection(SpriteDirection direction)
+bool AnimatedSprite::setDirection(SpriteDirection direction)
{
if (mDirection != direction)
{
mDirection = direction;
if (!mAction)
- return;
+ return false;
Animation *animation = mAction->getAnimation(mDirection);
@@ -175,7 +190,21 @@ void AnimatedSprite::setDirection(SpriteDirection direction)
mFrame = mAnimation->getFrame(0);
reset();
}
+
+ return true;
}
+
+ return false;
+}
+
+size_t AnimatedSprite::getCurrentFrame() const
+{
+ return mFrameIndex;
+}
+
+size_t AnimatedSprite::getFrameCount() const
+{
+ return mAnimation->getLength();
}
int AnimatedSprite::getWidth() const
@@ -193,3 +222,8 @@ int AnimatedSprite::getHeight() const
else
return 0;
}
+
+const Image* AnimatedSprite::getImage() const
+{
+ return mFrame ? mFrame->image : 0;
+}
diff --git a/src/animatedsprite.h b/src/animatedsprite.h
index 54b63cc0..bd39c267 100644
--- a/src/animatedsprite.h
+++ b/src/animatedsprite.h
@@ -22,19 +22,18 @@
#ifndef ANIMATEDSPRITE_H
#define ANIMATEDSPRITE_H
-#include "resources/spritedef.h"
+#include "sprite.h"
#include <map>
#include <string>
class Animation;
-class Graphics;
struct Frame;
/**
* Animates a sprite by adding playback state.
*/
-class AnimatedSprite
+class AnimatedSprite : public Sprite
{
public:
/**
@@ -53,59 +52,30 @@ class AnimatedSprite
static AnimatedSprite *load(const std::string &filename,
int variant = 0);
- /**
- * Destructor.
- */
virtual ~AnimatedSprite();
- /**
- * Resets the animated sprite.
- */
- void reset();
+ bool reset();
- /**
- * Plays an action using the current direction
- */
- void play(SpriteAction action);
+ bool play(std::string action);
- /**
- * Inform the animation of the passed time so that it can output the
- * correct animation frame.
- */
- void update(int time);
+ bool update(int time);
- /**
- * Draw the current animation frame at the coordinates given in screen
- * pixels.
- */
bool draw(Graphics* graphics, int posX, int posY) const;
- /**
- * gets the width in pixels of the image of the current frame
- */
int getWidth() const;
- /**
- * gets the height in pixels of the image of the current frame
- */
int getHeight() const;
- /**
- * Sets the direction.
- */
- void setDirection(SpriteDirection direction);
+ const Image* getImage() const;
- /**
- * Sets the alpha value of the animated sprite
- */
- void setAlpha(float alpha)
- { mAlpha = alpha; }
+ bool setDirection(SpriteDirection direction);
- /**
- * Returns the current alpha opacity of the animated sprite.
- */
- virtual float getAlpha() const
- { return mAlpha; }
+ int getNumberOfLayers()
+ { return 1; }
+
+ size_t getCurrentFrame() const;
+
+ size_t getFrameCount() const;
private:
bool updateCurrentAnimation(unsigned int dt);
@@ -120,7 +90,6 @@ class AnimatedSprite
Action *mAction; /**< The currently active action. */
Animation *mAnimation; /**< The currently active animation. */
Frame *mFrame; /**< The currently active frame. */
- float mAlpha; /**< The alpha opacity used to draw */
};
#endif
diff --git a/src/being.cpp b/src/being.cpp
index d2dfc855..1b95b17d 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -21,104 +21,163 @@
#include "being.h"
+#include "actorspritemanager.h"
#include "animatedsprite.h"
#include "client.h"
#include "configuration.h"
#include "effectmanager.h"
+#include "event.h"
#include "graphics.h"
+#include "guild.h"
#include "localplayer.h"
#include "log.h"
#include "map.h"
#include "particle.h"
+#include "party.h"
+#include "playerrelations.h"
#include "simpleanimation.h"
#include "sound.h"
+#include "sprite.h"
#include "text.h"
#include "statuseffect.h"
#include "gui/gui.h"
+#include "gui/socialwindow.h"
#include "gui/speechbubble.h"
-#include "gui/theme.h"
-#include "gui/userpalette.h"
+#include "net/charhandler.h"
+#include "net/gamehandler.h"
+#include "net/net.h"
+#include "net/playerhandler.h"
+
+#include "resources/beinginfo.h"
#include "resources/colordb.h"
#include "resources/emotedb.h"
#include "resources/image.h"
#include "resources/itemdb.h"
#include "resources/iteminfo.h"
+#include "resources/monsterdb.h"
+#include "resources/npcdb.h"
#include "resources/resourcemanager.h"
-
+#include "resources/theme.h"
+#include "resources/userpalette.h"
#include "utils/dtor.h"
#include "utils/stringutils.h"
#include "utils/xml.h"
-#include "net/net.h"
-#include "net/playerhandler.h"
#include <cassert>
#include <cmath>
-#define BEING_EFFECTS_FILE "effects.xml"
#define HAIR_FILE "hair.xml"
static const int DEFAULT_BEING_WIDTH = 32;
static const int DEFAULT_BEING_HEIGHT = 32;
-
-
int Being::mNumberOfHairstyles = 1;
// TODO: mWalkTime used by eAthena only
-Being::Being(int id, int subtype, Map *map):
- mFrame(0),
- mWalkTime(0),
+Being::Being(int id, Type type, int subtype, Map *map):
+ ActorSprite(id),
+ mInfo(BeingInfo::Unknown),
+ mActionTime(0),
mEmotion(0), mEmotionTime(0),
mSpeechTime(0),
+ mAttackType(1),
mAttackSpeed(350),
mAction(STAND),
- mSubType(subtype),
- mId(id),
+ mSubType(0xFFFF),
mDirection(DOWN),
mSpriteDirection(DIRECTION_DOWN),
- mMap(NULL),
mDispName(0),
mShowName(false),
mEquippedWeapon(NULL),
mText(0),
- mStunMode(0),
- mAlpha(1.0f),
- mStatusParticleEffects(&mStunParticleEffects, false),
- mChildParticleEffects(&mStatusParticleEffects, false),
- mMustResetParticles(false),
+ mGender(GENDER_UNSPECIFIED),
+ mParty(NULL),
+ mIsGM(false),
+ mType(type),
mX(0), mY(0),
- mDamageTaken(0),
- mUsedTargetCursor(NULL)
+ mDamageTaken(0)
{
setMap(map);
+ setSubtype(subtype);
mSpeechBubble = new SpeechBubble;
- mNameColor = &userPalette->getColor(UserPalette::NPC);
- mTextColor = &Theme::getThemeColor(Theme::CHAT);
mWalkSpeed = Net::getPlayerHandler()->getDefaultWalkSpeed();
+
+ if (getType() == PLAYER)
+ mShowName = config.getBoolValue("visiblenames");
+
+ config.addListener("visiblenames", this);
+
+ if (getType() == PLAYER || getType() == NPC)
+ setShowName(true);
+
+ updateColors();
+ listen("Chat");
}
Being::~Being()
{
- mUsedTargetCursor = NULL;
- delete_all(mSprites);
-
- if (player_node && player_node->getTarget() == this)
- player_node->setTarget(NULL);
-
- setMap(NULL);
+ config.removeListener("visiblenames", this);
delete mSpeechBubble;
delete mDispName;
delete mText;
+ mSpeechBubble = 0;
+ mDispName = 0;
+ mText = 0;
+}
+
+void Being::setSubtype(Uint16 subtype)
+{
+ if (subtype == mSubType)
+ return;
+
+ mSubType = subtype;
+
+ if (getType() == MONSTER)
+ {
+ mInfo = MonsterDB::get(mSubType);
+ setName(mInfo->getName());
+ setupSpriteDisplay(mInfo->getDisplay());
+ }
+ else if (getType() == NPC)
+ {
+ mInfo = NPCDB::get(mSubType);
+ setupSpriteDisplay(mInfo->getDisplay(), false);
+ }
+ else if (getType() == PLAYER)
+ {
+ int id = -100 - subtype;
+
+ // Prevent showing errors when sprite doesn't exist
+ if (!ItemDB::exists(id))
+ id = -100;
+
+ setSprite(Net::getCharHandler()->baseSprite(), id);
+ }
+}
+
+ActorSprite::TargetCursorSize Being::getTargetCursorSize() const
+{
+ return mInfo->getTargetCursorSize();
+}
+
+unsigned char Being::getWalkMask() const
+{
+ return mInfo->getWalkMask();
+}
+
+Map::BlockType Being::getBlockType() const
+{
+ return mInfo->getBlockType();
}
void Being::setPosition(const Vector &pos)
{
- mPos = pos;
+ Actor::setPosition(pos);
updateCoords();
@@ -152,8 +211,9 @@ void Being::setDestination(int dstX, int dstY)
Position dest = mMap->checkNodeOffsets(getCollisionRadius(), getWalkMask(),
dstX, dstY);
- Path thisPath = mMap->findPixelPath(mPos.x, mPos.y, dest.x, dest.y,
- getCollisionRadius(), getWalkMask());
+ Path thisPath = mMap->findPixelPath((int) mPos.x, (int) mPos.y,
+ dest.x, dest.y,
+ getCollisionRadius(), getWalkMask());
if (thisPath.empty())
{
@@ -186,10 +246,10 @@ void Being::setPath(const Path &path)
mPath = path;
if ((Net::getNetworkType() == ServerInfo::TMWATHENA) &&
- mAction != WALK && mAction != DEAD)
+ mAction != MOVE && mAction != DEAD)
{
nextTile();
- mWalkTime = tick_time;
+ mActionTime = tick_time;
}
}
@@ -235,7 +295,7 @@ void Being::setSpeech(const std::string &text, int time)
if (!mSpeech.empty())
mSpeechTime = time <= SPEECH_MAX_TIME ? time : SPEECH_MAX_TIME;
- const int speech = (int) config.getValue("speech", TEXT_OVERHEAD);
+ const int speech = config.getIntValue("speech");
if (speech == TEXT_OVERHEAD)
{
if (mText)
@@ -292,6 +352,8 @@ void Being::takeDamage(Being *attacker, int amount, AttackType type)
if (amount > 0)
{
+ sound.playSfx(mInfo->getSound(SOUND_EVENT_HURT));
+
if (getType() == MONSTER)
{
mDamageTaken += amount;
@@ -310,42 +372,50 @@ void Being::handleAttack(Being *victim, int damage, AttackType type)
if (this != player_node)
setAction(Being::ATTACK, 1);
- if (getType() == PLAYER && victim)
- {
- if (mEquippedWeapon)
- {
- fireMissile(victim, mEquippedWeapon->getMissileParticle());
- }
- }
+ if (getType() == PLAYER && victim && mEquippedWeapon)
+ fireMissile(victim, mEquippedWeapon->getMissileParticle());
+ else
+ fireMissile(victim, mInfo->getAttack(mAttackType)->missileParticle);
+
if (Net::getNetworkType() == ServerInfo::TMWATHENA)
{
- mFrame = 0;
- mWalkTime = tick_time;
+ reset();
+ mActionTime = tick_time;
}
+
+ sound.playSfx(mInfo->getSound((damage > 0) ?
+ SOUND_EVENT_HIT : SOUND_EVENT_MISS));
}
void Being::setName(const std::string &name)
{
- mName = name;
-
- if (getShowName())
+ if (getType() == NPC)
+ {
+ mName = name.substr(0, name.find('#', 0));
showName();
+ }
+ else
+ {
+ mName = name;
+
+ if (getType() == PLAYER && getShowName())
+ showName();
+ }
}
void Being::setShowName(bool doShowName)
{
- bool oldShow = mShowName;
+ if (mShowName == doShowName)
+ return;
+
mShowName = doShowName;
- if (doShowName != oldShow)
+ if (doShowName)
+ showName();
+ else
{
- if (doShowName)
- showName();
- else
- {
- delete mDispName;
- mDispName = 0;
- }
+ delete mDispName;
+ mDispName = 0;
}
}
@@ -360,26 +430,99 @@ void Being::setGuildPos(const std::string &pos)
logger->log("Got guild position \"%s\" for being %s(%i)", pos.c_str(), mName.c_str(), mId);
}
-void Being::setMap(Map *map)
+void Being::addGuild(Guild *guild)
{
- // Remove sprite from potential previous map
- if (mMap)
- mMap->removeSprite(mMapSprite);
+ mGuilds[guild->getId()] = guild;
+ guild->addMember(mId, mName);
- mMap = map;
+ if (this == player_node && socialWindow)
+ {
+ socialWindow->addTab(guild);
+ }
+}
- // Add sprite to potential new map
- if (mMap)
- mMapSprite = mMap->addSprite(this);
+void Being::removeGuild(int id)
+{
+ if (this == player_node && socialWindow)
+ {
+ socialWindow->removeTab(mGuilds[id]);
+ }
+
+ mGuilds[id]->removeMember(mId);
+ mGuilds.erase(id);
+}
- // Clear particle effect list because child particles became invalid
- mChildParticleEffects.clear();
- mMustResetParticles = true; // Reset status particles on next redraw
+Guild *Being::getGuild(const std::string &guildName) const
+{
+ std::map<int, Guild*>::const_iterator itr, itr_end = mGuilds.end();
+ for (itr = mGuilds.begin(); itr != itr_end; ++itr)
+ {
+ Guild *guild = itr->second;
+ if (guild->getName() == guildName)
+ {
+ return guild;
+ }
+ }
+
+ return NULL;
}
-void Being::controlParticle(Particle *particle)
+Guild *Being::getGuild(int id) const
{
- mChildParticleEffects.addLocally(particle);
+ std::map<int, Guild*>::const_iterator itr;
+ itr = mGuilds.find(id);
+ if (itr != mGuilds.end())
+ {
+ return itr->second;
+ }
+
+ return NULL;
+}
+
+void Being::clearGuilds()
+{
+ std::map<int, Guild*>::const_iterator itr, itr_end = mGuilds.end();
+ for (itr = mGuilds.begin(); itr != itr_end; ++itr)
+ {
+ Guild *guild = itr->second;
+
+ if (this == player_node && socialWindow)
+ socialWindow->removeTab(guild);
+
+ guild->removeMember(mId);
+ }
+
+ mGuilds.clear();
+}
+
+void Being::setParty(Party *party)
+{
+ if (party == mParty)
+ return;
+
+ Party *old = mParty;
+ mParty = party;
+
+ if (old)
+ {
+ old->removeMember(mId);
+ }
+
+ if (party)
+ {
+ party->addMember(mId, mName);
+ }
+
+ updateColors();
+
+ if (this == player_node && socialWindow)
+ {
+ if (old)
+ socialWindow->removeTab(old);
+
+ if (party)
+ socialWindow->addTab(party);
+ }
}
void Being::fireMissile(Being *victim, const std::string &particle)
@@ -404,46 +547,79 @@ void Being::fireMissile(Being *victim, const std::string &particle)
void Being::setAction(Action action, int attackType)
{
- SpriteAction currentAction = ACTION_INVALID;
+ std::string currentAction = SpriteAction::INVALID;
switch (action)
{
- case WALK:
- currentAction = ACTION_WALK;
+ case MOVE:
+ currentAction = SpriteAction::MOVE;
+ // Note: When adding a run action,
+ // Differentiate walk and run with action name,
+ // while using only the ACTION_MOVE.
break;
case SIT:
- currentAction = ACTION_SIT;
+ currentAction = SpriteAction::SIT;
break;
case ATTACK:
if (mEquippedWeapon)
- currentAction = mEquippedWeapon->getAttackType();
+ {
+ currentAction = mEquippedWeapon->getAttackAction();
+ reset();
+ }
else
- currentAction = ACTION_ATTACK;
+ {
+ mAttackType = attackType;
+ currentAction = mInfo->getAttack(attackType)->action;
+ reset();
+
+ if (Net::getNetworkType() == ServerInfo::MANASERV)
+ {
+ int rotation = 0;
+ //attack particle effect
+ std::string particleEffect = mInfo->getAttack(attackType)
+ ->particleEffect;
+ if (!particleEffect.empty() && Particle::enabled)
+ {
+ switch (mSpriteDirection)
+ {
+ case DIRECTION_DOWN: rotation = 0; break;
+ case DIRECTION_LEFT: rotation = 90; break;
+ case DIRECTION_UP: rotation = 180; break;
+ case DIRECTION_RIGHT: rotation = 270; break;
+ default: break;
+ }
+ Particle *p;
+ p = particleEngine->addEffect(particleEffect, 0, 0,
+ rotation);
+ controlParticle(p);
+ }
+ }
+ }
- for (SpriteIterator it = mSprites.begin(); it != mSprites.end(); it++)
- if (*it)
- (*it)->reset();
break;
case HURT:
- //currentAction = ACTION_HURT; // Buggy: makes the player stop
+ //currentAction = SpriteAction::HURT;// Buggy: makes the player stop
// attacking and unable to attack
- // again until he moves
+ // again until he moves.
+ // TODO: fix this!
break;
case DEAD:
- currentAction = ACTION_DEAD;
+ currentAction = SpriteAction::DEAD;
+ sound.playSfx(mInfo->getSound(SOUND_EVENT_DIE));
break;
case STAND:
- currentAction = ACTION_STAND;
+ currentAction = SpriteAction::STAND;
break;
}
- if (currentAction != ACTION_INVALID)
+ if (currentAction != SpriteAction::INVALID)
{
- for (SpriteIterator it = mSprites.begin(); it != mSprites.end(); it++)
- if (*it)
- (*it)->play(currentAction);
+ play(currentAction);
mAction = action;
}
+
+ if (currentAction != SpriteAction::MOVE)
+ mActionTime = tick_time;
}
void Being::setDirection(Uint8 direction)
@@ -469,9 +645,7 @@ void Being::setDirection(Uint8 direction)
dir = DIRECTION_LEFT;
mSpriteDirection = dir;
- for (SpriteIterator it = mSprites.begin(); it != mSprites.end(); it++)
- if (*it)
- (*it)->setDirection(dir);
+ CompoundSprite::setDirection(dir);
}
/** TODO: Used by eAthena only */
@@ -506,8 +680,8 @@ void Being::nextTile()
mX = pos.x;
mY = pos.y;
- setAction(WALK);
- mWalkTime += (int)(mWalkSpeed.x / 10);
+ setAction(MOVE);
+ mActionTime += (int)(mWalkSpeed.x / 10);
}
int Being::getCollisionRadius() const
@@ -570,8 +744,8 @@ void Being::logic()
else
setPosition(mPos + diff);
- if (mAction != WALK)
- setAction(WALK);
+ if (mAction != MOVE)
+ setAction(MOVE);
// Update the player sprite direction.
// N.B.: We only change this if the distance is more than one pixel.
@@ -600,13 +774,76 @@ void Being::logic()
// remove it and go to the next one.
mPath.pop_front();
}
- else if (mAction == WALK)
+ else if (mAction == MOVE)
{
setAction(STAND);
}
}
else if (Net::getNetworkType() == ServerInfo::TMWATHENA)
{
+ int frameCount = getFrameCount();
+
+ switch (mAction)
+ {
+ case STAND:
+ case SIT:
+ case DEAD:
+ case HURT:
+ break;
+
+ case MOVE:
+ if ((int) ((get_elapsed_time(mActionTime) * frameCount)
+ / getWalkSpeed().x) >= frameCount)
+ nextTile();
+ break;
+
+ case ATTACK:
+ int rotation = 0;
+ std::string particleEffect = "";
+
+ int curFrame = (get_elapsed_time(mActionTime) * frameCount)
+ / mAttackSpeed;
+
+ //attack particle effect
+ if (mEquippedWeapon)
+ {
+ particleEffect = mEquippedWeapon->getParticleEffect();
+
+ if (!particleEffect.empty() &&
+ findSameSubstring(particleEffect,
+ paths.getStringValue("particles")).empty())
+ particleEffect = paths.getStringValue("particles")
+ + particleEffect;
+ }
+ else
+ {
+ particleEffect = mInfo->getAttack(mAttackType)
+ ->particleEffect;
+ }
+
+ if (!particleEffect.empty() && Particle::enabled
+ && curFrame == 1)
+ {
+ switch (mDirection)
+ {
+ case DOWN: rotation = 0; break;
+ case LEFT: rotation = 90; break;
+ case UP: rotation = 180; break;
+ case RIGHT: rotation = 270; break;
+ default: break;
+ }
+ Particle *p;
+ p = particleEngine->addEffect(particleEffect, 0, 0,
+ rotation);
+ controlParticle(p);
+ }
+
+ if (curFrame >= frameCount)
+ nextTile();
+
+ break;
+ }
+
// Update pixel coordinates
setPosition(mX * 32 + 16 + getXOffset(),
mY * 32 + 32 + getYOffset());
@@ -619,68 +856,18 @@ void Being::logic()
mEmotion = 0;
}
- // Update sprite animations
- if (mUsedTargetCursor)
- mUsedTargetCursor->update(tick_time * MILLISECONDS_IN_A_TICK);
-
- for (SpriteIterator it = mSprites.begin(); it != mSprites.end(); it++)
- if (*it)
- (*it)->update(tick_time * MILLISECONDS_IN_A_TICK);
-
- // 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
- mChildParticleEffects.moveTo(mPos.x, mPos.y);
-}
-
-void Being::draw(Graphics *graphics, int offsetX, int offsetY) const
-{
- // TODO: Eventually, we probably should fix all sprite offsets so that
- // these translations aren't necessary anymore. The sprites know
- // best where their base point should be.
- const int px = getPixelX() + offsetX - 16;
- // Temporary fix to the Y offset.
- const int py = getPixelY() + offsetY -
- ((Net::getNetworkType() == ServerInfo::MANASERV) ? 15 : 32);
-
- if (mUsedTargetCursor)
- mUsedTargetCursor->draw(graphics, px, py);
-
- for (SpriteConstIterator it = mSprites.begin(); it != mSprites.end(); it++)
- {
- if (*it)
- {
- if ((*it)->getAlpha() != mAlpha)
- (*it)->setAlpha(mAlpha);
- (*it)->draw(graphics, px, py);
- }
- }
-}
+ ActorSprite::logic();
-void Being::drawSpriteAt(Graphics *graphics, int x, int y) const
-{
- const int px = x - 16;
- const int py = y - 32;
+ int frameCount = getFrameCount();
+ if (frameCount < 10)
+ frameCount = 10;
- for (SpriteConstIterator it = mSprites.begin(); it != mSprites.end(); it++)
+ if (!isAlive() && Net::getGameHandler()->removeDeadBeings() &&
+ (int) ((get_elapsed_time(mActionTime)
+ / getWalkSpeed().x) >= frameCount))
{
- if (*it)
- {
- if ((*it)->getAlpha() != mAlpha)
- (*it)->setAlpha(mAlpha);
- (*it)->draw(graphics, px, py);
- }
+ if (getType() != PLAYER)
+ actorSpriteManager->destroy(this);
}
}
@@ -701,7 +888,7 @@ void Being::drawSpeech(int offsetX, int offsetY)
{
const int px = getPixelX() - offsetX;
const int py = getPixelY() - offsetY;
- const int speech = (int) config.getValue("speech", TEXT_OVERHEAD);
+ const int speech = config.getIntValue("speech");
// Draw speech above this being
if (mSpeechTime == 0)
@@ -751,72 +938,11 @@ void Being::drawSpeech(int offsetX, int offsetY)
}
}
-void Being::setStatusEffectBlock(int offset, Uint16 newEffects)
-{
- for (int i = 0; i < STATUS_EFFECTS; i++)
- {
- int index = StatusEffect::blockEffectIndexToEffectIndex(offset + i);
-
- 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();
-
- if (effectId >= 0)
- {
- mStatusParticleEffects.setLocally(effectId, particle);
- }
- else
- {
- mStunParticleEffects.clearLocally();
- if (particle)
- mStunParticleEffects.addLocally(particle);
- }
-}
-
-void Being::updateStunMode(int oldMode, int newMode)
-{
- handleStatusEffect(StatusEffect::getStatusEffect(oldMode, false), -1);
- handleStatusEffect(StatusEffect::getStatusEffect(newMode, true), -1);
-}
-
-void Being::updateStatusEffect(int index, bool newStatus)
-{
- handleStatusEffect(StatusEffect::getStatusEffect(index, newStatus), index);
-}
-
-void Being::setStatusEffect(int index, bool active)
-{
- const bool wasActive = mStatusEffects.find(index) != mStatusEffects.end();
-
- if (active != wasActive)
- {
- updateStatusEffect(index, active);
- if (active)
- mStatusEffects.insert(index);
- else
- mStatusEffects.erase(index);
- }
-}
-
/** TODO: eAthena only */
int Being::getOffset(char pos, char neg) const
{
// Check whether we're walking in the requested direction
- if (mAction != WALK || !(mDirection & (pos | neg)))
+ if (mAction != MOVE || !(mDirection & (pos | neg)))
return 0;
int offset = 0;
@@ -824,9 +950,9 @@ int Being::getOffset(char pos, char neg) const
if (mMap)
{
offset = (pos == LEFT && neg == RIGHT) ?
- (int)((get_elapsed_time(mWalkTime)
+ (int)((get_elapsed_time(mActionTime)
* mMap->getTileWidth()) / mWalkSpeed.x) :
- (int)((get_elapsed_time(mWalkTime)
+ (int)((get_elapsed_time(mActionTime)
* mMap->getTileHeight()) / mWalkSpeed.y);
}
@@ -844,176 +970,182 @@ int Being::getOffset(char pos, char neg) const
int Being::getWidth() const
{
- AnimatedSprite *base = NULL;
-
- for (SpriteConstIterator it = mSprites.begin(); it != mSprites.end(); it++)
- if ((base = (*it)))
- break;
-
- if (base)
- return std::max(base->getWidth(), DEFAULT_BEING_WIDTH);
-
- return DEFAULT_BEING_WIDTH;
+ return std::max(CompoundSprite::getWidth(), DEFAULT_BEING_WIDTH);
}
int Being::getHeight() const
{
- AnimatedSprite *base = NULL;
-
- for (SpriteConstIterator it = mSprites.begin(); it != mSprites.end(); it++)
- if ((base = (*it)))
- break;
+ return std::max(CompoundSprite::getHeight(), DEFAULT_BEING_HEIGHT);
+}
- if (base)
- return std::max(base->getHeight(), DEFAULT_BEING_HEIGHT);
+void Being::updateCoords()
+{
+ if (!mDispName)
+ return;
- return DEFAULT_BEING_HEIGHT;
+ // Monster names show above the sprite instead of below it
+ if (getType() == MONSTER)
+ mDispName->adviseXY(getPixelX(),
+ getPixelY() - getHeight() - mDispName->getHeight());
+ else
+ mDispName->adviseXY(getPixelX(), getPixelY());
}
-void Being::setTargetAnimation(SimpleAnimation *animation)
+void Being::optionChanged(const std::string &value)
{
- mUsedTargetCursor = animation;
- mUsedTargetCursor->reset();
+ if (getType() == PLAYER && value == "visiblenames")
+ {
+ setShowName(config.getBoolValue("visiblenames"));
+ }
}
-struct EffectDescription {
- std::string mGFXEffect;
- std::string mSFXEffect;
-};
-
-static EffectDescription *default_effect = NULL;
-static std::map<int, EffectDescription *> effects;
-static bool effects_initialized = false;
-
-static EffectDescription *getEffectDescription(xmlNodePtr node, int *id)
+void Being::flashName(int time)
{
- EffectDescription *ed = new EffectDescription;
-
- *id = atoi(XML::getProperty(node, "id", "-1").c_str());
- ed->mSFXEffect = XML::getProperty(node, "audio", "");
- ed->mGFXEffect = XML::getProperty(node, "particle", "");
-
- return ed;
+ if (mDispName)
+ mDispName->flash(time);
}
-static EffectDescription *getEffectDescription(int effectId)
+void Being::showName()
{
- if (!effects_initialized)
- {
- XML::Document doc(BEING_EFFECTS_FILE);
- xmlNodePtr root = doc.rootNode();
+ delete mDispName;
+ mDispName = 0;
+ std::string mDisplayName(mName);
- if (!root || !xmlStrEqual(root->name, BAD_CAST "being-effects"))
- {
- logger->log("Error loading being effects file: "
- BEING_EFFECTS_FILE);
- return NULL;
- }
+ if (config.getBoolValue("showgender"))
+ {
+ if (getGender() == GENDER_FEMALE)
+ mDisplayName += " \u2640";
+ else if (getGender() == GENDER_MALE)
+ mDisplayName += " \u2642";
+ }
- for_each_xml_child_node(node, root)
+ if (getType() == MONSTER)
+ {
+ if (config.getBoolValue("showMonstersTakedDamage"))
{
- int id;
-
- if (xmlStrEqual(node->name, BAD_CAST "effect"))
- {
- EffectDescription *EffectDescription =
- getEffectDescription(node, &id);
- effects[id] = EffectDescription;
- }
- else if (xmlStrEqual(node->name, BAD_CAST "default"))
- {
- EffectDescription *effectDescription =
- getEffectDescription(node, &id);
-
- if (default_effect)
- delete default_effect;
-
- default_effect = effectDescription;
- }
+ mDisplayName += ", " + toString(getDamageTaken());
}
+ }
- effects_initialized = true;
- } // done initializing
+ gcn::Font *font = 0;
+ if (player_node && player_node->getTarget() == this
+ && getType() != MONSTER)
+ {
+ font = boldFont;
+ }
- EffectDescription *ed = effects[effectId];
+ mDispName = new FlashText(mDisplayName, getPixelX(), getPixelY(),
+ gcn::Graphics::CENTER, mNameColor, font);
- return ed ? ed : default_effect;
+ updateCoords();
}
-void Being::internalTriggerEffect(int effectId, bool sfx, bool gfx)
+void Being::updateColors()
{
- logger->log("Special effect #%d on %s", effectId,
- getId() == player_node->getId() ? "self" : "other");
-
- EffectDescription *ed = getEffectDescription(effectId);
-
- if (!ed)
+ if (getType() == MONSTER)
{
- logger->log("Unknown special effect and no default recorded");
- return;
+ mNameColor = &userPalette->getColor(UserPalette::MONSTER);
+ mTextColor = &userPalette->getColor(UserPalette::MONSTER);
}
-
- if (gfx && !ed->mGFXEffect.empty())
+ else if (getType() == NPC)
{
- Particle *selfFX;
-
- selfFX = particleEngine->addEffect(ed->mGFXEffect, 0, 0);
- controlParticle(selfFX);
+ mNameColor = &userPalette->getColor(UserPalette::NPC);
+ mTextColor = &userPalette->getColor(UserPalette::NPC);
}
+ else if (this == player_node)
+ {
+ mNameColor = &userPalette->getColor(UserPalette::SELF);
+ mTextColor = &Theme::getThemeColor(Theme::PLAYER);
+ }
+ else
+ {
+ mTextColor = &userPalette->getColor(Theme::PLAYER);
- if (sfx && !ed->mSFXEffect.empty())
- sound.playSfx(ed->mSFXEffect);
-}
+ if (mIsGM)
+ {
+ mTextColor = &userPalette->getColor(UserPalette::GM);
+ mNameColor = &userPalette->getColor(UserPalette::GM);
+ }
+ else if (mParty && mParty == player_node->getParty())
+ {
+ mNameColor = &userPalette->getColor(UserPalette::PARTY);
+ }
+ else
+ {
+ mNameColor = &userPalette->getColor(UserPalette::PC);
+ }
+ }
-void Being::updateCoords()
-{
if (mDispName)
{
- mDispName->adviseXY(getPixelX(), getPixelY());
+ mDispName->setColor(mNameColor);
}
}
-void Being::flashName(int time)
+void Being::setSprite(unsigned int slot, int id, const std::string &color,
+ bool isWeapon)
{
- if (mDispName)
- mDispName->flash(time);
-}
+ assert(slot < Net::getCharHandler()->maxSprite());
-void Being::showName()
-{
- delete mDispName;
- mDispName = 0;
- std::string mDisplayName(mName);
+ if (slot >= size())
+ ensureSize(slot + 1);
- if (getType() == PLAYER)
+ if (slot >= mSpriteIDs.size())
+ mSpriteIDs.resize(slot + 1, 0);
+
+ if (slot >= mSpriteColors.size())
+ mSpriteColors.resize(slot + 1, "");
+
+ // id = 0 means unequip
+ if (id == 0)
{
- if (config.getValue("showgender", false))
- {
- Player* player = static_cast<Player*>(this);
- if (player)
- {
- if (player->getGender() == GENDER_FEMALE)
- mDisplayName += " \u2640";
- else
- mDisplayName += " \u2642";
- }
- }
+ removeSprite(slot);
+
+ if (isWeapon)
+ mEquippedWeapon = NULL;
}
- else if (getType() == MONSTER)
+ else
{
- if (config.getValue("showMonstersTakedDamage", false))
+ std::string filename = ItemDB::get(id).getSprite(mGender);
+ AnimatedSprite *equipmentSprite = NULL;
+
+ if (!filename.empty())
{
- mDisplayName += ", " + toString(getDamageTaken());
+ if (!color.empty())
+ filename += "|" + color;
+
+ equipmentSprite = AnimatedSprite::load(
+ paths.getStringValue("sprites") + filename);
}
+
+ if (equipmentSprite)
+ equipmentSprite->setDirection(getSpriteDirection());
+
+ CompoundSprite::setSprite(slot, equipmentSprite);
+
+ if (isWeapon)
+ mEquippedWeapon = &ItemDB::get(id);
+
+ setAction(mAction);
}
- mDispName = new FlashText(mDisplayName, getPixelX(), getPixelY(),
- gcn::Graphics::CENTER, mNameColor);
+ mSpriteIDs[slot] = id;
+ mSpriteColors[slot] = color;
+}
+
+void Being::setSpriteID(unsigned int slot, int id)
+{
+ setSprite(slot, id, mSpriteColors[slot]);
+}
+
+void Being::setSpriteColor(unsigned int slot, const std::string &color)
+{
+ setSprite(slot, mSpriteIDs[slot], color);
}
int Being::getNumberOfLayers() const
{
- return mSprites.size();
+ return CompoundSprite::getNumberOfLayers();
}
void Being::load()
@@ -1023,7 +1155,7 @@ void Being::load()
int hairstyles = 1;
while (ItemDB::get(-hairstyles).getSprite(GENDER_MALE) !=
- paths.getValue("spriteErrorFile", "error.xml"))
+ paths.getStringValue("spriteErrorFile"))
hairstyles++;
mNumberOfHairstyles = hairstyles;
@@ -1034,3 +1166,57 @@ void Being::updateName()
if (mShowName)
showName();
}
+
+void Being::setGender(Gender gender)
+{
+ if (gender != mGender)
+ {
+ mGender = gender;
+
+ // Reload all subsprites
+ for (unsigned int i = 0; i < mSpriteIDs.size(); i++)
+ {
+ if (mSpriteIDs.at(i) != 0)
+ setSprite(i, mSpriteIDs.at(i), mSpriteColors.at(i));
+ }
+
+ updateName();
+ }
+}
+
+void Being::setGM(bool gm)
+{
+ mIsGM = gm;
+
+ updateColors();
+}
+
+bool Being::canTalk()
+{
+ return mType == NPC;
+}
+
+void Being::talkTo()
+{
+ Mana::Event event("doTalk");
+ event.setInt("npcId", mId);
+ event.trigger("NPC");
+}
+
+void Being::event(const std::string &channel, const Mana::Event &event)
+{
+ if (channel == "Chat" &&
+ (event.getName() == "Being" || event.getName() == "Player") &&
+ event.getInt("permissions") & PlayerRelation::SPEECH_FLOAT)
+ {
+ try
+ {
+ if (mId == event.getInt("beingId"))
+ {
+ setSpeech(event.getString("text"));
+ }
+ }
+ catch (Mana::BadEvent badEvent)
+ {}
+ }
+}
diff --git a/src/being.h b/src/being.h
index 71b3e2cf..a55e2d3a 100644
--- a/src/being.h
+++ b/src/being.h
@@ -22,19 +22,19 @@
#ifndef BEING_H
#define BEING_H
+#include "actorsprite.h"
#include "configlistener.h"
+#include "listener.h"
#include "map.h"
#include "particlecontainer.h"
#include "position.h"
-#include "sprite.h"
#include "vector.h"
-#include "resources/spritedef.h"
-
#include <guichan/color.hpp>
#include <SDL_types.h>
+#include <map>
#include <set>
#include <string>
#include <vector>
@@ -45,31 +45,27 @@
#define SPEECH_TIME 500
#define SPEECH_MAX_TIME 1000
-class AnimatedSprite;
+class BeingInfo;
class FlashText;
-class Graphics;
-class Image;
+class Guild;
class ItemInfo;
class Item;
class Particle;
+class Party;
class Position;
-class SimpleAnimation;
class SpeechBubble;
class Text;
-class StatusEffect;
+enum Gender
+{
+ GENDER_MALE = 0,
+ GENDER_FEMALE = 1,
+ GENDER_UNSPECIFIED = 2
+};
-class Being : public Sprite, public ConfigListener
+class Being : public ActorSprite, public ConfigListener, public Mana::Listener
{
public:
- enum Type
- {
- UNKNOWN,
- PLAYER,
- NPC,
- MONSTER
- };
-
/**
* Action the being is currently performing
* WARNING: Has to be in sync with the same enum in the Being class
@@ -78,21 +74,13 @@ class Being : public Sprite, public ConfigListener
enum Action
{
STAND,
- WALK,
+ MOVE,
ATTACK,
SIT,
DEAD,
HURT
};
- enum TargetCursorSize
- {
- TC_SMALL = 0,
- TC_MEDIUM,
- TC_LARGE,
- NUM_TC
- };
-
enum Speech
{
NO_SPEECH = 0,
@@ -128,29 +116,27 @@ class Being : public Sprite, public ConfigListener
* @param subtype partly determines the type of the being
* @param map the map the being is on
*/
- Being(int id, int subtype, Map *map);
+ Being(int id, Type type, int subtype, Map *map);
virtual ~Being();
+ Type getType() const { return mType; }
+
/**
* Removes all path nodes from this being.
*/
void clearPath();
/**
- * Returns the walk time.
- * Used to know which frame to display and trigger
- * the next Tile step.
- * TODO: Used by eAthena only?
+ * Returns the time spent in the current action.
*/
- int getWalkTime() const { return mWalkTime; }
+ int getActionTime() const { return mActionTime; }
/**
- * Set the current WalkTime value.
- * TODO: Used by eAthena only?
+ * Set the current action time.
* @see Ea::BeingHandler that set it to tick time.
*/
- void setWalkTime(int walkTime) { mWalkTime = walkTime; }
+ void setActionTime(int actionTime) { mActionTime = actionTime; }
/**
* Makes this being take the next tile of its path.
@@ -216,7 +202,7 @@ class Being : public Sprite, public ConfigListener
* @param damage the amount of damage recieved (0 means miss)
* @param type the attack type
*/
- virtual void takeDamage(Being *attacker, int damage, AttackType type);
+ void takeDamage(Being *attacker, int damage, AttackType type);
/**
* Handles an attack of another being by this being.
@@ -238,23 +224,82 @@ class Being : public Sprite, public ConfigListener
*
* @param name The name that should appear.
*/
- virtual void setName(const std::string &name);
+ void setName(const std::string &name);
bool getShowName() const
{ return mShowName; }
- virtual void setShowName(bool doShowName);
+ void setShowName(bool doShowName);
/**
- * Following are set from the server (mainly for players)
+ * Sets the name of the party the being is in. Shown in BeingPopup.
*/
void setPartyName(const std::string &name) { mPartyName = name; }
const std::string &getPartyName() const { return mPartyName; }
- virtual void setGuildName(const std::string &name);
+ /**
+ * Sets the name of the primary guild the being is in. Shown in
+ * BeingPopup (eventually).
+ */
+ void setGuildName(const std::string &name);
+
+ void setGuildPos(const std::string &pos);
- virtual void setGuildPos(const std::string &pos);
+ /**
+ * Adds a guild to the being.
+ */
+ void addGuild(Guild *guild);
+
+ /**
+ * Removers a guild from the being.
+ */
+ void removeGuild(int id);
+
+ /**
+ * Returns a pointer to the specified guild that the being is in.
+ */
+ Guild *getGuild(const std::string &guildName) const;
+
+ /**
+ * Returns a pointer to the specified guild that the being is in.
+ */
+ Guild *getGuild(int id) const;
+
+ /**
+ * Returns all guilds the being is in.
+ */
+ const std::map<int, Guild*> &getGuilds() const
+ { return mGuilds; }
+
+ /**
+ * Removes all guilds the being is in.
+ */
+ void clearGuilds();
+
+ /**
+ * Get number of guilds the being belongs to.
+ */
+ short getNumberOfGuilds() const
+ { return mGuilds.size(); }
+
+ bool isInParty() const
+ { return mParty != NULL; }
+
+ void setParty(Party *party);
+
+ Party *getParty() const
+ { return mParty; }
+
+ /**
+ * Sets visible equipments for this being.
+ */
+ void setSprite(unsigned int slot, int id,
+ const std::string &color = "", bool isWeapon = false);
+
+ void setSpriteID(unsigned int slot, int id);
+
+ void setSpriteColor(unsigned int slot, const std::string &color = "");
/**
* Get the number of hairstyles implemented
@@ -282,20 +327,27 @@ class Being : public Sprite, public ConfigListener
*/
void drawEmotion(Graphics *graphics, int offsetX, int offsetY);
- /**
- * Returns the type of the being.
- */
- virtual Type getType() const { return UNKNOWN; }
-
- /**
- * Return Being's current Job (player job, npc, monster, creature )
- */
Uint16 getSubType() const { return mSubType; }
/**
- * Set Being's current Job (player job, npc, monster, creature )
+ * Set Being's subtype (mostly for view for monsters and NPCs)
*/
- virtual void setSubtype(Uint16 subtype) { mSubType = subtype; }
+ void setSubtype(Uint16 subtype);
+
+ const BeingInfo *getInfo() const
+ { return mInfo; }
+
+ TargetCursorSize getTargetCursorSize() const;
+
+ /**
+ * Gets the way the object is blocked by other objects.
+ */
+ unsigned char getWalkMask() const;
+
+ /**
+ * Gets the way the monster blocks pathfinding for other objects
+ */
+ Map::BlockType getBlockType() const;
/**
* Sets the walk speed.
@@ -324,18 +376,6 @@ class Being : public Sprite, public ConfigListener
int getAttackSpeed() const { return mAttackSpeed; }
/**
- * Sets the sprite id.
- */
- void setId(int id) { mId = id; }
-
- int getId() const { return mId; }
-
- /**
- * Sets the map the being is on
- */
- void setMap(Map *map);
-
- /**
* Sets the current action.
*/
virtual void setAction(Action action, int attackType = 0);
@@ -361,65 +401,11 @@ class Being : public Sprite, public ConfigListener
void setDirection(Uint8 direction);
/**
- * Returns the being's current sprite frame number.
- */
- int getCurrentFrame() const { return mFrame; }
-
- /**
- * Set the being's current sprite frame number.
- */
- void setFrame(int frame) { mFrame = frame; }
-
- /**
* Returns the direction the being is facing.
*/
SpriteDirection getSpriteDirection() const
{ return SpriteDirection(mSpriteDirection); }
- /**
- * Draws this being to the given graphics context.
- *
- * @see Sprite::draw(Graphics, int, int)
- *
- * TODO: The following two functions should be combined.
- * at some point draw(), was changed to use mPx and mPy, with arugements
- * only for the offset, drawSpriteAt() takes x, and y and draws the sprite
- * exactly at those coords (though it does do some computing to work how the
- * old draw() worked).
- */
- virtual void draw(Graphics *graphics, int offsetX, int offsetY) const;
-
- virtual void drawSpriteAt(Graphics *graphics, int x, int y) const;
-
- /**
- * Set the alpha opacity used to draw the being.
- */
- virtual void setAlpha(float alpha)
- { mAlpha = alpha; }
-
- /**
- * Returns the current alpha opacity of the Being.
- */
- virtual float getAlpha() const
- { return mAlpha; }
-
- /**
- * Returns the X coordinate in pixels.
- */
- int getPixelX() const
- { return (int) mPos.x; }
-
- /**
- * Returns the Y coordinate in pixels.
- *
- * @see Sprite::getPixelY()
- */
- int getPixelY() const
- { return (int) mPos.y; }
-
- /**
- * Sets the position of this being.
- */
void setPosition(const Vector &pos);
/**
@@ -427,17 +413,12 @@ class Being : public Sprite, public ConfigListener
*
* @see setPosition(const Vector &pos)
*/
- void setPosition(float x, float y, float z = 0.0f)
+ inline void setPosition(float x, float y, float z = 0.0f)
{
setPosition(Vector(x, y, z));
}
/**
- * Returns the position of this being.
- */
- const Vector &getPosition() const { return mPos; }
-
- /**
* Returns the horizontal size of the current base sprite of the being.
*/
virtual int getWidth() const;
@@ -453,45 +434,17 @@ class Being : public Sprite, public ConfigListener
virtual int getCollisionRadius() const;
/**
- * Returns the required size of a target cursor for this being.
- */
- virtual Being::TargetCursorSize getTargetCursorSize() const
- { return TC_MEDIUM; }
-
- /**
- * Take control of a particle.
- */
- void controlParticle(Particle *particle);
-
- /**
* Shoots a missile particle from this being, to target being
*/
void fireMissile(Being *target, const std::string &particle);
/**
- * Gets the way the object is blocked by other objects.
- */
- virtual unsigned char getWalkMask() const
- { return 0x00; } //can walk through everything
-
- /**
* Returns the path this being is following. An empty path is returned
* when this being isn't following any path currently.
*/
const Path &getPath() const { return mPath; }
/**
- * Sets the target animation for this being.
- */
- void setTargetAnimation(SimpleAnimation *animation);
-
- /**
- * Untargets the being
- */
- void untarget() { mUsedTargetCursor = NULL; }
-
-
- /**
* Set the Emoticon type and time displayed above
* the being.
*/
@@ -507,45 +460,9 @@ class Being : public Sprite, public ConfigListener
*/
Uint8 getEmotion() const { return mEmotion; }
- /**
- * 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 AnimatedSprite *getSprite(int index) const
- { return mSprites[index]; }
-
static void load();
- virtual void optionChanged(const std::string &value) {}
+ virtual void optionChanged(const std::string &value);
void flashName(int time);
@@ -554,78 +471,65 @@ class Being : public Sprite, public ConfigListener
void updateName();
- protected:
/**
- * Sets the new path for this being.
+ * Sets the gender of this being.
*/
- void setPath(const Path &path);
+ virtual void setGender(Gender gender);
- /**
- * Updates name's location.
- */
- virtual void updateCoords();
+ Gender getGender() const
+ { return mGender; }
/**
- * Gets the way the object blocks pathfinding for other objects
+ * Whether or not this player is a GM.
*/
- virtual Map::BlockType getBlockType() const
- { return Map::BLOCKTYPE_NONE; }
+ bool isGM() const
+ { return mIsGM; }
/**
- * Trigger visual effect, with components
- *
- * \param effectId ID of the effect to trigger
- * \param sfx Whether to trigger sound effects
- * \param gfx Whether to trigger graphical effects
+ * Triggers whether or not to show the name as a GM name.
*/
- void internalTriggerEffect(int effectId, bool sfx, bool gfx);
+ void setGM(bool gm);
- /**
- * Notify self that the stun mode has been updated. Invoked by
- * setStunMode if something changed.
- */
- virtual void updateStunMode(int oldMode, int newMode);
+ bool canTalk();
+
+ void talkTo();
+ void event(const std::string &channel, const Mana::Event &event);
+
+ protected:
/**
- * Notify self that a status effect has flipped.
- * The new flag is passed.
+ * Sets the new path for this being.
*/
- virtual void updateStatusEffect(int index, bool newStatus);
+ void setPath(const Path &path);
/**
- * Handle an update to a status or stun effect
- *
- * \param The StatusEffect to effect
- * \param effectId -1 for stun, otherwise the effect index
+ * Updates name's location.
*/
- virtual void handleStatusEffect(StatusEffect *effect, int effectId);
+ void updateCoords();
- virtual void showName();
+ void showName();
- /** The current sprite Frame number to be displayed */
- int mFrame;
+ void updateColors();
- /** Used to trigger the nextStep (walking on next Tile)
- * TODO: Used by eAthena only?
- */
- int mWalkTime;
+ BeingInfo *mInfo;
+
+ int mActionTime; /**< Time spent in current action */
int mEmotion; /**< Currently showing emotion */
int mEmotionTime; /**< Time until emotion disappears */
/** Time until the last speech sentence disappears */
int mSpeechTime;
+ int mAttackType;
int mAttackSpeed; /**< Attack speed */
+
Action mAction; /**< Action the being is performing */
Uint16 mSubType; /**< Subtype (graphical view, basically) */
- int mId; /**< Unique sprite id */
Uint8 mDirection; /**< Facing direction */
Uint8 mSpriteDirection; /**< Facing direction */
- Map *mMap; /**< Map on which this being resides */
std::string mName; /**< Name of character */
std::string mPartyName;
- MapSprite mMapSprite;
/**
* Holds a text object when the being displays it's name, 0 otherwise
@@ -643,20 +547,18 @@ class Being : public Sprite, public ConfigListener
std::string mSpeech;
Text *mText;
const gcn::Color *mTextColor;
- Uint16 mStunMode; /**< Stun mode; zero if not stunned */
- std::set<int> mStatusEffects; /**< set of active status effects */
- typedef std::vector<AnimatedSprite*> Sprites;
- typedef Sprites::iterator SpriteIterator;
- typedef Sprites::const_iterator SpriteConstIterator;
- Sprites mSprites;
- float mAlpha; /**< Alpha opacity to draw the sprite */
+ Vector mDest; /**< destination coordinates. */
- ParticleList mStunParticleEffects;
- ParticleVector mStatusParticleEffects;
- ParticleList mChildParticleEffects;
+ std::vector<int> mSpriteIDs;
+ std::vector<std::string> mSpriteColors;
+ Gender mGender;
- Vector mDest; /**< destination coordinates. */
+ // Character guild information
+ std::map<int, Guild*> mGuilds;
+ Party *mParty;
+
+ bool mIsGM;
private:
@@ -667,8 +569,7 @@ class Being : public Sprite, public ConfigListener
*/
int getOffset(char pos, char neg) const;
- /** Reset particle status effects on next redraw? */
- bool mMustResetParticles;
+ const Type mType;
/** Speech Bubble components */
SpeechBubble *mSpeechBubble;
@@ -681,13 +582,9 @@ class Being : public Sprite, public ConfigListener
*/
Vector mWalkSpeed;
- Vector mPos; /**< Position coordinates. */
int mX, mY; /**< Position in tile */
int mDamageTaken;
-
- /** Target cursor being used */
- SimpleAnimation *mUsedTargetCursor;
};
#endif
diff --git a/src/beingmanager.cpp b/src/beingmanager.cpp
deleted file mode 100644
index 656b297e..00000000
--- a/src/beingmanager.cpp
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "beingmanager.h"
-
-#include "localplayer.h"
-#include "monster.h"
-#include "npc.h"
-#include "player.h"
-
-#include "gui/viewport.h"
-
-#include "net/gamehandler.h"
-#include "net/net.h"
-
-#include "utils/stringutils.h"
-#include "utils/dtor.h"
-
-#include <cassert>
-
-class FindBeingFunctor
-{
- public:
- bool operator() (Being *being)
- {
- Uint16 other_y = y + ((being->getType() == Being::NPC) ? 1 : 0);
- const Vector &pos = being->getPosition();
- return ((int) pos.x / 32 == x &&
- ((int) pos.y / 32 == y || (int) pos.y / 32 == other_y) &&
- being->isAlive() &&
- (type == Being::UNKNOWN || being->getType() == type));
- }
-
- Uint16 x, y;
- Being::Type type;
-} beingFinder;
-
-BeingManager::BeingManager()
-{
-}
-
-BeingManager::~BeingManager()
-{
- clear();
-}
-
-void BeingManager::setMap(Map *map)
-{
- mMap = map;
- if (player_node)
- player_node->setMap(map);
-}
-
-void BeingManager::setPlayer(LocalPlayer *player)
-{
- player_node = player;
- mBeings.push_back(player);
-}
-
-Being *BeingManager::createBeing(int id, Being::Type type, int subtype)
-{
- Being *being;
-
- switch (type)
- {
- case Being::PLAYER:
- being = new Player(id, subtype, mMap);
- break;
- case Being::NPC:
- being = new NPC(id, subtype, mMap);
- break;
- case Being::MONSTER:
- being = new Monster(id, subtype, mMap);
- break;
- case Being::UNKNOWN:
- being = new Being(id, subtype, mMap);
- break;
- default:
- assert(false);
- }
-
- mBeings.push_back(being);
- return being;
-}
-
-void BeingManager::destroyBeing(Being *being)
-{
- mBeings.remove(being);
- viewport->clearHoverBeing(being);
- delete being;
-}
-
-Being *BeingManager::findBeing(int id) const
-{
- for (Beings::const_iterator i = mBeings.begin(), i_end = mBeings.end();
- i != i_end; ++i)
- {
- Being *being = (*i);
- if (being->getId() == id)
- return being;
- }
- return NULL;
-}
-
-Being *BeingManager::findBeing(int x, int y, Being::Type type) const
-{
- beingFinder.x = x;
- beingFinder.y = y;
- beingFinder.type = type;
-
- Beings::const_iterator i = find_if(mBeings.begin(), mBeings.end(),
- beingFinder);
-
- return (i == mBeings.end()) ? NULL : *i;
-}
-
-Being *BeingManager::findBeingByPixel(int x, int y) const
-{
- Beings::const_iterator itr = mBeings.begin();
- Beings::const_iterator itr_end = mBeings.end();
-
- for (; itr != itr_end; ++itr)
- {
- Being *being = (*itr);
-
- int xtol = being->getWidth() / 2;
- int uptol = being->getHeight();
-
- if ((being->isAlive()) &&
- (being != player_node) &&
- (being->getPixelX() - xtol <= x) &&
- (being->getPixelX() + xtol >= x) &&
- (being->getPixelY() - uptol <= y) &&
- (being->getPixelY() >= y))
- {
- return being;
- }
- }
-
- return NULL;
-}
-
-Being *BeingManager::findBeingByName(const std::string &name,
- Being::Type type) const
-{
- for (Beings::const_iterator i = mBeings.begin(), i_end = mBeings.end();
- i != i_end; ++i)
- {
- Being *being = (*i);
- if (being->getName() == name &&
- (type == Being::UNKNOWN || type == being->getType()))
- return being;
- }
- return NULL;
-}
-
-const Beings &BeingManager::getAll() const
-{
- return mBeings;
-}
-
-void BeingManager::logic()
-{
- Beings::iterator i = mBeings.begin();
- while (i != mBeings.end())
- {
- Being *being = (*i);
-
- being->logic();
-
- if (!being->isAlive() &&
- Net::getGameHandler()->removeDeadBeings() &&
- being->getCurrentFrame() >= 20)
- {
- delete being;
- i = mBeings.erase(i);
- }
- else
- {
- ++i;
- }
- }
-}
-
-void BeingManager::clear()
-{
- if (player_node)
- mBeings.remove(player_node);
-
- delete_all(mBeings);
- mBeings.clear();
-
- if (player_node)
- mBeings.push_back(player_node);
-}
-
-Being *BeingManager::findNearestLivingBeing(int x, int y,
- int maxTileDist, Being::Type type,
- Being *excluded) const
-{
- Being *closestBeing = 0;
- int dist = 0;
-
- const int maxDist = maxTileDist * 32;
-
- Beings::const_iterator itr = mBeings.begin();
- Beings::const_iterator itr_end = mBeings.end();
-
- for (; itr != itr_end; ++itr)
- {
- Being *being = (*itr);
- const Vector &pos = being->getPosition();
- int d = abs(((int) pos.x) - x) + abs(((int) pos.y) - y);
-
- if ((being->getType() == type || type == Being::UNKNOWN)
- && (d < dist || !closestBeing) // it is closer
- && being->isAlive() // no dead beings
- && being != excluded)
- {
- dist = d;
- closestBeing = being;
- }
- }
-
- return (maxDist >= dist) ? closestBeing : 0;
-}
-
-Being *BeingManager::findNearestLivingBeing(Being *aroundBeing, int maxDist,
- Being::Type type) const
-{
- const Vector &pos = aroundBeing->getPosition();
- return findNearestLivingBeing((int)pos.x, (int)pos.y, maxDist, type,
- aroundBeing);
-}
-
-bool BeingManager::hasBeing(Being *being) const
-{
- for (Beings::const_iterator i = mBeings.begin(), i_end = mBeings.end();
- i != i_end; ++i)
- {
- if (being == *i)
- return true;
- }
-
- return false;
-}
-
-void BeingManager::getPlayerNames(std::vector<std::string> &names,
- bool npcNames)
-{
- Beings::iterator i = mBeings.begin();
- names.clear();
-
- while (i != mBeings.end())
- {
- Being *being = (*i);
- if ((being->getType() == Being::PLAYER
- || (being->getType() == Being::NPC && npcNames))
- && being->getName() != "")
- {
- names.push_back(being->getName());
- }
- ++i;
- }
-}
-
-void BeingManager::updatePlayerNames()
-{
- Beings::iterator i = mBeings.begin();
-
- while (i != mBeings.end())
- {
- Being *being = (*i);
- if (being->getType() == Being::PLAYER && being->getName() != "")
- being->updateName();
- ++i;
- }
-}
diff --git a/src/chatlog.cpp b/src/chatlog.cpp
new file mode 100644
index 00000000..d45bea22
--- /dev/null
+++ b/src/chatlog.cpp
@@ -0,0 +1,176 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * 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 "chatlog.h"
+
+#include <iostream>
+#include <sstream>
+#include <dirent.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#ifdef WIN32
+#include <windows.h>
+#elif defined __APPLE__
+#include <Carbon/Carbon.h>
+#endif
+
+#include "log.h"
+#include "configuration.h"
+
+#include "utils/stringutils.h"
+
+ChatLogger::ChatLogger()
+{
+}
+
+ChatLogger::~ChatLogger()
+{
+ if (mLogFile.is_open())
+ mLogFile.close();
+}
+
+void ChatLogger::setLogFile(const std::string &logFilename)
+{
+ if (mLogFile.is_open())
+ mLogFile.close();
+
+ mLogFile.open(logFilename.c_str(), std::ios_base::app);
+
+ if (!mLogFile.is_open())
+ {
+ std::cout << "Warning: error while opening " << logFilename <<
+ " for writing.\n";
+ }
+}
+
+void ChatLogger::setLogDir(const std::string &logDir)
+{
+ mLogDir = logDir;
+
+ if (mLogFile.is_open())
+ mLogFile.close();
+
+ DIR *dir = opendir(mLogDir.c_str());
+ if (!dir)
+ makeDir(mLogDir);
+ else
+ closedir(dir);
+}
+
+void ChatLogger::log(std::string str)
+{
+ std::string dateStr = getDateString();
+ if (!mLogFile.is_open() || dateStr != mLogDate)
+ {
+ mLogDate = dateStr;
+ setLogFile(strprintf("%s/%s/#General_%s.log", mLogDir.c_str(),
+ mServerName.c_str(), dateStr.c_str()));
+ }
+
+ str = removeColors(str);
+ writeTo(mLogFile, str);
+}
+
+void ChatLogger::log(std::string name, std::string str)
+{
+ std::ofstream logFile;
+ logFile.open(strprintf("%s/%s/%s_%s.log", mLogDir.c_str(), mServerName.c_str(),
+ secureName(name).c_str(), getDateString().c_str()).c_str(),
+ std::ios_base::app);
+
+ if (!logFile.is_open())
+ return;
+
+ str = removeColors(str);
+ writeTo(logFile, str);
+
+ if (logFile.is_open())
+ logFile.close();
+}
+
+std::string ChatLogger::getDateString() const
+{
+ std::string date;
+
+ time_t rawtime;
+ struct tm *timeinfo;
+ char buffer [80];
+
+ time (&rawtime);
+ timeinfo = localtime(&rawtime);
+
+ strftime(buffer, 79, "%y-%m-%d", timeinfo);
+ date = buffer;
+ return date;
+}
+
+std::string ChatLogger::secureName(std::string &name) const
+{
+ for (unsigned int f = 0; f < name.length(); f ++)
+ {
+ if (name[f] < '0' && name[f] > '9' && name[f] < 'a' && name[f] > 'z'
+ && name[f] < 'A' && name[f] > 'Z'
+ && name[f] != '-' && name[f] != '+' && name[f] != '='
+ && name[f] != '.' && name[f] != ','&& name[f] != ')'
+ && name[f] != '(' && name[f] != '[' && name[f] != ')')
+ {
+ name[f] = '_';
+ }
+ }
+ return name;
+}
+
+void ChatLogger::writeTo(std::ofstream &file, const std::string &str) const
+{
+ file << str << std::endl;
+}
+
+void ChatLogger::setServerName(const std::string &serverName)
+{
+ mServerName = serverName;
+ if (mServerName == "")
+ mServerName = config.getStringValue("MostUsedServerName0");
+
+ if (mLogFile.is_open())
+ mLogFile.close();
+
+ secureName(mServerName);
+ if (mLogDir != "")
+ {
+ DIR *dir = opendir((mLogDir + "/" + mServerName).c_str());
+ if (!dir)
+ makeDir(mLogDir + "/" + mServerName);
+ else
+ closedir(dir);
+ }
+}
+
+void ChatLogger::makeDir(const std::string &dir)
+{
+#ifdef WIN32
+ mkdir(dir.c_str());
+#else
+ mkdir(dir.c_str(), 0750);
+#endif
+}
diff --git a/src/chatlog.h b/src/chatlog.h
new file mode 100644
index 00000000..c359e953
--- /dev/null
+++ b/src/chatlog.h
@@ -0,0 +1,73 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * 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 _CHATLOG_H
+#define _CHATLOG_H
+
+#include <fstream>
+
+class ChatLogger
+{
+ public:
+ /**
+ * Constructor.
+ */
+ ChatLogger();
+
+ /**
+ * Destructor, closes log file.
+ */
+ ~ChatLogger();
+
+ void setLogDir(const std::string &logDir);
+
+ /**
+ * Enters a message in the log. The message will be timestamped.
+ */
+ void log(std::string str);
+
+ void log(std::string name, std::string str);
+
+ std::string getDateString() const;
+
+ std::string secureName(std::string &str) const;
+
+ void setServerName(const std::string &serverName);
+
+ private:
+ /**
+ * Sets the file to log to and opens it
+ */
+ void setLogFile(const std::string &logFilename);
+
+ void writeTo(std::ofstream &file, const std::string &str) const;
+
+ void makeDir(const std::string &dir);
+
+ std::ofstream mLogFile;
+ std::string mLogDir;
+ std::string mServerName;
+ std::string mLogDate;
+};
+
+extern ChatLogger *chatLogger;
+
+#endif
diff --git a/src/client.cpp b/src/client.cpp
index b63550e6..1e1d17a9 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -22,8 +22,10 @@
#include "client.h"
#include "main.h"
+#include "chatlog.h"
#include "configuration.h"
#include "emoteshortcut.h"
+#include "event.h"
#include "game.h"
#include "itemshortcut.h"
#include "keyboardconfig.h"
@@ -47,10 +49,8 @@
#include "gui/sdlinput.h"
#include "gui/serverdialog.h"
#include "gui/setup.h"
-#include "gui/theme.h"
#include "gui/unregisterdialog.h"
#include "gui/updatewindow.h"
-#include "gui/userpalette.h"
#include "gui/worldselectdialog.h"
#include "gui/widgets/button.h"
@@ -69,8 +69,11 @@
#include "resources/image.h"
#include "resources/itemdb.h"
#include "resources/monsterdb.h"
+#include "resources/specialdb.h"
#include "resources/npcdb.h"
#include "resources/resourcemanager.h"
+#include "resources/theme.h"
+#include "resources/userpalette.h"
#include "utils/gettext.h"
#include "utils/mkdir.h"
@@ -111,6 +114,7 @@ Configuration config; /**< XML file configuration reader */
Configuration branding; /**< XML branding information reader */
Configuration paths; /**< XML default paths information reader */
Logger *logger; /**< Log object */
+ChatLogger *chatLogger; /**< Chat log object */
KeyboardConfig keyboard;
UserPalette *userPalette;
@@ -215,14 +219,21 @@ Client::Client(const Options &options):
if (!options.brandingPath.empty())
{
branding.init(options.brandingPath);
+ branding.setDefaultValues(getBrandingDefaults());
}
initHomeDir();
initConfiguration();
+ chatLogger = new ChatLogger;
+ if (options.chatLogDir == "")
+ chatLogger->setLogDir(mLocalDataDir + std::string("/logs/"));
+ else
+ chatLogger->setLogDir(options.chatLogDir);
+
// Configure logger
logger->setLogFile(mLocalDataDir + std::string("/mana.log"));
- logger->setLogToStandardOut(config.getValue("logToStandardOut", 0));
+ logger->setLogToStandardOut(config.getBoolValue("logToStandardOut"));
// Log the mana version
logger->log("Mana %s", FULL_VERSION);
@@ -326,11 +337,11 @@ Client::Client(const Options &options):
graphics = new Graphics;
#endif
- const int width = (int) config.getValue("screenwidth", defaultScreenWidth);
- const int height = (int) config.getValue("screenheight", defaultScreenHeight);
+ const int width = config.getIntValue("screenwidth");
+ const int height = config.getIntValue("screenheight");
const int bpp = 0;
- const bool fullscreen = ((int) config.getValue("screen", 0) == 1);
- const bool hwaccel = ((int) config.getValue("hwaccel", 0) == 1);
+ const bool fullscreen = config.getBoolValue("screen");
+ const bool hwaccel = config.getBoolValue("hwaccel");
// Try to set the desired video mode
if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel))
@@ -353,13 +364,11 @@ Client::Client(const Options &options):
// Initialize sound engine
try
{
- if (config.getValue("sound", 0) == 1)
+ if (config.getBoolValue("sound"))
sound.init();
- sound.setSfxVolume((int) config.getValue("sfxVolume",
- defaultSfxVolume));
- sound.setMusicVolume((int) config.getValue("musicVolume",
- defaultMusicVolume));
+ sound.setSfxVolume(config.getIntValue("sfxVolume"));
+ sound.setMusicVolume(config.getIntValue("musicVolume"));
}
catch (const char *err)
{
@@ -384,25 +393,25 @@ Client::Client(const Options &options):
mCurrentServer.port = options.serverPort;
loginData.username = options.username;
loginData.password = options.password;
- loginData.remember = config.getValue("remember", 0);
+ loginData.remember = config.getBoolValue("remember");
loginData.registerLogin = false;
if (mCurrentServer.hostname.empty())
- {
- mCurrentServer.hostname = branding.getValue("defaultServer",
- "").c_str();
- }
+ mCurrentServer.hostname = branding.getValue("defaultServer","").c_str();
if (mCurrentServer.port == 0)
{
mCurrentServer.port = (short) branding.getValue("defaultPort",
- DEFAULT_PORT);
+ DEFAULT_PORT);
mCurrentServer.type = ServerInfo::parseType(
- branding.getValue("defaultServerType", "tmwathena"));
+ branding.getValue("defaultServerType", "tmwathena"));
}
+ if (chatLogger)
+ chatLogger->setServerName(mCurrentServer.hostname);
+
if (loginData.username.empty() && loginData.remember)
- loginData.username = config.getValue("username", "");
+ loginData.username = config.getStringValue("username");
if (mState != STATE_ERROR)
mState = STATE_CHOOSE_SERVER;
@@ -416,6 +425,9 @@ Client::Client(const Options &options):
SDL_initFramerate(&mFpsManager);
config.addListener("fpslimit", this);
optionChanged("fpslimit");
+
+ // Initialize PlayerInfo
+ PlayerInfo::init();
}
Client::~Client()
@@ -561,10 +573,8 @@ int Client::exec()
- 3, 3);
top->add(mSetupButton);
- int screenWidth = (int) config.getValue("screenwidth",
- defaultScreenWidth);
- int screenHeight = (int) config.getValue("screenheight",
- defaultScreenHeight);
+ int screenWidth = config.getIntValue("screenwidth");
+ int screenHeight = config.getIntValue("screenheight");
mDesktop->setSize(screenWidth, screenHeight);
}
@@ -576,9 +586,12 @@ int Client::exec()
if (mState != mOldState)
{
- Net::GeneralHandler *generalHandler = Net::getGeneralHandler();
- if (generalHandler)
- generalHandler->stateChanged(mOldState, mState);
+ {
+ Mana::Event event("StateChange");
+ event.setInt("oldState", mOldState);
+ event.setInt("newState", mState);
+ event.trigger("Client");
+ }
if (mOldState == STATE_GAME)
{
@@ -730,17 +743,21 @@ int Client::exec()
// Read default paths file 'data/paths.xml'
paths.init("paths.xml", true);
+ paths.setDefaultValues(getPathsDefaults());
// Load XML databases
ColorDB::load();
ItemDB::load();
Being::load(); // Hairstyles
MonsterDB::load();
+ SpecialDB::load();
NPCDB::load();
EmoteDB::load();
StatusEffect::load();
Units::loadUnits();
+ ActorSprite::load();
+
mDesktop->reloadWallpaper();
mState = STATE_GET_CHARACTERS;
@@ -766,7 +783,7 @@ int Client::exec()
mOptions.character, CharSelectDialog::Choose))
{
((CharSelectDialog*) mCurrentDialog)->selectByName(
- config.getValue("lastCharacter", ""),
+ config.getStringValue("lastCharacter"),
mOptions.chooseDefault ?
CharSelectDialog::Choose :
CharSelectDialog::Focus);
@@ -978,7 +995,7 @@ int Client::exec()
void Client::optionChanged(const std::string &name)
{
- const int fpsLimit = (int) config.getValue("fpslimit", 60);
+ const int fpsLimit = config.getIntValue("fpslimit");
mLimitFps = fpsLimit > 0;
if (mLimitFps)
SDL_setFramerate(&mFpsManager, fpsLimit);
@@ -1129,6 +1146,7 @@ void Client::initConfiguration()
{
fclose(configFile);
config.init(configPath);
+ config.setDefaultValues(getConfigDefaults());
}
}
@@ -1143,7 +1161,7 @@ void Client::initUpdatesDir()
// If updatesHost is currently empty, fill it from config file
if (mUpdateHost.empty())
{
- mUpdateHost = config.getValue("updatehost", "");
+ mUpdateHost = config.getStringValue("updatehost");
}
// Don't go out of range int he next check
@@ -1151,7 +1169,7 @@ void Client::initUpdatesDir()
return;
// Remove any trailing slash at the end of the update host
- if (mUpdateHost.at(mUpdateHost.size() - 1) == '/')
+ if (!mUpdateHost.empty() && mUpdateHost.at(mUpdateHost.size() - 1) == '/')
mUpdateHost.resize(mUpdateHost.size() - 1);
// Parse out any "http://" or "ftp://", and set the updates directory
@@ -1159,7 +1177,7 @@ void Client::initUpdatesDir()
pos = mUpdateHost.find("://");
if (pos != mUpdateHost.npos)
{
- if (pos + 3 < mUpdateHost.length())
+ if (pos + 3 < mUpdateHost.length() && !mUpdateHost.empty())
{
updates << "updates/" << mUpdateHost.substr(pos + 3);
mUpdatesDir = updates.str();
@@ -1221,7 +1239,7 @@ void Client::initScreenshotDir()
else
{
std::string configScreenshotDir =
- config.getValue("screenshotDirectory", "");
+ config.getStringValue("screenshotDirectory");
if (!configScreenshotDir.empty())
mScreenshotDir = configScreenshotDir;
else
@@ -1236,7 +1254,7 @@ void Client::initScreenshotDir()
}
config.setValue("screenshotDirectory", mScreenshotDir);
- if (config.getValue("useScreenshotDirectorySuffix", true))
+ if (config.getBoolValue("useScreenshotDirectorySuffix"))
{
std::string configScreenshotSuffix =
config.getValue("screenshotDirectorySuffix",
diff --git a/src/client.h b/src/client.h
index 3c52ea37..836ac3f8 100644
--- a/src/client.h
+++ b/src/client.h
@@ -142,6 +142,7 @@ public:
std::string brandingPath;
std::string updateHost;
std::string dataPath;
+ std::string chatLogDir;
std::string configDir;
std::string localDataDir;
std::string screenshotDir;
diff --git a/src/commandhandler.cpp b/src/commandhandler.cpp
index dab51c8f..a39e13bd 100644
--- a/src/commandhandler.cpp
+++ b/src/commandhandler.cpp
@@ -27,8 +27,6 @@
#include "localplayer.h"
#include "playerrelations.h"
-#include "gui/chat.h"
-
#include "gui/widgets/channeltab.h"
#include "gui/widgets/chattab.h"
@@ -389,7 +387,7 @@ void CommandHandler::handleMsg(const std::string &args, ChatTab *tab)
if (tempNick.compare(playerName) == 0 || args.empty())
return;
- chatWindow->whisper(recvnick, msg, true);
+ chatWindow->whisper(recvnick, msg, BY_PLAYER);
}
else
tab->chatLog(_("Cannot send empty whispers!"), BY_SERVER);
diff --git a/src/compoundsprite.cpp b/src/compoundsprite.cpp
new file mode 100644
index 00000000..293e170c
--- /dev/null
+++ b/src/compoundsprite.cpp
@@ -0,0 +1,367 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "compoundsprite.h"
+
+#include "game.h"
+#include "graphics.h"
+#include "openglgraphics.h"
+#include "map.h"
+
+#include "resources/image.h"
+
+#include "utils/dtor.h"
+
+#include <SDL.h>
+
+#define BUFFER_WIDTH 100
+#define BUFFER_HEIGHT 100
+
+CompoundSprite::CompoundSprite():
+ mImage(NULL),
+ mAlphaImage(NULL),
+ mNeedsRedraw(false)
+{
+ mAlpha = 1.0f;
+}
+
+CompoundSprite::~CompoundSprite()
+{
+ SpriteIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ delete (*it);
+
+ clear();
+
+ delete mImage;
+ delete mAlphaImage;
+}
+
+bool CompoundSprite::reset()
+{
+ bool ret = false;
+
+ SpriteIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ if (*it)
+ ret |= (*it)->reset();
+
+ mNeedsRedraw |= ret;
+ return ret;
+}
+
+bool CompoundSprite::play(std::string action)
+{
+ bool ret = false;
+
+ SpriteIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ if (*it)
+ ret |= (*it)->play(action);
+
+ mNeedsRedraw |= ret;
+ return ret;
+}
+
+bool CompoundSprite::update(int time)
+{
+ bool ret = false;
+
+ SpriteIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ if (*it)
+ ret |= (*it)->update(time);
+
+ mNeedsRedraw |= ret;
+ return ret;
+}
+
+bool CompoundSprite::draw(Graphics* graphics, int posX, int posY) const
+{
+ if (mNeedsRedraw)
+ redraw();
+
+ if (mAlpha == 1.0f && mImage)
+ {
+ return graphics->drawImage(mImage, posX + mOffsetX, posY + mOffsetY);
+ }
+ else if (mAlpha && mAlphaImage)
+ {
+ if (mAlphaImage->getAlpha() != mAlpha)
+ mAlphaImage->setAlpha(mAlpha);
+
+ return graphics->drawImage(mAlphaImage,
+ posX + mOffsetX, posY + mOffsetY);
+ }
+ else
+ {
+ SpriteConstIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ {
+ if (*it)
+ {
+ if ((*it)->getAlpha() != mAlpha)
+ (*it)->setAlpha(mAlpha);
+ (*it)->draw(graphics, posX, posY);
+ }
+ }
+ }
+
+ return false;
+}
+
+int CompoundSprite::getWidth() const
+{
+ Sprite *base = NULL;
+
+ SpriteConstIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ if ((base = (*it)))
+ break;
+
+ if (base)
+ return base->getWidth();
+
+ return 0;
+}
+
+int CompoundSprite::getHeight() const
+{
+ Sprite *base = NULL;
+
+ SpriteConstIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ if ((base = (*it)))
+ break;
+
+ if (base)
+ return base->getHeight();
+
+ return 0;
+}
+
+const Image* CompoundSprite::getImage() const
+{
+ return mImage;
+}
+
+bool CompoundSprite::setDirection(SpriteDirection direction)
+{
+ bool ret = false;
+
+ SpriteIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ if (*it)
+ ret |= (*it)->setDirection(direction);
+
+ mNeedsRedraw |= ret;
+ return ret;
+}
+
+int CompoundSprite::getNumberOfLayers() const
+{
+ if (mImage || mAlphaImage)
+ {
+ return 1;
+ }
+ else
+ {
+ return size();
+ }
+}
+
+size_t CompoundSprite::getCurrentFrame() const
+{
+ SpriteConstIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ if (*it)
+ return (*it)->getCurrentFrame();
+
+ return 0;
+}
+
+size_t CompoundSprite::getFrameCount() const
+{
+ SpriteConstIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ if (*it)
+ return (*it)->getFrameCount();
+
+ return 0;
+}
+
+void CompoundSprite::addSprite(Sprite* sprite)
+{
+ push_back(sprite);
+ mNeedsRedraw = true;
+}
+
+void CompoundSprite::setSprite(int layer, Sprite* sprite)
+{
+ // Skip if it won't change anything
+ if (at(layer) == sprite)
+ return;
+
+ if (at(layer))
+ delete at(layer);
+ at(layer) = sprite;
+ mNeedsRedraw = true;
+}
+
+void CompoundSprite::removeSprite(int layer)
+{
+ // Skip if it won't change anything
+ if (at(layer) == NULL)
+ return;
+
+ delete at(layer);
+ at(layer) = NULL;
+ mNeedsRedraw = true;
+}
+
+void CompoundSprite::clear()
+{
+ // Skip if it won't change anything
+ if (empty())
+ return;
+
+ std::vector<Sprite*>::clear();
+ mNeedsRedraw = true;
+}
+
+void CompoundSprite::ensureSize(size_t layerCount)
+{
+ // Skip if it won't change anything
+ if (size() >= layerCount)
+ return;
+
+ resize(layerCount, NULL);
+ mNeedsRedraw = true;
+}
+
+/**
+ * Returns the curent frame in the current animation of the given layer.
+ */
+size_t CompoundSprite::getCurrentFrame(size_t layer)
+{
+ if (layer >= size())
+ return 0;
+
+ Sprite *s = getSprite(layer);
+ if (s)
+ return s->getCurrentFrame();
+
+ return 0;
+}
+
+/**
+ * Returns the frame count in the current animation of the given layer.
+ */
+size_t CompoundSprite::getFrameCount(size_t layer)
+{
+ if (layer >= size())
+ return 0;
+
+ Sprite *s = getSprite(layer);
+ if (s)
+ return s->getFrameCount();
+
+ return 0;
+}
+
+void CompoundSprite::redraw() const
+{
+ // TODO OpenGL support
+ if (Image::getLoadAsOpenGL())
+ {
+ mNeedsRedraw = false;
+ return;
+ }
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ int rmask = 0xff000000;
+ int gmask = 0x00ff0000;
+ int bmask = 0x0000ff00;
+ int amask = 0x000000ff;
+#else
+ int rmask = 0x000000ff;
+ int gmask = 0x0000ff00;
+ int bmask = 0x00ff0000;
+ int amask = 0xff000000;
+#endif
+
+ SDL_Surface *surface = SDL_CreateRGBSurface(SDL_HWSURFACE,
+ BUFFER_WIDTH, BUFFER_HEIGHT,
+ 32, rmask, gmask, bmask, amask);
+
+ if (!surface)
+ return;
+
+ Graphics *graphics = new Graphics();
+ graphics->setBlitMode(Graphics::BLIT_GFX);
+ graphics->setTarget(surface);
+ graphics->_beginDraw();
+
+ int tileX = 32 / 2;
+ int tileY = 32;
+
+ Game *game = Game::instance();
+ if (game)
+ {
+ Map *map = game->getCurrentMap();
+ tileX = map->getTileWidth() / 2;
+ tileY = map->getTileWidth();
+ }
+
+ int posX = BUFFER_WIDTH / 2 - tileX;
+ int posY = BUFFER_HEIGHT - tileY;
+
+ mOffsetX = tileX - BUFFER_WIDTH / 2;
+ mOffsetY = tileY - BUFFER_HEIGHT;
+
+ SpriteConstIterator it, it_end;
+ for (it = begin(), it_end = end(); it != it_end; it++)
+ {
+ if (*it)
+ {
+ (*it)->draw(graphics, posX, posY);
+ }
+ }
+
+ delete graphics;
+
+ SDL_Surface *surfaceA = SDL_CreateRGBSurface(SDL_HWSURFACE,
+ BUFFER_WIDTH, BUFFER_HEIGHT,
+ 32, rmask, gmask, bmask, amask);
+
+ SDL_SetAlpha(surface, 0, SDL_ALPHA_OPAQUE);
+ SDL_BlitSurface(surface, NULL, surfaceA, NULL);
+
+ delete mImage;
+ delete mAlphaImage;
+
+ mImage = Image::load(surface);
+ SDL_FreeSurface(surface);
+
+ mAlphaImage = Image::load(surfaceA);
+ SDL_FreeSurface(surfaceA);
+
+ mNeedsRedraw = false;
+}
diff --git a/src/compoundsprite.h b/src/compoundsprite.h
new file mode 100644
index 00000000..3b443219
--- /dev/null
+++ b/src/compoundsprite.h
@@ -0,0 +1,105 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef COMPOUNDSPRITE_H
+#define COMPOUNDSPRITE_H
+
+#include "sprite.h"
+
+#include <vector>
+
+class Image;
+
+class CompoundSprite : public Sprite, private std::vector<Sprite*>
+{
+public:
+ CompoundSprite();
+
+ ~CompoundSprite();
+
+ virtual bool reset();
+
+ virtual bool play(std::string action);
+
+ virtual bool update(int time);
+
+ virtual bool draw(Graphics* graphics, int posX, int posY) const;
+
+ /**
+ * Gets the width in pixels of the first sprite in the list.
+ */
+ virtual int getWidth() const;
+
+ /**
+ * Gets the height in pixels of the first sprite in the list.
+ */
+ virtual int getHeight() const;
+
+ virtual const Image* getImage() const;
+
+ virtual bool setDirection(SpriteDirection direction);
+
+ int getNumberOfLayers() const;
+
+ size_t getCurrentFrame() const;
+
+ size_t getFrameCount() const;
+
+ size_t size() const
+ { return std::vector<Sprite*>::size(); }
+
+ void addSprite(Sprite* sprite);
+
+ void setSprite(int layer, Sprite* sprite);
+
+ Sprite *getSprite(int layer) const
+ { return at(layer); }
+
+ void removeSprite(int layer);
+
+ void clear();
+
+ void ensureSize(size_t layerCount);
+
+ /**
+ * Returns the curent frame in the current animation of the given layer.
+ */
+ virtual size_t getCurrentFrame(size_t layer);
+
+ /**
+ * Returns the frame count in the current animation of the given layer.
+ */
+ virtual size_t getFrameCount(size_t layer);
+
+private:
+ typedef CompoundSprite::iterator SpriteIterator;
+ typedef CompoundSprite::const_iterator SpriteConstIterator;
+
+ void redraw() const;
+
+ mutable Image *mImage;
+ mutable Image *mAlphaImage;
+
+ mutable int mOffsetX, mOffsetY;
+
+ mutable bool mNeedsRedraw;
+};
+
+#endif // COMPOUNDSPRITE_H
diff --git a/src/configuration.cpp b/src/configuration.cpp
index d8b11034..a6f691d8 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -98,6 +98,126 @@ ConfigurationObject::~ConfigurationObject()
clear();
}
+void Configuration::cleanDefaults()
+{
+ if (mDefaultsData)
+ {
+ for (DefaultsData::const_iterator iter = mDefaultsData->begin();
+ iter != mDefaultsData->end(); iter++)
+ {
+ if (iter->second)
+ delete(iter->second);
+ }
+ mDefaultsData->clear();
+ delete mDefaultsData;
+ mDefaultsData = 0;
+ }
+}
+
+Configuration::~Configuration()
+{
+ cleanDefaults();
+}
+
+void Configuration::setDefaultValues(DefaultsData *defaultsData)
+{
+ cleanDefaults();
+ mDefaultsData = defaultsData;
+}
+
+int Configuration::getIntValue(const std::string &key) const
+{
+ int defaultValue = 0;
+ if (mDefaultsData)
+ {
+ DefaultsData::const_iterator itdef = mDefaultsData->find(key);
+
+ if (itdef != mDefaultsData->end() && itdef->second
+ && itdef->second->getType() == Mana::VariableData::DATA_INT)
+ {
+ defaultValue = ((Mana::IntData*)itdef->second)->getData();
+ }
+ else
+ {
+ logger->log("%s: No integer value in registry for key %s",
+ mConfigPath.c_str(), key.c_str());
+ }
+ }
+ Options::const_iterator iter = mOptions.find(key);
+ return (iter != mOptions.end()) ? atoi(iter->second.c_str()) : defaultValue;
+}
+
+std::string Configuration::getStringValue(const std::string &key) const
+{
+ std::string defaultValue = "";
+ if (mDefaultsData)
+ {
+ DefaultsData::const_iterator itdef = mDefaultsData->find(key);
+
+ if (itdef != mDefaultsData->end() && itdef->second
+ && itdef->second->getType() == Mana::VariableData::DATA_STRING)
+ {
+ defaultValue = ((Mana::StringData*)itdef->second)->getData();
+ }
+ else
+ {
+ logger->log("%s: No string value in registry for key %s",
+ mConfigPath.c_str(), key.c_str());
+ }
+ }
+ Options::const_iterator iter = mOptions.find(key);
+ return (iter != mOptions.end()) ? iter->second : defaultValue;
+}
+
+
+float Configuration::getFloatValue(const std::string &key) const
+{
+ float defaultValue = 0.0f;
+ if (mDefaultsData)
+ {
+ DefaultsData::const_iterator itdef = mDefaultsData->find(key);
+
+ if (itdef != mDefaultsData->end() && itdef->second
+ && itdef->second->getType() == Mana::VariableData::DATA_FLOAT)
+ {
+ defaultValue = ((Mana::FloatData*)itdef->second)->getData();
+ }
+ else
+ {
+ logger->log("%s: No float value in registry for key %s",
+ mConfigPath.c_str(), key.c_str());
+ }
+ }
+ Options::const_iterator iter = mOptions.find(key);
+ return (iter != mOptions.end()) ? atof(iter->second.c_str()) : defaultValue;
+}
+
+bool Configuration::getBoolValue(const std::string &key) const
+{
+ bool defaultValue = false;
+ if (mDefaultsData)
+ {
+ DefaultsData::const_iterator itdef = mDefaultsData->find(key);
+
+ if (itdef != mDefaultsData->end() && itdef->second
+ && itdef->second->getType() == Mana::VariableData::DATA_BOOL)
+ {
+ defaultValue = ((Mana::BoolData*)itdef->second)->getData();
+ }
+ else
+ {
+ logger->log("%s: No boolean value in registry for key %s",
+ mConfigPath.c_str(), key.c_str());
+ }
+ }
+
+ Options::const_iterator iter = mOptions.find(key);
+ if (iter != mOptions.end())
+ return getBoolFromString(iter->second);
+ else
+ return defaultValue;
+}
+
void ConfigurationObject::initFromXML(xmlNodePtr parent_node)
{
clear();
diff --git a/src/configuration.h b/src/configuration.h
index 908d13a4..761cc43b 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -23,6 +23,7 @@
#define CONFIGURATION_H
#include "utils/stringutils.h"
+#include "defaults.h"
#include <libxml/xmlwriter.h>
@@ -192,7 +193,7 @@ class ConfigurationObject
class Configuration : public ConfigurationObject
{
public:
- virtual ~Configuration() {}
+ ~Configuration();
/**
* Reads config file and parse all options into memory.
@@ -203,6 +204,13 @@ class Configuration : public ConfigurationObject
void init(const std::string &filename, bool useResManager = false);
/**
+ * Set the default values for each keys.
+ *
+ * @param defaultsData data used as defaults.
+ */
+ void setDefaultValues(DefaultsData *defaultsData);
+
+ /**
* Writes the current settings back to the config file.
*/
void write();
@@ -238,14 +246,30 @@ class Configuration : public ConfigurationObject
inline void setValue(const std::string &key, bool value)
{ setValue(key, value ? "1" : "0"); }
+ /**
+ * returns a value corresponding to the given key.
+ * The default value returned in based on fallbacks registry.
+ * @see defaults.h
+ */
+ int getIntValue(const std::string &key) const;
+ float getFloatValue(const std::string &key) const;
+ std::string getStringValue(const std::string &key) const;
+ bool getBoolValue(const std::string &key) const;
+
private:
+ /**
+ * Clean up the default values member.
+ */
+ void cleanDefaults();
+
typedef std::list<ConfigListener*> Listeners;
typedef Listeners::iterator ListenerIterator;
typedef std::map<std::string, Listeners> ListenerMap;
typedef ListenerMap::iterator ListenerMapIterator;
ListenerMap mListenerMap;
- std::string mConfigPath; /**< Location of config file */
+ std::string mConfigPath; /**< Location of config file */
+ DefaultsData *mDefaultsData; /**< Defaults of value for a given key */
};
extern Configuration branding;
diff --git a/src/defaults.cpp b/src/defaults.cpp
new file mode 100644
index 00000000..c08fb357
--- /dev/null
+++ b/src/defaults.cpp
@@ -0,0 +1,182 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "defaults.h"
+
+#include "utils/stringutils.h"
+
+#include "being.h"
+#include "graphics.h"
+#include "client.h"
+
+#include <stdlib.h>
+
+using namespace Mana;
+
+VariableData* createData(int defData)
+{
+ return new IntData(defData);
+}
+
+VariableData* createData(double defData)
+{
+ return new FloatData(defData);
+}
+
+VariableData* createData(float defData)
+{
+ return new FloatData(defData);
+}
+
+VariableData* createData(const std::string &defData)
+{
+ return new StringData(defData);
+}
+
+VariableData* createData(const char* defData)
+{
+ return new StringData(defData);
+}
+
+VariableData* createData(bool defData)
+{
+ return new BoolData(defData);
+}
+
+#define AddDEF(defaultsData, key, value) \
+ defaultsData->insert(std::pair<std::string, VariableData*> \
+ (key, createData(value)));
+
+
+DefaultsData* getConfigDefaults()
+{
+ DefaultsData* configData = new DefaultsData;
+ // Init main config defaults
+ AddDEF(configData, "OverlayDetail", 2);
+ AddDEF(configData, "speechBubblecolor", "000000");
+ AddDEF(configData, "speechBubbleAlpha", 1.0f);
+ AddDEF(configData, "MostUsedServerName0", "server.themanaworld.org");
+ AddDEF(configData, "visiblenames", true);
+ AddDEF(configData, "speech", Being::TEXT_OVERHEAD);
+ AddDEF(configData, "showgender", false);
+ AddDEF(configData, "showMonstersTakedDamage", false);
+ AddDEF(configData, "particleMaxCount", 3000);
+ AddDEF(configData, "particleFastPhysics", 0);
+ AddDEF(configData, "particleEmitterSkip", 1);
+ AddDEF(configData, "particleeffects", true);
+ AddDEF(configData, "logToStandardOut", false);
+ AddDEF(configData, "opengl", false);
+ AddDEF(configData, "screenwidth", defaultScreenWidth);
+ AddDEF(configData, "screenheight", defaultScreenHeight);
+ AddDEF(configData, "screen", false);
+ AddDEF(configData, "hwaccel", false);
+ AddDEF(configData, "sound", false);
+ AddDEF(configData, "sfxVolume", 100);
+ AddDEF(configData, "musicVolume", 60);
+ AddDEF(configData, "remember", false);
+ AddDEF(configData, "username", "");
+ AddDEF(configData, "lastCharacter", "");
+ AddDEF(configData, "fpslimit", 60);
+ AddDEF(configData, "updatehost", "");
+ AddDEF(configData, "screenshotDirectory", "");
+ AddDEF(configData, "useScreenshotDirectorySuffix", true);
+ AddDEF(configData, "screenshotDirectorySuffix", "");
+ AddDEF(configData, "EnableSync", false);
+ AddDEF(configData, "joystickEnabled", false);
+ AddDEF(configData, "upTolerance", 100);
+ AddDEF(configData, "downTolerance", 100);
+ AddDEF(configData, "leftTolerance", 100);
+ AddDEF(configData, "rightTolerance", 100);
+ AddDEF(configData, "logNpcInGui", true);
+ AddDEF(configData, "download-music", false);
+ AddDEF(configData, "guialpha", 0.8f);
+ AddDEF(configData, "ChatLogLength", 0);
+ AddDEF(configData, "enableChatLog", false);
+ AddDEF(configData, "whispertab", false);
+ AddDEF(configData, "customcursor", true);
+ AddDEF(configData, "showownname", false);
+ AddDEF(configData, "showpickupparticle", false);
+ AddDEF(configData, "showpickupchat", true);
+ AddDEF(configData, "fontSize", 11);
+ AddDEF(configData, "ReturnToggles", false);
+ AddDEF(configData, "ScrollLaziness", 16);
+ AddDEF(configData, "ScrollRadius", 0);
+ AddDEF(configData, "ScrollCenterOffsetX", 0);
+ AddDEF(configData, "ScrollCenterOffsetY", 0);
+ AddDEF(configData, "onlineServerList", "");
+ AddDEF(configData, "theme", "");
+
+ return configData;
+}
+
+DefaultsData* getBrandingDefaults()
+{
+ DefaultsData* brandingData = new DefaultsData;
+ // Init config defaults
+ AddDEF(brandingData, "wallpapersPath", "");
+ AddDEF(brandingData, "wallpapersFile", "");
+ AddDEF(brandingData, "appName", "Mana");
+ AddDEF(brandingData, "appIcon", "icons/mana.png");
+ AddDEF(brandingData, "loginMusic", "Magick - Real.ogg");
+ AddDEF(brandingData, "defaultServer", "");
+ AddDEF(brandingData, "defaultPort", DEFAULT_PORT);
+ AddDEF(brandingData, "defaultServerType", "tmwathena");
+ AddDEF(brandingData, "onlineServerList", "a");
+ AddDEF(brandingData, "appShort", "mana");
+ AddDEF(brandingData, "defaultUpdateHost", "");
+ AddDEF(brandingData, "helpPath", "");
+ AddDEF(brandingData, "onlineServerList", "");
+ AddDEF(brandingData, "guiThemePath", "");
+ AddDEF(brandingData, "theme", "");
+ AddDEF(brandingData, "font", "fonts/dejavusans.ttf");
+ AddDEF(brandingData, "boldFont", "fonts/dejavusans-bold.ttf");
+
+ return brandingData;
+}
+
+DefaultsData* getPathsDefaults()
+{
+ DefaultsData *pathsData = new DefaultsData;
+ // Init paths.xml defaults
+ AddDEF(pathsData, "itemIcons", "graphics/items/");
+ AddDEF(pathsData, "unknownItemFile", "unknown-item.png");
+ AddDEF(pathsData, "sprites", "graphics/sprites/");
+ AddDEF(pathsData, "spriteErrorFile", "error.xml");
+
+ AddDEF(pathsData, "particles", "graphics/particles/");
+ AddDEF(pathsData, "levelUpEffectFile", "levelup.particle.xml");
+ AddDEF(pathsData, "portalEffectFile", "warparea.particle.xml");
+
+ AddDEF(pathsData, "minimaps", "graphics/minimaps/");
+ AddDEF(pathsData, "maps", "maps/");
+
+ AddDEF(pathsData, "sfx", "sfx/");
+ AddDEF(pathsData, "attackSfxFile", "fist-swish.ogg");
+ AddDEF(pathsData, "music", "music/");
+
+ AddDEF(pathsData, "wallpapers", "graphics/images/");
+ AddDEF(pathsData, "wallpaperFile", "login_wallpaper.png");
+
+ AddDEF(pathsData, "help", "help/");
+
+ return pathsData;
+}
+
+#undef AddDEF
diff --git a/src/defaults.h b/src/defaults.h
new file mode 100644
index 00000000..b9dfa511
--- /dev/null
+++ b/src/defaults.h
@@ -0,0 +1,34 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DEFAULTS_H
+#define DEFAULTS_H
+
+#include <map>
+#include <string>
+#include "variabledata.h"
+
+typedef std::map<std::string, Mana::VariableData*> DefaultsData;
+
+DefaultsData* getConfigDefaults();
+DefaultsData* getBrandingDefaults();
+DefaultsData* getPathsDefaults();
+
+#endif
diff --git a/src/event.cpp b/src/event.cpp
new file mode 100644
index 00000000..38213cd2
--- /dev/null
+++ b/src/event.cpp
@@ -0,0 +1,187 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "event.h"
+
+#include "listener.h"
+#include "variabledata.h"
+
+namespace Mana
+{
+
+ListenMap Event::mBindings;
+
+Event::~Event()
+{
+ VariableMap::iterator it = mData.begin();
+ while (it != mData.end())
+ {
+ delete it->second;
+ it++;
+ }
+}
+
+void Event::setInt(const std::string &key, int value) throw (BadEvent)
+{
+ if (mData.find(key) != mData.end())
+ throw KEY_ALREADY_EXISTS;
+
+ mData[key] = new IntData(value);
+}
+
+int Event::getInt(const std::string &key) const throw (BadEvent)
+{
+ VariableMap::const_iterator it = mData.find(key);
+ if (it == mData.end())
+ throw BAD_KEY;
+
+ if (it->second->getType() != VariableData::DATA_INT)
+ throw BAD_VALUE;
+
+ return static_cast<IntData *>(it->second)->getData();
+}
+
+bool Event::hasInt(const std::string &key) const
+{
+ VariableMap::const_iterator it = mData.find(key);
+ return !(it == mData.end()
+ || it->second->getType() != VariableData::DATA_INT);
+}
+
+void Event::setString(const std::string &key, const std::string &value) throw (BadEvent)
+{
+ if (mData.find(key) != mData.end())
+ throw KEY_ALREADY_EXISTS;
+
+ mData[key] = new StringData(value);
+}
+
+const std::string &Event::getString(const std::string &key) const throw (BadEvent)
+{
+ VariableMap::const_iterator it = mData.find(key);
+ if (it == mData.end())
+ throw BAD_KEY;
+
+ if (it->second->getType() != VariableData::DATA_STRING)
+ throw BAD_VALUE;
+
+ return static_cast<StringData *>(it->second)->getData();
+}
+
+
+bool Event::hasString(const std::string &key) const
+{
+ VariableMap::const_iterator it = mData.find(key);
+ return !(it == mData.end()
+ || it->second->getType() != VariableData::DATA_STRING);
+}
+
+void Event::setFloat(const std::string &key, double value) throw (BadEvent)
+{
+ if (mData.find(key) != mData.end())
+ throw KEY_ALREADY_EXISTS;
+
+ mData[key] = new FloatData(value);
+}
+
+double Event::getFloat(const std::string &key) const throw (BadEvent)
+{
+ VariableMap::const_iterator it = mData.find(key);
+ if (it == mData.end())
+ throw BAD_KEY;
+
+ if (it->second->getType() != VariableData::DATA_FLOAT)
+ throw BAD_VALUE;
+
+ return static_cast<FloatData *>(it->second)->getData();
+}
+
+bool Event::hasFloat(const std::string &key) const
+{
+ VariableMap::const_iterator it = mData.find(key);
+ return !(it == mData.end()
+ || it->second->getType() != VariableData::DATA_FLOAT);
+}
+
+void Event::setBool(const std::string &key, bool value) throw (BadEvent)
+{
+ if (mData.find(key) != mData.end())
+ throw KEY_ALREADY_EXISTS;
+
+ mData[key] = new BoolData(value);
+}
+
+bool Event::getBool(const std::string &key) const throw (BadEvent)
+{
+ VariableMap::const_iterator it = mData.find(key);
+ if (it == mData.end())
+ throw BAD_KEY;
+
+ if (it->second->getType() != VariableData::DATA_BOOL)
+ throw BAD_VALUE;
+
+ return static_cast<BoolData *>(it->second)->getData();
+}
+
+bool Event::hasBool(const std::string &key) const
+{
+ VariableMap::const_iterator it = mData.find(key);
+ return !(it == mData.end()
+ || it->second->getType() != VariableData::DATA_BOOL);
+}
+
+void Event::trigger(const std::string &channel, const Event &event)
+{
+ ListenMap::iterator it = mBindings.find(channel);
+
+ // Make sure something is listening
+ if (it == mBindings.end())
+ return;
+
+ // Loop though all listeners
+ ListenerSet::iterator lit = it->second.begin();
+ while (lit != it->second.end())
+ {
+ (*lit)->event(channel, event);
+ lit++;
+ }
+}
+
+void Event::bind(Listener *listener, const std::string &channel)
+{
+ mBindings[channel].insert(listener);
+}
+
+void Event::unbind(Listener *listener, const std::string &channel)
+{
+ mBindings[channel].erase(listener);
+}
+
+void Event::remove(Listener *listener)
+{
+ ListenMap::iterator it = mBindings.begin();
+ while (it != mBindings.end())
+ {
+ it->second.erase(listener);
+ it++;
+ }
+}
+
+} // namespace Mana
diff --git a/src/event.h b/src/event.h
new file mode 100644
index 00000000..68560dae
--- /dev/null
+++ b/src/event.h
@@ -0,0 +1,207 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EVENT_H
+#define EVENT_H
+
+#include <string>
+#include <map>
+#include <set>
+
+namespace Mana
+{
+
+// Possible exception that can be thrown
+enum BadEvent {
+ BAD_KEY,
+ BAD_VALUE,
+ KEY_ALREADY_EXISTS
+};
+
+class Listener;
+
+typedef std::set<Listener *> ListenerSet;
+typedef std::map<std::string, ListenerSet > ListenMap;
+
+class VariableData;
+typedef std::map<std::string, VariableData *> VariableMap;
+
+#define SERVER_NOTICE(message) { \
+Mana::Event event("ServerNotice"); \
+event.setString("message", message); \
+event.trigger("Notices", event); }
+
+class Event
+{
+public:
+ /**
+ * Makes an event with the given name.
+ */
+ Event(const std::string &name)
+ { mEventName = name; }
+
+ ~Event();
+
+ /**
+ * Returns the name of the event.
+ */
+ const std::string &getName() const
+ { return mEventName; }
+
+ /**
+ * Sets the given variable to the given integer, if it isn't already set.
+ */
+ void setInt(const std::string &key, int value) throw (BadEvent);
+
+ /**
+ * Returns the given variable if it is set and an integer.
+ */
+ int getInt(const std::string &key) const throw (BadEvent);
+
+ /**
+ * Returns the given variable if it is set and an integer, returning the
+ * given default otherwise.
+ */
+ inline int getInt(const std::string &key, int defaultValue) const
+ { try { return getInt(key); } catch (BadEvent) { return defaultValue; }}
+
+ /**
+ * Returns true if the given variable exists and is an integer.
+ */
+ bool hasInt(const std::string &key) const;
+
+ /**
+ * Sets the given variable to the given string, if it isn't already set.
+ */
+ void setString(const std::string &key, const std::string &value) throw (BadEvent);
+
+ /**
+ * Returns the given variable if it is set and a string.
+ */
+ const std::string &getString(const std::string &key) const throw (BadEvent);
+
+ /**
+ * Returns the given variable if it is set and a string, returning the
+ * given default otherwise.
+ */
+ inline std::string getString(const std::string &key,
+ const std::string &defaultValue) const
+ { try { return getString(key); } catch (BadEvent) { return defaultValue; }}
+
+ /**
+ * Returns true if the given variable exists and is a string.
+ */
+ bool hasString(const std::string &key) const;
+
+ /**
+ * Sets the given variable to the given floating-point, if it isn't already
+ * set.
+ */
+ void setFloat(const std::string &key, double value) throw (BadEvent);
+
+ /**
+ * Returns the given variable if it is set and a floating-point.
+ */
+ double getFloat(const std::string &key) const throw (BadEvent);
+
+ /**
+ * Returns the given variable if it is set and a floating-point, returning
+ * the given default otherwise.
+ */
+ inline double getFloat(const std::string &key, float defaultValue) const
+ { try { return getFloat(key); } catch (BadEvent) { return defaultValue; }}
+
+ /**
+ * Returns true if the given variable exists and is a floating-point.
+ */
+ bool hasFloat(const std::string &key) const;
+
+ /**
+ * Sets the given variable to the given boolean, if it isn't already set.
+ */
+ void setBool(const std::string &key, bool value) throw (BadEvent);
+
+ /**
+ * Returns the given variable if it is set and a boolean.
+ */
+ bool getBool(const std::string &key) const throw (BadEvent);
+
+ /**
+ * Returns the given variable if it is set and a boolean, returning the
+ * given default otherwise.
+ */
+ inline bool getBool(const std::string &key, bool defaultValue) const
+ { try { return getBool(key); } catch (BadEvent) { return defaultValue; }}
+
+ /**
+ * Returns true if the given variable exists and is a boolean.
+ */
+ bool hasBool(const std::string &key) const;
+
+ /**
+ * Sends this event to all classes listening to the given channel.
+ */
+ inline void trigger(const std::string &channel) const
+ { trigger(channel, *this); }
+
+ /**
+ * Sends the given event to all classes listening to the given channel.
+ */
+ static void trigger(const std::string &channel, const Event &event);
+
+ /**
+ * Sends an empty event with the given name to all classes listening to the
+ * given channel.
+ */
+ static inline void trigger(const std::string& channel,
+ const std::string& name)
+ { trigger(channel, Mana::Event(name)); }
+
+protected:
+ friend class Listener;
+
+ /**
+ * Binds the given listener to the given channel. The listener will receive
+ * all events triggered on the channel.
+ */
+ static void bind(Listener *listener, const std::string &channel);
+
+ /**
+ * Unbinds the given listener from the given channel. The listener will no
+ * longer receive any events from the channel.
+ */
+ static void unbind(Listener *listener, const std::string &channel);
+
+ /**
+ * Unbinds the given listener from all channels.
+ */
+ static void remove(Listener *listener);
+
+private:
+ static ListenMap mBindings;
+
+ std::string mEventName;
+
+ VariableMap mData;
+};
+
+} // namespace Mana
+
+#endif
diff --git a/src/flooritem.cpp b/src/flooritem.cpp
index c3442a86..84e07f35 100644
--- a/src/flooritem.cpp
+++ b/src/flooritem.cpp
@@ -21,59 +21,34 @@
#include "flooritem.h"
-#include "graphics.h"
-#include "item.h"
-#include "map.h"
+#include "net/net.h"
-#include "resources/image.h"
+#include "resources/itemdb.h"
+#include "resources/iteminfo.h"
FloorItem::FloorItem(int id,
int itemId,
int x,
int y,
Map *map):
- mId(id),
+ ActorSprite(id),
+ mItemId(itemId),
mX(x),
- mY(y),
- mMap(map),
- mAlpha(1.0f)
+ mY(y)
{
- // Create a corresponding item instance
- mItem = new Item(itemId);
+ setMap(map);
- // Add ourselves to the map
- mMapSprite = mMap->addSprite(this);
-}
-
-FloorItem::~FloorItem()
-{
- // Remove ourselves from the map
- mMap->removeSprite(mMapSprite);
+ // TODO: Eventually, we probably should fix all sprite offsets so that
+ // these translations aren't necessary anymore. The sprites know
+ // best where their base point should be.
+ mPos.x = x * map->getTileWidth() + 16;
+ mPos.y = y * map->getTileHeight() +
+ ((Net::getNetworkType() == ServerInfo::MANASERV) ? 15 : 32);
- delete mItem;
-}
-
-int FloorItem::getItemId() const
-{
- return mItem->getId();
+ setupSpriteDisplay(ItemDB::get(itemId).getDisplay());
}
-Item *FloorItem::getItem() const
+const ItemInfo &FloorItem::getInfo() const
{
- return mItem;
-}
-
-void FloorItem::draw(Graphics *graphics, int offsetX, int offsetY) const
-{
- if (mItem)
- {
- Image *image = mItem->getDrawImage();
-
- if (image)
- if (mAlpha != image->getAlpha())
- image->setAlpha(mAlpha);
-
- graphics->drawImage(image, mX * mMap->getTileWidth() + offsetX,
- mY * mMap->getTileHeight() + offsetY);
- }
+ return ItemDB::get(mId);
}
diff --git a/src/flooritem.h b/src/flooritem.h
index ec8c37cd..e599c939 100644
--- a/src/flooritem.h
+++ b/src/flooritem.h
@@ -22,19 +22,14 @@
#ifndef FLOORITEM_H
#define FLOORITEM_H
-#include "map.h"
-#include "sprite.h"
+#include "actorsprite.h"
-#include <list>
-
-class Graphics;
-class Image;
-class Item;
+class ItemInfo;
/**
* An item lying on the floor.
*/
-class FloorItem : public Sprite
+class FloorItem : public ActorSprite
{
public:
/**
@@ -52,72 +47,29 @@ class FloorItem : public Sprite
int y,
Map *map);
- ~FloorItem();
-
- /**
- * Returns instance ID of this item.
- */
- int getId() const { return mId; }
+ Type getType() const { return FLOOR_ITEM; }
/**
* Returns the item ID.
*/
- int getItemId() const;
-
- /**
- * Returns the item object. Useful for adding an item link for the
- * floor item to chat.
- */
- Item *getItem() const;
-
- /**
- * Returns the x coordinate in tiles.
- */
- int getX() const { return mX; }
+ int getItemId() const
+ { return mItemId; }
/**
- * Returns the y coordinate in tiles.
+ * Returns the item info for this floor item. Useful for adding an item
+ * link for the floor item to chat.
*/
- int getY() const { return mY; }
+ const ItemInfo &getInfo() const;
- /**
- * Returns the pixel y coordinate.
- *
- * @see Sprite::getPixelY()
- */
- int getPixelY() const
- { return mY * mMap->getTileHeight() + mMap->getTileHeight() / 2; }
-
- /**
- * Draws this floor item to the given graphics context.
- *
- * @see Sprite::draw(Graphics, int, int)
- */
- void draw(Graphics *graphics, int offsetX, int offsetY) const;
-
- /**
- * Sets the alpha value of the floor item
- */
- void setAlpha(float alpha)
- { mAlpha = alpha; }
-
- /**
- * Returns the current alpha opacity of the floor item.
- */
- virtual float getAlpha() const
- { return mAlpha; }
+ virtual int getTileX() const
+ { return mX; }
- /** We consider flooritems (at least for now) to be one layer-sprites */
- virtual int getNumberOfLayers() const
- { return 1; }
+ virtual int getTileY() const
+ { return mY; }
private:
- int mId;
+ int mItemId;
int mX, mY;
- Item *mItem;
- MapSprite mMapSprite;
- Map *mMap;
- float mAlpha;
};
#endif
diff --git a/src/flooritemmanager.cpp b/src/flooritemmanager.cpp
deleted file mode 100644
index a190a168..00000000
--- a/src/flooritemmanager.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "flooritemmanager.h"
-#include "flooritem.h"
-
-#include "game.h"
-
-#include "utils/dtor.h"
-
-FloorItemManager::~FloorItemManager()
-{
- clear();
-}
-
-FloorItem *FloorItemManager::create(int id, int itemId, int x, int y)
-{
- Map *map = Game::instance()->getCurrentMap();
- FloorItem *floorItem = new FloorItem(id, itemId, x, y, map);
- mFloorItems.push_back(floorItem);
- return floorItem;
-}
-
-void FloorItemManager::destroy(FloorItem *item)
-{
- mFloorItems.remove(item);
- delete item;
-}
-
-void FloorItemManager::clear()
-{
- delete_all(mFloorItems);
- mFloorItems.clear();
-}
-
-FloorItem *FloorItemManager::findById(int id) const
-{
- FloorItems::const_iterator i;
- for (i = mFloorItems.begin(); i != mFloorItems.end(); i++)
- {
- if ((*i)->getId() == id)
- {
- return *i;
- }
- }
-
- return NULL;
-}
-
-FloorItem *FloorItemManager::findByCoordinates(int x, int y) const
-{
- FloorItems::const_iterator i;
- for (i = mFloorItems.begin(); i != mFloorItems.end(); i++)
- {
- if ((*i)->getX() == x && (*i)->getY() == y)
- {
- return *i;
- }
- }
-
- return NULL;
-}
diff --git a/src/game.cpp b/src/game.cpp
index ec5e6b13..18bad69c 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -21,14 +21,15 @@
#include "game.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
+#include "actorsprite.h"
#include "channelmanager.h"
#include "client.h"
#include "commandhandler.h"
#include "configuration.h"
#include "effectmanager.h"
+#include "event.h"
#include "emoteshortcut.h"
-#include "flooritemmanager.h"
#include "graphics.h"
#include "itemshortcut.h"
#include "joystick.h"
@@ -36,7 +37,6 @@
#include "localplayer.h"
#include "log.h"
#include "map.h"
-#include "npc.h"
#include "particle.h"
#include "playerrelations.h"
#include "sound.h"
@@ -115,8 +115,7 @@ OutfitWindow *outfitWindow;
SpecialsWindow *specialsWindow;
SocialWindow *socialWindow;
-BeingManager *beingManager = NULL;
-FloorItemManager *floorItemManager = NULL;
+ActorSpriteManager *actorSpriteManager = NULL;
ChannelManager *channelManager = NULL;
CommandHandler *commandHandler = NULL;
Particle *particleEngine = NULL;
@@ -130,14 +129,17 @@ ChatTab *localChatTab = NULL;
*/
static void initEngines()
{
- beingManager = new BeingManager;
+ Mana::Event::trigger("Game", "EnginesInitalizing");
+
+ actorSpriteManager = new ActorSpriteManager;
commandHandler = new CommandHandler;
- floorItemManager = new FloorItemManager;
channelManager = new ChannelManager;
effectManager = new EffectManager;
particleEngine = new Particle(NULL);
particleEngine->setupEngine();
+
+ Mana::Event::trigger("Game", "EnginesInitalized");
}
/**
@@ -145,15 +147,17 @@ static void initEngines()
*/
static void createGuiWindows()
{
+ Mana::Event::trigger("Game", "GuiWindowsLoading");
+
setupWindow->clearWindowsForReset();
// Create dialogs
chatWindow = new ChatWindow;
tradeWindow = new TradeWindow;
- equipmentWindow = new EquipmentWindow(player_node->mEquipment.get());
+ equipmentWindow = new EquipmentWindow(PlayerInfo::getEquipment());
statusWindow = new StatusWindow;
miniStatusWindow = new MiniStatusWindow;
- inventoryWindow = new InventoryWindow(player_node->getInventory());
+ inventoryWindow = new InventoryWindow(PlayerInfo::getInventory());
skillDialog = new SkillDialog;
minimap = new Minimap;
helpWindow = new HelpWindow;
@@ -173,7 +177,9 @@ static void createGuiWindows()
logger->setChatWindow(chatWindow);
}
- Net::getGeneralHandler()->guiWindowsLoaded();
+ NpcDialog::setup();
+
+ Mana::Event::trigger("Game", "GuiWindowsLoaded");
}
#define del_0(X) { delete X; X = 0; }
@@ -183,7 +189,8 @@ static void createGuiWindows()
*/
static void destroyGuiWindows()
{
- Net::getGeneralHandler()->guiWindowsUnloaded();
+ Mana::Event::trigger("Game", "GuiWindowsUnloading");
+
logger->setChatWindow(NULL);
del_0(localChatTab) // Need to do this first, so it can remove itself
del_0(chatWindow)
@@ -201,12 +208,14 @@ static void destroyGuiWindows()
del_0(outfitWindow)
del_0(specialsWindow)
del_0(socialWindow)
+
+ Mana::Event::trigger("Game", "GuiWindowsUnloaded");
}
Game *Game::mInstance = 0;
Game::Game():
- mLastTarget(Being::UNKNOWN),
+ mLastTarget(ActorSprite::UNKNOWN),
mCurrentMap(0), mMapName("")
{
assert(!mInstance);
@@ -230,10 +239,8 @@ Game::Game():
initEngines();
- Net::getGameHandler()->inGame();
-
// Initialize beings
- beingManager->setPlayer(player_node);
+ actorSpriteManager->setPlayer(player_node);
/*
* To prevent the server from sending data before the client
@@ -253,6 +260,8 @@ Game::Game():
joystick = new Joystick(0);
setupWindow->setInGame(true);
+
+ Mana::Event::trigger("Game", "Constructed");
}
Game::~Game()
@@ -261,10 +270,9 @@ Game::~Game()
destroyGuiWindows();
- del_0(beingManager)
+ del_0(actorSpriteManager)
if (Client::getState() != STATE_CHANGE_MAP)
del_0(player_node)
- del_0(floorItemManager)
del_0(channelManager)
del_0(commandHandler)
del_0(joystick)
@@ -273,6 +281,8 @@ Game::~Game()
del_0(mCurrentMap)
mInstance = 0;
+
+ Mana::Event::trigger("Game", "Destructed");
}
static bool saveScreenshot()
@@ -316,11 +326,11 @@ static bool saveScreenshot()
std::stringstream chatlogentry;
// TODO: Make it one complete gettext string below
chatlogentry << _("Screenshot saved as ") << filenameSuffix.str();
- localChatTab->chatLog(chatlogentry.str(), BY_SERVER);
+ SERVER_NOTICE(chatlogentry.str())
}
else
{
- localChatTab->chatLog(_("Saving screenshot failed!"), BY_SERVER);
+ SERVER_NOTICE(_("Saving screenshot failed!"))
logger->log("Error: could not save screenshot.");
}
@@ -334,7 +344,8 @@ void Game::logic()
handleInput();
// Handle all necessary game logic
- beingManager->logic();
+ ActorSprite::actorLogic();
+ actorSpriteManager->logic();
particleEngine->update();
if (mCurrentMap)
mCurrentMap->update();
@@ -392,7 +403,7 @@ void Game::handleInput()
// send straight to gui for certain windows
if (quitDialog || TextDialog::isActive() ||
- NpcPostDialog::isActive())
+ PlayerInfo::getNPCPostCount() > 0)
{
try
{
@@ -449,7 +460,8 @@ void Game::handleInput()
}
- if (!chatWindow->isInputFocused() || (event.key.keysym.mod & KMOD_ALT))
+ if (!chatWindow->isInputFocused() || (event.key.keysym.mod &
+ KMOD_ALT))
{
if (keyboard.isKeyActive(keyboard.KEY_PREV_CHAT_TAB))
{
@@ -601,7 +613,7 @@ void Game::handleInput()
// off under eAthena.
FloorItem *item =
- floorItemManager->findByCoordinates(x, y);
+ actorSpriteManager->findItem(x, y);
// If none below the player, try the tile in front
// of the player
@@ -618,8 +630,7 @@ void Game::handleInput()
default: break;
}
- item = floorItemManager->findByCoordinates(
- x, y);
+ item = actorSpriteManager->findItem(x, y);
}
if (item)
@@ -698,16 +709,12 @@ void Game::handleInput()
unsigned int deflt = player_relations.getDefault();
if (deflt & PlayerRelation::TRADE)
{
- localChatTab->chatLog(
- _("Ignoring incoming trade requests"),
- BY_SERVER);
+ SERVER_NOTICE(_("Ignoring incoming trade requests"))
deflt &= ~PlayerRelation::TRADE;
}
else
{
- localChatTab->chatLog(
- _("Accepting incoming trade requests"),
- BY_SERVER);
+ SERVER_NOTICE(_("Accepting incoming trade requests"))
deflt |= PlayerRelation::TRADE;
}
@@ -753,7 +760,7 @@ void Game::handleInput()
return;
// Moving player around
- if (player_node->isAlive() && !NPC::isTalking() &&
+ if (player_node->isAlive() && !PlayerInfo::isTalking() &&
!chatWindow->isInputFocused() && !quitDialog)
{
// Get the state of the keyboard keys
@@ -831,8 +838,8 @@ void Game::handleInput()
if (!player_node->getTarget())
{
// Only auto target Monsters
- target = beingManager->findNearestLivingBeing(player_node,
- 20, Being::MONSTER);
+ target = actorSpriteManager->findNearestLivingBeing(player_node,
+ 20, ActorSprite::MONSTER);
}
player_node->attack(target, newTarget);
}
@@ -844,16 +851,16 @@ void Game::handleInput()
(joystick && joystick->buttonPressed(3))) &&
!keyboard.isKeyActive(keyboard.KEY_TARGET))
{
- Being::Type currentTarget = Being::UNKNOWN;
+ ActorSprite::Type currentTarget = ActorSprite::UNKNOWN;
if (keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) ||
(joystick && joystick->buttonPressed(3)))
- currentTarget = Being::MONSTER;
+ currentTarget = ActorSprite::MONSTER;
else if (keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER))
- currentTarget = Being::PLAYER;
+ currentTarget = ActorSprite::PLAYER;
else if (keyboard.isKeyActive(keyboard.KEY_TARGET_NPC))
- currentTarget = Being::NPC;
+ currentTarget = ActorSprite::NPC;
- Being *target = beingManager->findNearestLivingBeing(player_node,
+ Being *target = actorSpriteManager->findNearestLivingBeing(player_node,
20, currentTarget);
if (target && (target != player_node->getTarget() ||
@@ -865,7 +872,7 @@ void Game::handleInput()
}
else
{
- mLastTarget = Being::UNKNOWN; // Reset last target
+ mLastTarget = ActorSprite::UNKNOWN; // Reset last target
}
// Talk to the nearest NPC if 't' pressed
@@ -876,8 +883,8 @@ void Game::handleInput()
if (target)
{
- if (target->getType() == Being::NPC)
- static_cast<NPC*>(target)->talk();
+ if (target->canTalk())
+ target->talkTo();
}
}
@@ -892,7 +899,7 @@ void Game::handleInput()
{
if (joystick->buttonPressed(1))
{
- FloorItem *item = floorItemManager->findByCoordinates(x, y);
+ FloorItem *item = actorSpriteManager->findItem(x, y);
if (item)
player_node->pickUp(item);
@@ -912,8 +919,7 @@ void Game::handleInput()
void Game::changeMap(const std::string &mapPath)
{
// Clean up floor items, beings and particles
- floorItemManager->clear();
- beingManager->clear();
+ actorSpriteManager->clear();
// Close the popup menu on map change so that invalid options can't be
// executed.
@@ -946,7 +952,7 @@ void Game::changeMap(const std::string &mapPath)
// Notify the minimap and beingManager about the map change
minimap->setMap(newMap);
- beingManager->setMap(newMap);
+ actorSpriteManager->setMap(newMap);
particleEngine->setMap(newMap);
viewport->setMap(newMap);
@@ -963,5 +969,7 @@ void Game::changeMap(const std::string &mapPath)
delete mCurrentMap;
mCurrentMap = newMap;
- Net::getGameHandler()->mapLoaded(mapPath);
+ Mana::Event event("MapLoaded");
+ event.setString("mapPath", mapPath);
+ event.trigger("Game");
}
diff --git a/src/graphics.cpp b/src/graphics.cpp
index 9815e1ad..24f92544 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -27,12 +27,15 @@
#include "resources/image.h"
#include "resources/imageloader.h"
+#include <SDL_gfxBlitFunc.h>
+
Graphics::Graphics():
mWidth(0),
mHeight(0),
mBpp(0),
mFullscreen(false),
- mHWAccel(false)
+ mHWAccel(false),
+ mBlitMode(BLIT_NORMAL)
{
}
@@ -183,7 +186,10 @@ bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY,
srcRect.w = width;
srcRect.h = height;
- return !(SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect) < 0);
+ if (mBlitMode == BLIT_NORMAL)
+ return !(SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect) < 0);
+ else
+ return !(SDL_gfxBlitRGBA(image->mSDLSurface, &srcRect, mTarget, &dstRect) < 0);
}
void Graphics::drawImage(gcn::Image const *image, int srcX, int srcY,
diff --git a/src/graphics.h b/src/graphics.h
index 211fb901..344c31c3 100644
--- a/src/graphics.h
+++ b/src/graphics.h
@@ -73,6 +73,11 @@ struct ImageRect
class Graphics : public gcn::SDLGraphics
{
public:
+ enum BlitMode {
+ BLIT_NORMAL = 0,
+ BLIT_GFX
+ };
+
/**
* Constructor.
*/
@@ -182,6 +187,12 @@ class Graphics : public gcn::SDLGraphics
drawImageRect(area.x, area.y, area.width, area.height, imgRect);
}
+ void setBlitMode(BlitMode mode)
+ { mBlitMode = mode; }
+
+ BlitMode getBlitMode()
+ { return mBlitMode; }
+
/**
* Updates the screen. This is done by either copying the buffer to the
* screen or swapping pages.
@@ -211,6 +222,7 @@ class Graphics : public gcn::SDLGraphics
int mBpp;
bool mFullscreen;
bool mHWAccel;
+ BlitMode mBlitMode;
};
extern Graphics *graphics;
diff --git a/src/gui/beingpopup.cpp b/src/gui/beingpopup.cpp
index 687b20c2..ee9fd66d 100644
--- a/src/gui/beingpopup.cpp
+++ b/src/gui/beingpopup.cpp
@@ -20,8 +20,8 @@
#include "gui/beingpopup.h"
+#include "being.h"
#include "graphics.h"
-#include "player.h"
#include "units.h"
#include "gui/gui.h"
@@ -57,21 +57,21 @@ BeingPopup::~BeingPopup()
{
}
-void BeingPopup::show(int x, int y, Player *p)
+void BeingPopup::show(int x, int y, Being *b)
{
- if (!p)
+ if (!b)
{
setVisible(false);
return;
}
- if (!(p->getPartyName().empty()))
+ if (!(b->getPartyName().empty()))
{
- mBeingName->setCaption(p->getName());
+ mBeingName->setCaption(b->getName());
mBeingName->adjustSize();
mBeingParty->setCaption(strprintf(_("Party: %s"),
- p->getPartyName().c_str()));
+ b->getPartyName().c_str()));
mBeingParty->adjustSize();
int minWidth = std::max(mBeingName->getWidth(),
diff --git a/src/gui/beingpopup.h b/src/gui/beingpopup.h
index f397e374..514a6e7e 100644
--- a/src/gui/beingpopup.h
+++ b/src/gui/beingpopup.h
@@ -23,8 +23,8 @@
#include "gui/widgets/popup.h"
+class Being;
class Label;
-class Player;
/**
* A popup that displays information about a being.
@@ -45,7 +45,7 @@ class BeingPopup : public Popup
/**
* Sets the info to be displayed given a particular player.
*/
- void show(int x, int y, Player *p);
+ void show(int x, int y, Being *b);
// TODO: Add a version for monsters, NPCs, etc?
diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp
index 031c53dd..cc135e07 100644
--- a/src/gui/buy.cpp
+++ b/src/gui/buy.cpp
@@ -21,6 +21,10 @@
#include "gui/buy.h"
+#include "playerinfo.h"
+#include "shopitem.h"
+#include "units.h"
+
#include "gui/setup.h"
#include "gui/widgets/button.h"
@@ -31,10 +35,6 @@
#include "gui/widgets/shoplistbox.h"
#include "gui/widgets/slider.h"
-#include "npc.h"
-#include "shopitem.h"
-#include "units.h"
-
#include "net/net.h"
#include "net/npchandler.h"
@@ -112,6 +112,8 @@ BuyDialog::BuyDialog(int npcId):
instances.push_back(this);
setVisible(true);
+
+ PlayerInfo::setBuySellState(BUYSELL_BUYING);
}
BuyDialog::~BuyDialog()
@@ -119,6 +121,9 @@ BuyDialog::~BuyDialog()
delete mShopItems;
instances.remove(this);
+
+ if (PlayerInfo::getBuySellState() == BUYSELL_BUYING)
+ PlayerInfo::setBuySellState(BUYSELL_NONE);
}
void BuyDialog::setMoney(int amount)
diff --git a/src/gui/buy.h b/src/gui/buy.h
index 4b273bcc..c3cb3229 100644
--- a/src/gui/buy.h
+++ b/src/gui/buy.h
@@ -100,11 +100,6 @@ class BuyDialog : public Window, public gcn::ActionListener,
void setVisible(bool visible);
/**
- * Returns true if any instances exist.
- */
- static bool isActive() { return instances.size() > 0; }
-
- /**
* Closes all instances.
*/
static void closeAll();
diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp
index c6b4ef41..4419ffcc 100644
--- a/src/gui/buysell.cpp
+++ b/src/gui/buysell.cpp
@@ -21,7 +21,7 @@
#include "buysell.h"
-#include "npc.h"
+#include "playerinfo.h"
#include "gui/setup.h"
@@ -67,11 +67,16 @@ BuySellDialog::BuySellDialog(int npcId):
instances.push_back(this);
setVisible(true);
+
+ PlayerInfo::setBuySellState(BUYSELL_CHOOSING);
}
BuySellDialog::~BuySellDialog()
{
instances.remove(this);
+
+ if (PlayerInfo::getBuySellState() == BUYSELL_CHOOSING)
+ PlayerInfo::setBuySellState(BUYSELL_NONE);
}
void BuySellDialog::setVisible(bool visible)
diff --git a/src/gui/buysell.h b/src/gui/buysell.h
index cf7ec91e..3408821a 100644
--- a/src/gui/buysell.h
+++ b/src/gui/buysell.h
@@ -52,11 +52,6 @@ class BuySellDialog : public Window, public gcn::ActionListener
void action(const gcn::ActionEvent &event);
/**
- * Returns true if any instances exist.
- */
- static bool isActive() { return instances.size() > 0; }
-
- /**
* Closes all instances.
*/
static void closeAll();
diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp
index e4a5fd01..a2cb2efb 100644
--- a/src/gui/charcreatedialog.cpp
+++ b/src/gui/charcreatedialog.cpp
@@ -54,7 +54,7 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot):
mCharSelectDialog(parent),
mSlot(slot)
{
- mPlayer = new Player(0, 0, NULL);
+ mPlayer = new Being(0, ActorSprite::PLAYER, 0, NULL);
mPlayer->setGender(GENDER_MALE);
int numberOfHairColors = ColorDB::size();
diff --git a/src/gui/charcreatedialog.h b/src/gui/charcreatedialog.h
index 902e650e..018de3f5 100644
--- a/src/gui/charcreatedialog.h
+++ b/src/gui/charcreatedialog.h
@@ -22,7 +22,7 @@
#ifndef CHAR_CREATE_DIALOG_H
#define CHAR_CREATE_DIALOG_H
-#include "player.h"
+#include "being.h"
#include "guichanfwd.h"
#include "gui/charselectdialog.h"
@@ -110,7 +110,7 @@ class CharCreateDialog : public Window, public gcn::ActionListener
gcn::Button *mCreateButton;
gcn::Button *mCancelButton;
- Player *mPlayer;
+ Being *mPlayer;
PlayerBox *mPlayerBox;
int mHairStyle;
diff --git a/src/gui/charselectdialog.cpp b/src/gui/charselectdialog.cpp
index e22c4daf..9d6050f8 100644
--- a/src/gui/charselectdialog.cpp
+++ b/src/gui/charselectdialog.cpp
@@ -388,8 +388,10 @@ void CharacterDisplay::update()
mButton->setCaption(_("Choose"));
mButton->setActionEventId("use");
mName->setCaption(strprintf("%s", character->getName().c_str()));
- mLevel->setCaption(strprintf("Level %d", character->getLevel()));
- mMoney->setCaption(Units::formatCurrency(character->getMoney()));
+ mLevel->setCaption(strprintf("Level %d",
+ mCharacter->data.mAttributes[LEVEL]));
+ mMoney->setCaption(Units::formatCurrency(
+ mCharacter->data.mAttributes[MONEY]));
mDelete->setVisible(true);
}
diff --git a/src/gui/charselectdialog.h b/src/gui/charselectdialog.h
index b6e71715..6d565135 100644
--- a/src/gui/charselectdialog.h
+++ b/src/gui/charselectdialog.h
@@ -22,9 +22,9 @@
#ifndef CHAR_SELECT_H
#define CHAR_SELECT_H
+#include "being.h"
#include "guichanfwd.h"
#include "main.h"
-#include "player.h"
#include "gui/widgets/window.h"
diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp
index f87a8a3d..b1d4b131 100644
--- a/src/gui/chat.cpp
+++ b/src/gui/chat.cpp
@@ -21,10 +21,11 @@
#include "chat.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
#include "configuration.h"
#include "localplayer.h"
#include "party.h"
+#include "playerrelations.h"
#include "gui/recorder.h"
#include "gui/setup.h"
@@ -77,6 +78,9 @@ ChatWindow::ChatWindow():
Window(_("Chat")),
mTmpVisible(false)
{
+ listen("Chat");
+ listen("Notices");
+
setWindowName("Chat");
setupWindow->registerWindowForReset(this);
@@ -108,7 +112,7 @@ ChatWindow::ChatWindow():
mChatInput->addKeyListener(this);
mCurHist = mHistory.end();
- mReturnToggles = config.getValue("ReturnToggles", "0") == "1";
+ mReturnToggles = config.getBoolValue("ReturnToggles");
mRecorder = new Recorder(this);
}
@@ -281,20 +285,20 @@ void ChatWindow::chatInput(const std::string &msg)
void ChatWindow::doPresent()
{
- const Beings &beings = beingManager->getAll();
+ const ActorSprites &actors = actorSpriteManager->getAll();
std::string response = "";
int playercount = 0;
- for (Beings::const_iterator bi = beings.begin(), be = beings.end();
- bi != be; ++bi)
+ for (ActorSpritesConstIterator it = actors.begin(), it_end = actors.end();
+ it != it_end; it++)
{
- if ((*bi)->getType() == Being::PLAYER)
+ if ((*it)->getType() == ActorSprite::PLAYER)
{
if (!response.empty())
{
response += ", ";
}
- response += (*bi)->getName();
+ response += static_cast<Being*>(*it)->getName();
++playercount;
}
}
@@ -408,6 +412,40 @@ void ChatWindow::keyPressed(gcn::KeyEvent &event)
}
}
+void ChatWindow::event(const std::string &channel, const Mana::Event &event)
+{
+ if (channel == "Notices")
+ {
+ if (event.getName() == "ServerNotice")
+ localChatTab->chatLog(event.getString("message"), BY_SERVER);
+ }
+ else if (channel == "Chat")
+ {
+ if (event.getName() == "Whisper")
+ {
+ whisper(event.getString("nick"), event.getString("message"));
+ }
+ else if (event.getName() == "WhisperError")
+ {
+ whisper(event.getString("nick"),
+ event.getString("error"), BY_SERVER);
+ }
+ else if (event.getName() == "Player")
+ {
+ localChatTab->chatLog(event.getString("message"), BY_PLAYER);
+ }
+ else if (event.getName() == "Announcement")
+ {
+ localChatTab->chatLog(event.getString("message"), BY_GM);
+ }
+ else if (event.getName() == "Being")
+ {
+ if (event.getInt("permissions") & PlayerRelation::SPEECH_LOG)
+ localChatTab->chatLog(event.getString("message"), BY_OTHER);
+ }
+ }
+}
+
void ChatWindow::addInputText(const std::string &text)
{
const int caretPos = mChatInput->getCaretPosition();
@@ -446,7 +484,7 @@ void ChatWindow::setRecordingFile(const std::string &msg)
}
void ChatWindow::whisper(const std::string &nick,
- const std::string &mes, bool own)
+ const std::string &mes, Own own)
{
if (mes.empty())
return;
@@ -465,15 +503,19 @@ void ChatWindow::whisper(const std::string &nick,
if (i != mWhispers.end())
tab = i->second;
- else if (config.getValue("whispertab", true))
+ else if (config.getBoolValue("whispertab"))
tab = addWhisperTab(nick);
if (tab)
{
- if (own)
+ if (own == BY_PLAYER)
{
tab->chatInput(mes);
}
+ else if (own == BY_SERVER)
+ {
+ tab->chatLog(mes);
+ }
else
{
tab->chatLog(nick, mes);
@@ -482,7 +524,7 @@ void ChatWindow::whisper(const std::string &nick,
}
else
{
- if (own)
+ if (own == BY_PLAYER)
{
Net::getChatHandler()->privateMessage(nick, mes);
@@ -546,7 +588,7 @@ void ChatWindow::autoComplete()
if (newName == "")
{
- beingManager->getPlayerNames(nameList, true);
+ actorSpriteManager->getPlayerNames(nameList, true);
newName = autoComplete(nameList, name);
}
if (newName == "")
diff --git a/src/gui/chat.h b/src/gui/chat.h
index e49d02c9..db5fe293 100644
--- a/src/gui/chat.h
+++ b/src/gui/chat.h
@@ -22,6 +22,8 @@
#ifndef CHAT_H
#define CHAT_H
+#include "listener.h"
+
#include "gui/widgets/window.h"
#include <guichan/actionlistener.hpp>
@@ -35,8 +37,8 @@
#include <vector>
class BrowserBox;
-class Channel;
class ChatTab;
+class Channel;
class ChatInput;
class Recorder;
class ScrollArea;
@@ -47,12 +49,24 @@ class WhisperTab;
#define DEFAULT_CHAT_WINDOW_SCROLL 7 // 1 means `1/8th of the window size'.
+enum Own
+{
+ BY_GM,
+ BY_PLAYER,
+ BY_OTHER,
+ BY_SERVER,
+ BY_CHANNEL,
+ ACT_WHISPER, // getting whispered at
+ ACT_IS, // equivalent to "/me" on IRC
+ BY_LOGGER
+};
+
/** One item in the chat log */
struct CHATLOG
{
std::string nick;
std::string text;
- int own;
+ Own own;
};
/**
@@ -62,7 +76,8 @@ struct CHATLOG
*/
class ChatWindow : public Window,
public gcn::ActionListener,
- public gcn::KeyListener
+ public gcn::KeyListener,
+ public Mana::Listener
{
public:
/**
@@ -147,6 +162,7 @@ class ChatWindow : public Window,
void mousePressed(gcn::MouseEvent &event);
void mouseDragged(gcn::MouseEvent &event);
+ void event(const std::string &channel, const Mana::Event &event);
/**
* Scrolls the chat window
@@ -170,7 +186,7 @@ class ChatWindow : public Window,
void doPresent();
void whisper(const std::string &nick, const std::string &mes,
- bool own = false);
+ Own own = BY_OTHER);
ChatTab *addWhisperTab(const std::string &nick, bool switchTo = false);
diff --git a/src/gui/emotepopup.cpp b/src/gui/emotepopup.cpp
index 7c05e263..f9dc8e0f 100644
--- a/src/gui/emotepopup.cpp
+++ b/src/gui/emotepopup.cpp
@@ -29,11 +29,10 @@
#include "localplayer.h"
#include "log.h"
-#include "gui/theme.h"
-
#include "resources/emotedb.h"
#include "resources/image.h"
#include "resources/iteminfo.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
@@ -61,7 +60,7 @@ EmotePopup::EmotePopup():
if (!mSelectionImage)
logger->error("Unable to load selection.png");
- mSelectionImage->setAlpha(config.getValue("guialpha", 0.8));
+ mSelectionImage->setAlpha(config.getFloatValue("guialpha"));
addMouseListener(this);
recalculateSize();
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index 43e330f4..dcc372cd 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -29,7 +29,6 @@
#include "gui/equipmentwindow.h"
#include "gui/itempopup.h"
-#include "gui/theme.h"
#include "gui/setup.h"
#include "gui/viewport.h"
@@ -41,6 +40,7 @@
#include "resources/image.h"
#include "resources/iteminfo.h"
#include "resources/resourcemanager.h"
+#include "resources/theme.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index df2ddadf..f8dc3e82 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -24,7 +24,6 @@
#include "gui/focushandler.h"
#include "gui/palette.h"
#include "gui/sdlinput.h"
-#include "gui/theme.h"
#include "gui/truetypefont.h"
#include "gui/widgets/window.h"
@@ -39,6 +38,7 @@
#include "resources/imageset.h"
#include "resources/imageloader.h"
#include "resources/resourcemanager.h"
+#include "resources/theme.h"
#include <guichan/exception.hpp>
#include <guichan/image.hpp>
@@ -61,7 +61,7 @@ class GuiConfigListener : public ConfigListener
{
if (name == "customcursor")
{
- bool bCustomCursor = config.getValue("customcursor", 1) == 1;
+ bool bCustomCursor = config.getBoolValue("customcursor");
mGui->setUseCustomCursor(bCustomCursor);
}
}
@@ -104,7 +104,7 @@ Gui::Gui(Graphics *graphics):
ResourceManager *resman = ResourceManager::getInstance();
// Set global font
- const int fontSize = (int) config.getValue("fontSize", 11);
+ const int fontSize = config.getValue("fontSize", 11);
std::string fontFile = branding.getValue("font", "fonts/dejavusans.ttf");
std::string path = resman->getPath(fontFile);
@@ -135,7 +135,7 @@ Gui::Gui(Graphics *graphics):
gcn::Widget::setGlobalFont(mGuiFont);
// Initialize mouse cursor and listen for changes to the option
- setUseCustomCursor(config.getValue("customcursor", 1) == 1);
+ setUseCustomCursor(config.getBoolValue("customcursor"));
mConfigListener = new GuiConfigListener(this);
config.addListener("customcursor", mConfigListener);
}
diff --git a/src/gui/help.cpp b/src/gui/help.cpp
index f3c6a0af..aca036c1 100644
--- a/src/gui/help.cpp
+++ b/src/gui/help.cpp
@@ -94,9 +94,9 @@ void HelpWindow::loadHelp(const std::string &helpFile)
void HelpWindow::loadFile(const std::string &file)
{
ResourceManager *resman = ResourceManager::getInstance();
- std::string helpPath = branding.getValue("helpPath", "");
+ std::string helpPath = branding.getStringValue("helpPath");
if (helpPath.empty())
- helpPath = paths.getValue("help", "help/");
+ helpPath = paths.getStringValue("help");
std::vector<std::string> lines =
resman->loadTextFile(helpPath + file + ".txt");
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index 591ebd2f..41ac96b4 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -23,14 +23,13 @@
#include "inventory.h"
#include "item.h"
-#include "localplayer.h"
#include "units.h"
#include "keyboardconfig.h"
+#include "playerinfo.h"
#include "gui/itemamount.h"
#include "gui/setup.h"
#include "gui/sdlinput.h"
-#include "gui/theme.h"
#include "gui/viewport.h"
#include "gui/widgets/button.h"
@@ -44,6 +43,7 @@
#include "net/net.h"
#include "resources/iteminfo.h"
+#include "resources/theme.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
@@ -60,6 +60,8 @@ InventoryWindow::InventoryWindow(Inventory *inventory):
mInventory(inventory),
mSplit(false)
{
+ listen("Attributes");
+
setWindowName(isMainInventory() ? "Inventory" : "Storage");
setupWindow->registerWindowForReset(this);
setResizable(true);
@@ -138,13 +140,19 @@ InventoryWindow::InventoryWindow(Inventory *inventory):
slotsChanged(mInventory);
if (!isMainInventory())
+ {
setVisible(true);
+ PlayerInfo::setStorageCount(PlayerInfo::getStorageCount() + 1);
+ }
}
InventoryWindow::~InventoryWindow()
{
instances.remove(this);
mInventory->removeInventoyListener(this);
+
+ if (!isMainInventory())
+ PlayerInfo::setStorageCount(PlayerInfo::getStorageCount() - 1);
}
void InventoryWindow::action(const gcn::ActionEvent &event)
@@ -234,7 +242,7 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
if (event.getButton() == gcn::MouseEvent::LEFT)
{
- if (isStorageActive() && keyboard.isKeyActive(keyboard.KEY_EMOTE))
+ if (instances.size() > 1 && keyboard.isKeyActive(keyboard.KEY_EMOTE))
{
Item *item = mItems->getSelectedItem();
@@ -341,10 +349,29 @@ void InventoryWindow::close()
}
}
+void InventoryWindow::event(const std::string &channel, const Mana::Event &event)
+{
+ if (event.getName() == "UpdateAttribute")
+ {
+ int id = event.getInt("id");
+ if (id == TOTAL_WEIGHT ||
+ id == MAX_WEIGHT)
+ {
+ updateWeight();
+ }
+ }
+}
+
void InventoryWindow::updateWeight()
{
- int total = player_node->getTotalWeight();
- int max = player_node->getMaxWeight();
+ if (!isMainInventory())
+ return;
+
+ int total = PlayerInfo::getAttribute(TOTAL_WEIGHT);
+ int max = PlayerInfo::getAttribute(MAX_WEIGHT);
+
+ if (max <= 0)
+ return;
// Adjust progress bar
mWeightBar->setProgress((float) total / max);
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index f611e934..af72106b 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -23,6 +23,7 @@
#define INVENTORYWINDOW_H
#include "inventory.h"
+#include "listener.h"
#include "gui/widgets/window.h"
@@ -47,7 +48,8 @@ class InventoryWindow : public Window,
public gcn::ActionListener,
public gcn::KeyListener,
public gcn::SelectionListener,
- public InventoryListener
+ public InventoryListener,
+ public Mana::Listener
{
public:
/**
@@ -100,22 +102,20 @@ class InventoryWindow : public Window,
* window has been closed.
*/
void close();
-
- /**
- * Updates the weight bar.
- */
- void updateWeight();
void slotsChanged(Inventory* inventory);
bool isMainInventory() { return mInventory->isMainInventory(); }
+ void event(const std::string &channel, const Mana::Event &event);
+
+ private:
/**
- * Returns true if any instances exist.
+ * Updates the weight bar.
*/
- static bool isStorageActive() { return instances.size() > 1; }
+ void updateWeight();
+
- private:
typedef std::list<InventoryWindow*> WindowList;
static WindowList instances;
diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp
index 0cde9395..c926670a 100644
--- a/src/gui/itempopup.cpp
+++ b/src/gui/itempopup.cpp
@@ -26,9 +26,9 @@
#include "units.h"
#include "gui/gui.h"
-#include "gui/theme.h"
#include "gui/widgets/icon.h"
+#include "gui/widgets/label.h"
#include "gui/widgets/textbox.h"
#include "utils/gettext.h"
@@ -36,6 +36,7 @@
#include "resources/image.h"
#include "resources/resourcemanager.h"
+#include "resources/theme.h"
#include <guichan/font.hpp>
@@ -46,7 +47,7 @@ ItemPopup::ItemPopup():
mIcon(0)
{
// Item Name
- mItemName = new gcn::Label;
+ mItemName = new Label;
mItemName->setFont(boldFont);
mItemName->setPosition(getPadding(), getPadding());
@@ -103,8 +104,9 @@ void ItemPopup::setItem(const ItemInfo &item, bool showImage)
{
ResourceManager *resman = ResourceManager::getInstance();
Image *image = resman->getImage(
- paths.getValue("itemIcons", "graphics/items/")
- + item.getImageName());
+ paths.getStringValue("itemIcons")
+ + item.getDisplay().image);
+
mIcon->setImage(image);
if (image)
{
diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp
index 35844f64..dd447f95 100644
--- a/src/gui/minimap.cpp
+++ b/src/gui/minimap.cpp
@@ -21,20 +21,19 @@
#include "gui/minimap.h"
+#include "actorspritemanager.h"
#include "being.h"
-#include "beingmanager.h"
#include "configuration.h"
#include "graphics.h"
#include "localplayer.h"
#include "log.h"
#include "map.h"
-#include "player.h"
#include "gui/setup.h"
-#include "gui/userpalette.h"
#include "resources/image.h"
#include "resources/resourcemanager.h"
+#include "resources/userpalette.h"
#include "utils/gettext.h"
@@ -185,52 +184,46 @@ void Minimap::draw(gcn::Graphics *graphics)
drawImage(mMapImage, mapOriginX, mapOriginY);
}
- const Beings &beings = beingManager->getAll();
+ const ActorSprites &actors = actorSpriteManager->getAll();
- for (Beings::const_iterator bi = beings.begin(), bi_end = beings.end();
- bi != bi_end; ++bi)
+ for (ActorSpritesConstIterator it = actors.begin(), it_end = actors.end();
+ it != it_end; it++)
{
- const Being *being = (*bi);
+ if ((*it)->getType() == ActorSprite::FLOOR_ITEM)
+ continue;
+
+ const Being *being = static_cast<Being*>(*it);
int dotSize = 2;
- switch (being->getType())
+ int type = UserPalette::PC;
+
+ if (being == player_node)
+ {
+ type = UserPalette::SELF;
+ dotSize = 3;
+ }
+ else if (being->isGM())
+ type = UserPalette::GM;
+ else if (being->isInParty())
+ type = UserPalette::PARTY;
+ else
{
- case Being::PLAYER:
- {
- const Player *player = static_cast<const Player*>(being);
-
- int type = UserPalette::PC;
-
- if (being == player_node)
- {
- type = UserPalette::SELF;
- dotSize = 3;
- }
- else if (player->isGM())
- {
- type = UserPalette::GM;
- }
- else if (player->isInParty())
- {
- type = UserPalette::PARTY;
- }
-
- graphics->setColor(userPalette->getColor(type));
+ switch (being->getType())
+ {
+ case ActorSprite::MONSTER:
+ graphics->setColor(userPalette->getColor(UserPalette::MONSTER));
break;
- }
-
- case Being::MONSTER:
- graphics->setColor(userPalette->getColor(UserPalette::MONSTER));
- break;
- case Being::NPC:
- graphics->setColor(userPalette->getColor(UserPalette::NPC));
- break;
+ case ActorSprite::NPC:
+ graphics->setColor(userPalette->getColor(UserPalette::NPC));
+ break;
- default:
- continue;
+ default:
+ continue;
+ }
}
+ graphics->setColor(userPalette->getColor(type));
const int offsetHeight = (int) ((dotSize - 1) * mHeightProportion);
const int offsetWidth = (int) ((dotSize - 1) * mWidthProportion);
diff --git a/src/gui/ministatus.cpp b/src/gui/ministatus.cpp
index 90581f61..1642d1b0 100644
--- a/src/gui/ministatus.cpp
+++ b/src/gui/ministatus.cpp
@@ -24,17 +24,20 @@
#include "animatedsprite.h"
#include "configuration.h"
#include "graphics.h"
-#include "localplayer.h"
+#include "playerinfo.h"
+#include "statuseffect.h"
#include "gui/gui.h"
#include "gui/statuswindow.h"
#include "gui/textpopup.h"
-#include "gui/theme.h"
#include "gui/widgets/progressbar.h"
#include "net/net.h"
#include "net/playerhandler.h"
+#include "net/gamehandler.h"
+
+#include "resources/theme.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
@@ -44,22 +47,36 @@ extern volatile int tick_time;
MiniStatusWindow::MiniStatusWindow():
Popup("MiniStatus")
{
- int max = player_node->getMaxHp();
- mHpBar = new ProgressBar(max ? (float) player_node->getHp() / max : 0,
- 100, 20, Theme::PROG_HP);
- max = player_node->getMaxMP();
- mMpBar = new ProgressBar(max ? (float) player_node->getMP() / max : 0,
- 100, 20, Net::getPlayerHandler()->canUseMagic() ?
- Theme::PROG_MP : Theme::PROG_NO_MP);
- max = player_node->getExpNeeded();
- mXpBar = new ProgressBar(max ? (float) player_node->getExp() / max : 0,
- 100, 20, Theme::PROG_EXP);
+ listen("Attributes");
+
+ mHpBar = new ProgressBar(0, 100, 20, Theme::PROG_HP);
+ StatusWindow::updateHPBar(mHpBar);
+
+ if (Net::getGameHandler()->canUseMagicBar())
+ {
+ mMpBar = new ProgressBar(0, 100, 20,
+ Net::getPlayerHandler()->canUseMagic()
+ ? Theme::PROG_MP : Theme::PROG_NO_MP);
+
+ StatusWindow::updateMPBar(mMpBar);
+ }
+ else
+ mMpBar = 0;
+
+ mXpBar = new ProgressBar(0, 100, 20, Theme::PROG_EXP);
+ StatusWindow::updateXPBar(mXpBar);
+
+ // Add the progressbars to the window
+
mHpBar->setPosition(0, 3);
- mMpBar->setPosition(mHpBar->getWidth() + 3, 3);
- mXpBar->setPosition(mMpBar->getX() + mMpBar->getWidth() + 3, 3);
+ if (mMpBar)
+ mMpBar->setPosition(mHpBar->getWidth() + 3, 3);
+ mXpBar->setPosition(mMpBar ? mMpBar->getX() + mMpBar->getWidth() + 3 :
+ mHpBar->getX() + mHpBar->getWidth() + 3, 3);
add(mHpBar);
- add(mMpBar);
+ if (mMpBar)
+ add(mMpBar);
add(mXpBar);
setContentSize(mXpBar->getX() + mXpBar->getWidth(),
@@ -70,8 +87,6 @@ MiniStatusWindow::MiniStatusWindow():
mTextPopup = new TextPopup();
addMouseListener(this);
-
- update(StatusWindow::HP);
}
void MiniStatusWindow::setIcon(int index, AnimatedSprite *sprite)
@@ -104,19 +119,82 @@ void MiniStatusWindow::drawIcons(Graphics *graphics)
}
}
-void MiniStatusWindow::update(int id)
+void MiniStatusWindow::event(const std::string &channel, const Mana::Event &event)
{
- if (id == StatusWindow::HP)
- {
- StatusWindow::updateHPBar(mHpBar);
- }
- else if (id == StatusWindow::MP)
+ if (channel == "Attributes")
{
- StatusWindow::updateMPBar(mMpBar);
+ if (event.getName() == "UpdateAttribute")
+ {
+ int id = event.getInt("id");
+ if (id == HP || id == MAX_HP)
+ {
+ StatusWindow::updateHPBar(mHpBar);
+ }
+ else if (id == MP || id == MAX_MP)
+ {
+ StatusWindow::updateMPBar(mMpBar);
+ }
+ else if (id == EXP || id == EXP_NEEDED)
+ {
+ StatusWindow::updateXPBar(mXpBar);
+ }
+ }
}
- else if (id == StatusWindow::EXP)
+ else if (channel == "ActorSprite")
{
- StatusWindow::updateXPBar(mXpBar);
+ if (event.getName() == "UpdateStatusEffect")
+ {
+ int index = event.getInt("index");
+ bool newStatus = event.getBool("newStatus");
+
+ StatusEffect *effect = StatusEffect::getStatusEffect(index,
+ newStatus);
+
+ if (effect)
+ {
+ effect->deliverMessage();
+ effect->playSFX();
+
+ AnimatedSprite *sprite = effect->getIcon();
+
+ typedef std::vector<int> IntMap;
+
+ if (!sprite)
+ {
+ // delete sprite, if necessary
+ for (unsigned int i = 0; i < mStatusEffectIcons.size();)
+ if (mStatusEffectIcons[i] == index)
+ {
+ 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] == index)
+ {
+ miniStatusWindow->setIcon(i, sprite);
+ found = true;
+ break;
+ }
+
+ if (!found)
+ { // add new
+ int offset = mStatusEffectIcons.size();
+ miniStatusWindow->setIcon(offset, sprite);
+ mStatusEffectIcons.push_back(index);
+ }
+ }
+ }
+ }
}
}
@@ -152,23 +230,23 @@ void MiniStatusWindow::mouseMoved(gcn::MouseEvent &event)
if (event.getSource() == mXpBar)
{
mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", player_node->getExp(),
- player_node->getExpNeeded()),
+ strprintf("%u/%u", PlayerInfo::getAttribute(EXP),
+ PlayerInfo::getAttribute(EXP_NEEDED)),
strprintf("%s: %u", _("Need"),
- player_node->getExpNeeded()
- - player_node->getExp()));
+ PlayerInfo::getAttribute(EXP_NEEDED)
+ - PlayerInfo::getAttribute(EXP)));
}
else if (event.getSource() == mHpBar)
{
mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", player_node->getHp(),
- player_node->getMaxHp()));
+ strprintf("%u/%u", PlayerInfo::getAttribute(HP),
+ PlayerInfo::getAttribute(MAX_HP)));
}
else if (event.getSource() == mMpBar)
{
mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", player_node->getMP(),
- player_node->getMaxMP()));
+ strprintf("%u/%u", PlayerInfo::getAttribute(MP),
+ PlayerInfo::getAttribute(MAX_MP)));
}
else
{
@@ -182,5 +260,3 @@ void MiniStatusWindow::mouseExited(gcn::MouseEvent &event)
mTextPopup->setVisible(false);
}
-
-
diff --git a/src/gui/ministatus.h b/src/gui/ministatus.h
index bb8d4094..077eedeb 100644
--- a/src/gui/ministatus.h
+++ b/src/gui/ministatus.h
@@ -22,6 +22,8 @@
#ifndef MINISTATUS_H
#define MINISTATUS_H
+#include "listener.h"
+
#include "gui/widgets/popup.h"
#include <vector>
@@ -36,21 +38,14 @@ class TextPopup;
*
* \ingroup Interface
*/
-class MiniStatusWindow : public Popup
+class MiniStatusWindow : public Popup, public Mana::Listener
{
public:
MiniStatusWindow();
- /**
- * Sets one of the icons.
- */
- void setIcon(int index, AnimatedSprite *sprite);
-
- void eraseIcon(int index);
-
void drawIcons(Graphics *graphics);
- void update(int id); // Same types as status window
+ void event(const std::string &channel, const Mana::Event &event);
void logic(); // Updates icons
@@ -63,6 +58,13 @@ class MiniStatusWindow : public Popup
private:
bool isInBar(ProgressBar *bar, int x, int y) const;
+ /**
+ * Sets one of the icons.
+ */
+ void setIcon(int index, AnimatedSprite *sprite);
+
+ void eraseIcon(int index);
+
/*
* Mini Status Bars
*/
@@ -71,6 +73,7 @@ class MiniStatusWindow : public Popup
ProgressBar *mXpBar;
TextPopup *mTextPopup;
+ std::vector<int> mStatusEffectIcons;
std::vector<AnimatedSprite *> mIcons;
};
diff --git a/src/gui/npcdialog.cpp b/src/gui/npcdialog.cpp
index 6d3995a7..935962a0 100644
--- a/src/gui/npcdialog.cpp
+++ b/src/gui/npcdialog.cpp
@@ -22,8 +22,11 @@
#include "gui/npcdialog.h"
#include "configuration.h"
-#include "npc.h"
+#include "event.h"
+#include "listener.h"
+#include "playerinfo.h"
+#include "gui/npcpostdialog.h"
#include "gui/setup.h"
#include "gui/widgets/button.h"
@@ -34,9 +37,6 @@
#include "gui/widgets/textbox.h"
#include "gui/widgets/textfield.h"
-#include "net/net.h"
-#include "net/npchandler.h"
-
#include "utils/gettext.h"
#include "utils/stringutils.h"
@@ -47,12 +47,32 @@
#define CAPTION_CLOSE _("Close")
#define CAPTION_SUBMIT _("Submit")
+#define NpcEvent(name) Mana::Event event(name);\
+event.setInt("npcId", mNpcId);
+
+typedef std::map<int, NpcDialog*> NpcDialogs;
+
+class NpcEventListener : public Mana::Listener
+{
+public:
+ void event(const std::string &channel, const Mana::Event &event);
+
+ NpcDialog *getDialog(int id, bool make = true);
+
+ void removeDialog(int id);
+
+private:
+ NpcDialogs mNpcDialogs;
+};
+
+static NpcEventListener *npcListener = NULL;
+
NpcDialog::DialogList NpcDialog::instances;
NpcDialog::NpcDialog(int npcId)
: Window(_("NPC")),
mNpcId(npcId),
- mLogInteraction(config.getValue("logNpcInGui", true)),
+ mLogInteraction(config.getBoolValue("logNpcInGui")),
mDefaultInt(0),
mInputState(NPC_INPUT_NONE),
mActionState(NPC_ACTION_WAIT)
@@ -124,6 +144,8 @@ NpcDialog::NpcDialog(int npcId)
requestFocus();
config.addListener("logNpcInGui", this);
+ PlayerInfo::setNPCInteractionCount(PlayerInfo::getNPCInteractionCount()
+ + 1);
}
NpcDialog::~NpcDialog()
@@ -140,6 +162,10 @@ NpcDialog::~NpcDialog()
instances.remove(this);
config.removeListener("logNpcInGui", this);
+ PlayerInfo::setNPCInteractionCount(PlayerInfo::getNPCInteractionCount()
+ - 1);
+
+ npcListener->removeDialog(mNpcId);
}
void NpcDialog::setText(const std::string &text)
@@ -192,27 +218,32 @@ void NpcDialog::action(const gcn::ActionEvent &event)
if (mInputState == NPC_INPUT_LIST)
{
- int choice = 0;
int selectedIndex = mItemList->getSelected();
if (selectedIndex >= (int) mItems.size() || selectedIndex < 0)
- {
return;
- }
- choice = selectedIndex + 1;
+
printText = mItems[selectedIndex];
- Net::getNpcHandler()->listInput(mNpcId, choice);
+ NpcEvent("doMenu")
+ event.setInt("choice", selectedIndex + 1);
+ event.trigger("NPC");
}
else if (mInputState == NPC_INPUT_STRING)
{
printText = mTextField->getText();
- Net::getNpcHandler()->stringInput(mNpcId, printText);
+
+ NpcEvent("doStringInput")
+ event.setString("value", printText);
+ event.trigger("NPC");
}
else if (mInputState == NPC_INPUT_INTEGER)
{
printText = strprintf("%d", mIntField->getValue());
- Net::getNpcHandler()->integerInput(mNpcId, mIntField->getValue());
+
+ NpcEvent("doIntegerInput")
+ event.setInt("value", mIntField->getValue());
+ event.trigger("NPC");
}
// addText will auto remove the input layout
addText(strprintf("\n> \"%s\"\n", printText.c_str()), false);
@@ -250,12 +281,15 @@ void NpcDialog::action(const gcn::ActionEvent &event)
void NpcDialog::nextDialog()
{
- Net::getNpcHandler()->nextDialog(mNpcId);
+ NpcEvent("doNext");
+ event.trigger("NPC");
}
void NpcDialog::closeDialog()
{
- Net::getNpcHandler()->closeDialog(mNpcId);
+ NpcEvent("doClose");
+ event.trigger("NPC");
+ close();
}
int NpcDialog::getNumberOfElements()
@@ -281,15 +315,6 @@ void NpcDialog::addChoice(const std::string &choice)
mItems.push_back(choice);
}
-void NpcDialog::parseListItems(const std::string &itemString)
-{
- std::istringstream iss(itemString);
-
- std::string tmp;
- while (getline(iss, tmp, ':'))
- mItems.push_back(tmp);
-}
-
void NpcDialog::textRequest(const std::string &defaultText)
{
mActionState = NPC_ACTION_INPUT;
@@ -370,7 +395,7 @@ void NpcDialog::optionChanged(const std::string &name)
{
if (name == "logNpcInGui")
{
- mLogInteraction = config.getValue("logNpcInGui", true);
+ mLogInteraction = config.getBoolValue("logNpcInGui");
}
}
@@ -404,6 +429,16 @@ void NpcDialog::closeAll()
}
}
+void NpcDialog::setup()
+{
+ if (npcListener)
+ return;
+
+ npcListener = new NpcEventListener();
+
+ npcListener->listen("NPC");
+}
+
void NpcDialog::buildLayout()
{
clearLayout();
@@ -470,3 +505,125 @@ void NpcDialog::buildLayout()
mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll());
}
+
+void NpcEventListener::event(const std::string &channel,
+ const Mana::Event &event)
+{
+ if (channel != "NPC")
+ return;
+
+ if (event.getName() == "Message")
+ {
+ NpcDialog *dialog = getDialog(event.getInt("id"));
+
+ dialog->addText(event.getString("text"));
+ }
+ else if (event.getName() == "Menu")
+ {
+ NpcDialog *dialog = getDialog(event.getInt("id"));
+
+ dialog->choiceRequest();
+
+ int count = event.getInt("choiceCount");
+ for (int i = 1; i <= count; i++)
+ dialog->addChoice(event.getString("choice" + toString(i)));
+ }
+ else if (event.getName() == "IntegerInput")
+ {
+ NpcDialog *dialog = getDialog(event.getInt("id"));
+
+ int defaultValue = event.getInt("default", 0);
+ int min = event.getInt("min", 0);
+ int max = event.getInt("max", 2147483647);
+
+ dialog->integerRequest(defaultValue, min, max);
+ }
+ else if (event.getName() == "StringInput")
+ {
+ NpcDialog *dialog = getDialog(event.getInt("id"));
+
+ try
+ {
+ dialog->textRequest(event.getString("default"));
+ }
+ catch (Mana::BadEvent)
+ {
+ dialog->textRequest("");
+ }
+ }
+ else if (event.getName() == "Next")
+ {
+ int id = event.getInt("id");
+ NpcDialog *dialog = getDialog(id, false);
+
+ if (!dialog)
+ {
+ int mNpcId = id;
+ NpcEvent("doNext");
+ event.trigger("NPC");
+ return;
+ }
+
+ dialog->showNextButton();
+ }
+ else if (event.getName() == "Close")
+ {
+ int id = event.getInt("id");
+ NpcDialog *dialog = getDialog(id, false);
+
+ if (!dialog)
+ {
+ int mNpcId = id;
+ NpcEvent("doClose");
+ event.trigger("NPC");
+ return;
+ }
+
+ dialog->showCloseButton();
+ }
+ else if (event.getName() == "CloseAll")
+ {
+ NpcDialog::closeAll();
+ }
+ else if (event.getName() == "End")
+ {
+ int id = event.getInt("id");
+ NpcDialog *dialog = getDialog(id, false);
+
+ if (dialog)
+ dialog->close();
+ }
+ else if (event.getName() == "Post")
+ {
+ new NpcPostDialog(event.getInt("id"));
+ }
+}
+
+NpcDialog *NpcEventListener::getDialog(int id, bool make)
+{
+ NpcDialogs::iterator diag = mNpcDialogs.find(id);
+ NpcDialog *dialog = 0;
+
+ if (diag == mNpcDialogs.end())
+ {
+ // Empty dialogs don't help
+ if (make)
+ {
+ dialog = new NpcDialog(id);
+ mNpcDialogs[id] = dialog;
+ }
+ }
+ else
+ {
+ dialog = diag->second;
+ }
+
+ return dialog;
+}
+
+void NpcEventListener::removeDialog(int id)
+{
+ NpcDialogs::iterator it = mNpcDialogs.find(id);
+ if (it != mNpcDialogs.end())
+ mNpcDialogs.erase(it);
+}
diff --git a/src/gui/npcdialog.h b/src/gui/npcdialog.h
index a8521ce9..5850ecca 100644
--- a/src/gui/npcdialog.h
+++ b/src/gui/npcdialog.h
@@ -23,7 +23,6 @@
#define NPCDIALOG_H
#include "configlistener.h"
-#include "npc.h"
#include "gui/widgets/window.h"
@@ -120,13 +119,6 @@ class NpcDialog : public Window, public gcn::ActionListener,
void addChoice(const std::string &);
/**
- * Fills the options list for an NPC dialog.
- *
- * @param itemString A string with the options separated with colons.
- */
- void parseListItems(const std::string &itemString);
-
- /**
* Requests a text string from the user.
*/
void textRequest(const std::string &defaultText = "");
@@ -138,8 +130,7 @@ class NpcDialog : public Window, public gcn::ActionListener,
/**
* Requests a interger from the user.
*/
- void integerRequest(int defaultValue = 0, int min = 0,
- int max = 2147483647);
+ void integerRequest(int defaultValue, int min, int max);
void move(int amount);
@@ -155,11 +146,6 @@ class NpcDialog : public Window, public gcn::ActionListener,
void optionChanged(const std::string &name);
/**
- * Returns true if any instances exist.
- */
- static bool isActive() { return instances.size() > 0; }
-
- /**
* Returns the first active instance. Useful for pushing user
* interaction.
*/
@@ -170,6 +156,8 @@ class NpcDialog : public Window, public gcn::ActionListener,
*/
static void closeAll();
+ static void setup();
+
private:
typedef std::list<NpcDialog*> DialogList;
static DialogList instances;
diff --git a/src/gui/npcpostdialog.cpp b/src/gui/npcpostdialog.cpp
index 19d0cf61..0662515e 100644
--- a/src/gui/npcpostdialog.cpp
+++ b/src/gui/npcpostdialog.cpp
@@ -21,18 +21,15 @@
#include "gui/npcpostdialog.h"
-#include "npc.h"
+#include "event.h"
+#include "playerinfo.h"
#include "gui/widgets/button.h"
-#include "gui/widgets/chattab.h"
#include "gui/widgets/label.h"
#include "gui/widgets/textbox.h"
#include "gui/widgets/textfield.h"
#include "gui/widgets/scrollarea.h"
-#include "net/net.h"
-#include "net/npchandler.h"
-
#include "utils/gettext.h"
NpcPostDialog::DialogList NpcPostDialog::instances;
@@ -80,11 +77,14 @@ NpcPostDialog::NpcPostDialog(int npcId):
instances.push_back(this);
setVisible(true);
+
+ PlayerInfo::setNPCPostCount(PlayerInfo::getNPCPostCount() + 1);
}
NpcPostDialog::~NpcPostDialog()
{
instances.remove(this);
+ PlayerInfo::setNPCPostCount(PlayerInfo::getNPCPostCount() - 1);
}
void NpcPostDialog::action(const gcn::ActionEvent &event)
@@ -93,13 +93,15 @@ void NpcPostDialog::action(const gcn::ActionEvent &event)
{
if (mSender->getText().empty() || mText->getText().empty())
{
- localChatTab->chatLog(_("Failed to send as sender or letter "
- "invalid."));
+ SERVER_NOTICE(_("Failed to send as sender or letter invalid."))
}
else
{
- Net::getNpcHandler()->sendLetter(mNpcId, mSender->getText(),
- mText->getText());
+ Mana::Event event("doSendLetter");
+ event.setInt("npcId", mNpcId);
+ event.setString("recipient", mSender->getText());
+ event.setString("text", mText->getText());
+ event.trigger("NPC");
}
setVisible(false);
}
diff --git a/src/gui/npcpostdialog.h b/src/gui/npcpostdialog.h
index ad0053a3..248e4515 100644
--- a/src/gui/npcpostdialog.h
+++ b/src/gui/npcpostdialog.h
@@ -47,11 +47,6 @@ public:
void setVisible(bool visible);
/**
- * Returns true if any instances exist.
- */
- static bool isActive() { return instances.size() > 0; }
-
- /**
* Closes all instances.
*/
static void closeAll();
diff --git a/src/gui/outfitwindow.cpp b/src/gui/outfitwindow.cpp
index 89bf47da..ad3342ee 100644
--- a/src/gui/outfitwindow.cpp
+++ b/src/gui/outfitwindow.cpp
@@ -22,18 +22,17 @@
#include "outfitwindow.h"
#include "configuration.h"
-#include "localplayer.h"
+#include "equipment.h"
#include "graphics.h"
#include "inventory.h"
-#include "equipment.h"
#include "item.h"
#include "log.h"
+#include "playerinfo.h"
#include "gui/chat.h"
#include "gui/widgets/button.h"
#include "gui/widgets/checkbox.h"
-#include "gui/widgets/chattab.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layout.h"
@@ -168,7 +167,7 @@ void OutfitWindow::wearOutfit(int outfit)
Item *item;
for (int i = 0; i < OUTFIT_ITEM_COUNT; i++)
{
- item = player_node->getInventory()->findItem(mItems[outfit][i]);
+ item = PlayerInfo::getInventory()->findItem(mItems[outfit][i]);
if (item && !item->isEquipped() && item->getQuantity())
{
if (item->isEquipment())
@@ -206,7 +205,7 @@ void OutfitWindow::draw(gcn::Graphics *graphics)
}
Item *item =
- player_node->getInventory()->findItem(mItems[mCurrentOutfit][i]);
+ PlayerInfo::getInventory()->findItem(mItems[mCurrentOutfit][i]);
if (item)
{
// Draw item icon.
@@ -245,7 +244,7 @@ void OutfitWindow::mouseDragged(gcn::MouseEvent &event)
const int itemId = mItems[mCurrentOutfit][index];
if (itemId < 0)
return;
- Item *item = player_node->getInventory()->findItem(itemId);
+ Item *item = PlayerInfo::getInventory()->findItem(itemId);
if (item)
{
mItemMoved = item;
@@ -319,7 +318,7 @@ int OutfitWindow::getIndexFromGrid(int pointX, int pointY) const
void OutfitWindow::unequipNotInOutfit(int outfit)
{
- Inventory *inventory = player_node->getInventory();
+ Inventory *inventory = PlayerInfo::getInventory();
if (!inventory)
return;
diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp
index 520b4005..7bf1d4fb 100644
--- a/src/gui/popupmenu.cpp
+++ b/src/gui/popupmenu.cpp
@@ -21,14 +21,14 @@
#include "gui/popupmenu.h"
+#include "actorspritemanager.h"
#include "being.h"
-#include "beingmanager.h"
#include "flooritem.h"
#include "graphics.h"
#include "item.h"
#include "localplayer.h"
#include "log.h"
-#include "npc.h"
+#include "playerinfo.h"
#include "playerrelations.h"
#include "gui/chat.h"
@@ -76,7 +76,7 @@ void PopupMenu::showPopup(int x, int y, Being *being)
switch (being->getType())
{
- case Being::PLAYER:
+ case ActorSprite::PLAYER:
{
// Players can be traded with.
mBrowserBox->addRow(strprintf("@@trade|%s@@",
@@ -145,7 +145,7 @@ void PopupMenu::showPopup(int x, int y, Being *being)
}
break;
- case Being::NPC:
+ case ActorSprite::NPC:
// NPCs can be talked to (single option, candidate for removal
// unless more options would be added)
mBrowserBox->addRow(strprintf("@@talk|%s@@",
@@ -153,7 +153,7 @@ void PopupMenu::showPopup(int x, int y, Being *being)
name.c_str()).c_str()));
break;
- case Being::MONSTER:
+ case ActorSprite::MONSTER:
{
// Monsters can be attacked
mBrowserBox->addRow(strprintf("@@attack|%s@@",
@@ -182,11 +182,11 @@ void PopupMenu::showPopup(int x, int y, Being *being)
void PopupMenu::showPopup(int x, int y, FloorItem *floorItem)
{
mFloorItem = floorItem;
- mItem = floorItem->getItem();
+ ItemInfo info = floorItem->getInfo();
mBrowserBox->clearRows();
// Floor item can be picked up (single option, candidate for removal)
- std::string name = ItemDB::get(mFloorItem->getItemId()).getName();
+ std::string name = info.getName();
mBrowserBox->addRow(strprintf("@@pickup|%s@@", strprintf(_("Pick up %s"),
name.c_str()).c_str()));
mBrowserBox->addRow(strprintf("@@chat|%s@@", _("Add to chat")));
@@ -200,16 +200,17 @@ void PopupMenu::showPopup(int x, int y, FloorItem *floorItem)
void PopupMenu::handleLink(const std::string &link)
{
- Being *being = beingManager->findBeing(mBeingId);
+ Being *being = actorSpriteManager->findBeing(mBeingId);
// Talk To action
- if (link == "talk" && being && being->getType() == Being::NPC)
+ if (link == "talk" && being && being->canTalk())
{
- static_cast<NPC*>(being)->talk();
+ being->talkTo();
}
// Trade action
- else if (link == "trade" && being && being->getType() == Being::PLAYER)
+ else if (link == "trade" && being &&
+ being->getType() == ActorSprite::PLAYER)
{
Net::getTradeHandler()->request(being);
tradePartnerName = being->getName();
@@ -223,27 +224,32 @@ void PopupMenu::handleLink(const std::string &link)
{
chatWindow->addInputText("/w \"" + being->getName() + "\" ");
}
- else if (link == "unignore" && being && being->getType() == Being::PLAYER)
+ else if (link == "unignore" && being &&
+ being->getType() == ActorSprite::PLAYER)
{
player_relations.setRelation(being->getName(), PlayerRelation::NEUTRAL);
}
- else if (link == "ignore" && being && being->getType() == Being::PLAYER)
+ else if (link == "ignore" && being &&
+ being->getType() == ActorSprite::PLAYER)
{
player_relations.setRelation(being->getName(), PlayerRelation::IGNORED);
}
- else if (link == "disregard" && being && being->getType() == Being::PLAYER)
+ else if (link == "disregard" && being &&
+ being->getType() == ActorSprite::PLAYER)
{
player_relations.setRelation(being->getName(), PlayerRelation::DISREGARDED);
}
- else if (link == "friend" && being && being->getType() == Being::PLAYER)
+ else if (link == "friend" && being &&
+ being->getType() == ActorSprite::PLAYER)
{
player_relations.setRelation(being->getName(), PlayerRelation::FRIEND);
}
// Guild action
- else if (link == "guild" && being && being->getType() == Being::PLAYER)
+ else if (link == "guild" && being &&
+ being->getType() == ActorSprite::PLAYER)
{
player_node->inviteToGuild(being);
}
@@ -283,7 +289,10 @@ void PopupMenu::handleLink(const std::string &link)
else if (link == "chat")
{
- chatWindow->addItemText(mItem->getInfo().getName());
+ if (mItem)
+ chatWindow->addItemText(mItem->getInfo().getName());
+ else if (mFloorItem)
+ chatWindow->addItemText(mFloorItem->getInfo().getName());
}
else if (link == "split")
@@ -310,9 +319,10 @@ void PopupMenu::handleLink(const std::string &link)
mItem);
}
- else if (link == "party" && being && being->getType() == Being::PLAYER)
+ else if (link == "party" && being &&
+ being->getType() == ActorSprite::PLAYER)
{
- Net::getPartyHandler()->invite(static_cast<Player*>(being));
+ Net::getPartyHandler()->invite(being);
}
else if (link == "name" && being)
@@ -323,8 +333,8 @@ void PopupMenu::handleLink(const std::string &link)
else if (link == "admin-kick" &&
being &&
- (being->getType() == Being::PLAYER ||
- being->getType() == Being::MONSTER))
+ (being->getType() == ActorSprite::PLAYER ||
+ being->getType() == ActorSprite::MONSTER))
{
Net::getAdminHandler()->kick(being->getId());
}
@@ -372,7 +382,7 @@ void PopupMenu::showPopup(Window *parent, int x, int y, Item *item,
mBrowserBox->addRow(strprintf("@@split|%s@@", _("Split")));
}
- if (InventoryWindow::isStorageActive())
+ if (PlayerInfo::getStorageCount() > 0)
{
mBrowserBox->addRow(strprintf("@@store|%s@@", _("Store")));
}
diff --git a/src/gui/recorder.cpp b/src/gui/recorder.cpp
index 257afd7f..2345369e 100644
--- a/src/gui/recorder.cpp
+++ b/src/gui/recorder.cpp
@@ -21,11 +21,11 @@
#include "gui/recorder.h"
#include "client.h"
+#include "event.h"
#include "gui/chat.h"
#include "gui/widgets/button.h"
-#include "gui/widgets/chattab.h"
#include "gui/widgets/layout.h"
#include "gui/widgets/windowcontainer.h"
@@ -84,16 +84,16 @@ void Recorder::setRecordingFile(const std::string &msg)
* Message should go after mStream is closed so that it isn't
* recorded.
*/
- localChatTab->chatLog(_("Finishing recording."), BY_SERVER);
+ SERVER_NOTICE(_("Finishing recording."))
}
else
{
- localChatTab->chatLog(_("Not currently recording."), BY_SERVER);
+ SERVER_NOTICE(_("Not currently recording."))
}
}
else if (mStream.is_open())
{
- localChatTab->chatLog(_("Already recording."), BY_SERVER);
+ SERVER_NOTICE(_("Already recording."))
}
else
{
@@ -101,7 +101,7 @@ void Recorder::setRecordingFile(const std::string &msg)
* Message should go before mStream is opened so that it isn't
* recorded.
*/
- localChatTab->chatLog(_("Starting to record..."), BY_SERVER);
+ SERVER_NOTICE(_("Starting to record..."))
const std::string file = Client::getLocalDataDirectory() + "/" + msgCopy;
mStream.open(file.c_str(), std::ios_base::trunc);
@@ -109,7 +109,7 @@ void Recorder::setRecordingFile(const std::string &msg)
if (mStream.is_open())
setVisible(true);
else
- localChatTab->chatLog(_("Failed to start recording."), BY_SERVER);
+ SERVER_NOTICE(_("Failed to start recording."))
}
}
diff --git a/src/gui/register.h b/src/gui/register.h
index 645b0be8..3c65695b 100644
--- a/src/gui/register.h
+++ b/src/gui/register.h
@@ -22,8 +22,6 @@
#ifndef REGISTER_H
#define REGISTER_H
-#include "player.h"
-
#include "gui/widgets/window.h"
#include <guichan/actionlistener.hpp>
diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp
index 69ff7ed2..83f01d7f 100644
--- a/src/gui/sell.cpp
+++ b/src/gui/sell.cpp
@@ -21,7 +21,7 @@
#include "gui/sell.h"
-#include "npc.h"
+#include "playerinfo.h"
#include "shopitem.h"
#include "units.h"
@@ -111,6 +111,8 @@ SellDialog::SellDialog(int npcId):
instances.push_back(this);
setVisible(true);
+
+ PlayerInfo::setBuySellState(BUYSELL_SELLING);
}
SellDialog::~SellDialog()
@@ -118,6 +120,9 @@ SellDialog::~SellDialog()
delete mShopItems;
instances.remove(this);
+
+ if (PlayerInfo::getBuySellState() == BUYSELL_SELLING)
+ PlayerInfo::setBuySellState(BUYSELL_NONE);
}
void SellDialog::reset()
@@ -197,6 +202,11 @@ void SellDialog::action(const gcn::ActionEvent &event)
// the inventory index of the next Duplicate otherwise.
itemIndex = item->getCurrentInvIndex();
sellCount = item->sellCurrentDuplicate(mAmountItems);
+
+ // For Manaserv, the Item id is to be given as index.
+ if ((Net::getNetworkType() == ServerInfo::MANASERV))
+ itemIndex = item->getId();
+
Net::getNpcHandler()->sellItem(mNpcId, itemIndex, sellCount);
mAmountItems -= sellCount;
}
diff --git a/src/gui/sell.h b/src/gui/sell.h
index 32a4dc55..c286dcc2 100644
--- a/src/gui/sell.h
+++ b/src/gui/sell.h
@@ -86,11 +86,6 @@ class SellDialog : public Window, gcn::ActionListener, gcn::SelectionListener
void setVisible(bool visible);
/**
- * Returns true if any instances exist.
- */
- static bool isActive() { return instances.size() > 0; }
-
- /**
* Closes all instances.
*/
static void closeAll();
diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp
index 0762b00f..115b582c 100644
--- a/src/gui/serverdialog.cpp
+++ b/src/gui/serverdialog.cpp
@@ -21,6 +21,7 @@
#include "gui/serverdialog.h"
+#include "chatlog.h"
#include "client.h"
#include "configuration.h"
#include "gui.h"
@@ -29,7 +30,6 @@
#include "gui/okdialog.h"
#include "gui/sdlinput.h"
-#include "gui/theme.h"
#include "gui/widgets/button.h"
#include "gui/widgets/dropdown.h"
@@ -41,10 +41,11 @@
#include "net/net.h"
+#include "resources/theme.h"
+
#include "utils/gettext.h"
#include "utils/stringutils.h"
#include "utils/xml.h"
-#include "widgets/dropdown.h"
#include <guichan/font.hpp>
@@ -347,6 +348,8 @@ void ServerDialog::action(const gcn::ActionEvent &event)
// Save the selected server
mServerInfo->save = true;
+ chatLogger->setServerName(mServerInfo->hostname);
+
saveCustomServers(*mServerInfo);
Client::setState(STATE_CONNECT_SERVER);
@@ -482,10 +485,10 @@ void ServerDialog::setFieldsReadOnly(bool readOnly)
void ServerDialog::downloadServerList()
{
// Try to load the configuration value for the onlineServerList
- std::string listFile = branding.getValue("onlineServerList", std::string());
+ std::string listFile = branding.getStringValue("onlineServerList");
if (listFile.empty())
- listFile = config.getValue("onlineServerList", std::string());
+ listFile = config.getStringValue("onlineServerList");
// Fall back to manasource.org when neither branding nor config set it
if (listFile.empty())
diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp
index 2c6b89e8..8e9f5e98 100644
--- a/src/gui/setup_audio.cpp
+++ b/src/gui/setup_audio.cpp
@@ -35,10 +35,10 @@
#include "utils/gettext.h"
Setup_Audio::Setup_Audio():
- mMusicVolume((int)config.getValue("musicVolume", 60)),
- mSfxVolume((int)config.getValue("sfxVolume", 100)),
- mSoundEnabled(config.getValue("sound", 0)),
- mDownloadEnabled(config.getValue("download-music", false)),
+ mMusicVolume(config.getIntValue("musicVolume")),
+ mSfxVolume(config.getIntValue("sfxVolume")),
+ mSoundEnabled(config.getBoolValue("sound")),
+ mDownloadEnabled(config.getBoolValue("download-music")),
mSoundCheckBox(new CheckBox(_("Sound"), mSoundEnabled)),
mDownloadMusicCheckBox(new CheckBox(_("Download music"), mDownloadEnabled)),
mSfxSlider(new Slider(0, sound.getMaxVolume())),
@@ -82,14 +82,14 @@ void Setup_Audio::apply()
{
mSoundEnabled = mSoundCheckBox->isSelected();
mDownloadEnabled = mDownloadMusicCheckBox->isSelected();
- mSfxVolume = (int) config.getValue("sfxVolume", 100);
- mMusicVolume = (int) config.getValue("musicVolume", 60);
+ mSfxVolume = config.getIntValue("sfxVolume");
+ mMusicVolume = config.getIntValue("musicVolume");
config.setValue("sound", mSoundEnabled);
// Display a message if user has selected to download music,
// And if downloadmusic is not already enabled
- if (mDownloadEnabled && !config.getValue("download-music", false))
+ if (mDownloadEnabled && !config.getBoolValue("download-music"))
{
new OkDialog(_("Notice"),_("You may have to restart your client if you want to download new music"));
}
diff --git a/src/gui/setup_colors.cpp b/src/gui/setup_colors.cpp
index 12dba82a..6b3b3fec 100644
--- a/src/gui/setup_colors.cpp
+++ b/src/gui/setup_colors.cpp
@@ -23,8 +23,6 @@
#include "configuration.h"
#include "gui/gui.h"
-#include "gui/theme.h"
-#include "gui/userpalette.h"
#include "gui/widgets/browserbox.h"
#include "gui/widgets/itemlinkhandler.h"
@@ -36,6 +34,9 @@
#include "gui/widgets/textfield.h"
#include "gui/widgets/textpreview.h"
+#include "resources/theme.h"
+#include "resources/userpalette.h"
+
#include "utils/gettext.h"
#include "utils/stringutils.h"
diff --git a/src/gui/setup_joystick.cpp b/src/gui/setup_joystick.cpp
index 965f5712..7ac5b5ed 100644
--- a/src/gui/setup_joystick.cpp
+++ b/src/gui/setup_joystick.cpp
@@ -40,7 +40,7 @@ Setup_Joystick::Setup_Joystick():
{
setName(_("Joystick"));
- mOriginalJoystickEnabled = !config.getValue("joystickEnabled", false);
+ mOriginalJoystickEnabled = !config.getBoolValue("joystickEnabled");
mJoystickEnabled->setSelected(mOriginalJoystickEnabled);
mJoystickEnabled->addActionListener(this);
diff --git a/src/gui/setup_players.cpp b/src/gui/setup_players.cpp
index 802a5b2e..cbe0e264 100644
--- a/src/gui/setup_players.cpp
+++ b/src/gui/setup_players.cpp
@@ -21,7 +21,7 @@
#include "gui/setup_players.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
#include "configuration.h"
#include "log.h"
@@ -214,6 +214,7 @@ public:
#define ACTION_STRATEGY "strategy"
#define ACTION_WHISPER_TAB "whisper tab"
#define ACTION_SHOW_GENDER "show gender"
+#define ACTION_ENABLE_CHAT_LOG "enable log"
Setup_Players::Setup_Players():
mPlayerTableTitleModel(new StaticTableModel(1, COLUMNS_NR)),
@@ -226,10 +227,12 @@ Setup_Players::Setup_Players():
mDefaultWhisper(new CheckBox(_("Allow whispers"),
player_relations.getDefault() & PlayerRelation::WHISPER)),
mDeleteButton(new Button(_("Delete"), ACTION_DELETE, this)),
- mWhisperTab(config.getValue("whispertab", false)),
+ mWhisperTab(config.getBoolValue("whispertab")),
mWhisperTabCheckBox(new CheckBox(_("Put all whispers in tabs"), mWhisperTab)),
- mShowGender(config.getValue("showgender", false)),
- mShowGenderCheckBox(new CheckBox(_("Show gender"), mShowGender))
+ mShowGender(config.getBoolValue("showgender")),
+ mShowGenderCheckBox(new CheckBox(_("Show gender"), mShowGender)),
+ mEnableChatLog(config.getBoolValue("enableChatLog")),
+ mEnableChatLogCheckBox(new CheckBox(_("Enable Chat log"), mEnableChatLog))
{
setName(_("Players"));
@@ -279,6 +282,9 @@ Setup_Players::Setup_Players():
mShowGenderCheckBox->setActionEventId(ACTION_SHOW_GENDER);
mShowGenderCheckBox->addActionListener(this);
+ mEnableChatLogCheckBox->setActionEventId(ACTION_ENABLE_CHAT_LOG);
+ mEnableChatLogCheckBox->addActionListener(this);
+
reset();
// Do the layout
@@ -289,6 +295,7 @@ Setup_Players::Setup_Players():
place(0, 1, mPlayerScrollArea, 4, 4).setPadding(2);
place(0, 5, mDeleteButton);
place(0, 6, mShowGenderCheckBox, 2).setPadding(2);
+ place(0, 7, mEnableChatLogCheckBox, 2).setPadding(2);
place(2, 5, ignore_action_label);
place(2, 6, mIgnoreActionChoicesBox, 2).setPadding(2);
place(2, 7, mDefaultTrading);
@@ -341,20 +348,24 @@ void Setup_Players::apply()
PlayerRelation::WHISPER : 0));
config.setValue("whispertab", mWhisperTab);
- bool showGender = config.getValue("showgender", false);
+ bool showGender = config.getBoolValue("showgender");
config.setValue("showgender", mShowGender);
- if (beingManager && mShowGender != showGender)
- beingManager->updatePlayerNames();
+ if (actorSpriteManager && mShowGender != showGender)
+ actorSpriteManager->updatePlayerNames();
+
+ config.setValue("enableChatLog", mEnableChatLog);
}
void Setup_Players::cancel()
{
- mWhisperTab = config.getValue("whispertab", false);
+ mWhisperTab = config.getBoolValue("whispertab");
mWhisperTabCheckBox->setSelected(mWhisperTab);
- mShowGender = config.getValue("showgender", false);
+ mShowGender = config.getBoolValue("showgender");
mShowGenderCheckBox->setSelected(mShowGender);
+ mEnableChatLog = config.getBoolValue("enableChatLog");
+ mEnableChatLogCheckBox->setSelected(mEnableChatLog);
}
void Setup_Players::action(const gcn::ActionEvent &event)
@@ -402,6 +413,10 @@ void Setup_Players::action(const gcn::ActionEvent &event)
{
mShowGender = mShowGenderCheckBox->isSelected();
}
+ else if (event.getId() == ACTION_ENABLE_CHAT_LOG)
+ {
+ mEnableChatLog = mEnableChatLogCheckBox->isSelected();
+ }
}
void Setup_Players::updatedPlayer(const std::string &name)
diff --git a/src/gui/setup_players.h b/src/gui/setup_players.h
index 5337b213..a62ffe1f 100644
--- a/src/gui/setup_players.h
+++ b/src/gui/setup_players.h
@@ -70,6 +70,9 @@ private:
bool mShowGender;
gcn::CheckBox *mShowGenderCheckBox;
+
+ bool mEnableChatLog;
+ gcn::CheckBox *mEnableChatLogCheckBox;
};
#endif
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index 81ce8107..bbfae738 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -171,7 +171,7 @@ static const char *speechModeToString(Being::Speech mode)
const char *Setup_Video::overlayDetailToString(int detail)
{
if (detail == -1)
- detail = config.getValue("OverlayDetail", -1);
+ detail = config.getIntValue("OverlayDetail");
switch (detail)
{
@@ -185,7 +185,7 @@ const char *Setup_Video::overlayDetailToString(int detail)
const char *Setup_Video::particleDetailToString(int detail)
{
if (detail == -1)
- detail = 3 - config.getValue("particleEmitterSkip", -1);
+ detail = 3 - config.getIntValue("particleEmitterSkip");
switch (detail)
{
@@ -198,21 +198,19 @@ const char *Setup_Video::particleDetailToString(int detail)
}
Setup_Video::Setup_Video():
- mFullScreenEnabled(config.getValue("screen", false)),
- mOpenGLEnabled(config.getValue("opengl", false)),
- mCustomCursorEnabled(config.getValue("customcursor", true)),
- mShowMonsterDamageEnabled(config.getValue("showMonstersTakedDamage",
- false)),
- mVisibleNamesEnabled(config.getValue("visiblenames", true)),
- mParticleEffectsEnabled(config.getValue("particleeffects", true)),
- mNameEnabled(config.getValue("showownname", false)),
- mNPCLogEnabled(config.getValue("logNpcInGui", true)),
- mPickupChatEnabled(config.getValue("showpickupchat", true)),
- mPickupParticleEnabled(config.getValue("showpickupparticle", false)),
- mOpacity(config.getValue("guialpha", 0.8)),
- mFps((int) config.getValue("fpslimit", 60)),
- mSpeechMode(static_cast<Being::Speech>(
- config.getValue("speech", Being::TEXT_OVERHEAD))),
+ mFullScreenEnabled(config.getBoolValue("screen")),
+ mOpenGLEnabled(config.getBoolValue("opengl")),
+ mCustomCursorEnabled(config.getBoolValue("customcursor")),
+ mShowMonsterDamageEnabled(config.getBoolValue("showMonstersTakedDamage")),
+ mVisibleNamesEnabled(config.getBoolValue("visiblenames")),
+ mParticleEffectsEnabled(config.getBoolValue("particleeffects")),
+ mNameEnabled(config.getBoolValue("showownname")),
+ mNPCLogEnabled(config.getBoolValue("logNpcInGui")),
+ mPickupChatEnabled(config.getBoolValue("showpickupchat")),
+ mPickupParticleEnabled(config.getBoolValue("showpickupparticle")),
+ mOpacity(config.getFloatValue("guialpha")),
+ mFps(config.getIntValue("fpslimit")),
+ mSpeechMode(static_cast<Being::Speech>(config.getIntValue("speech"))),
mModeListModel(new ModeListModel),
mModeList(new ListBox(mModeListModel)),
mFsCheckBox(new CheckBox(_("Full screen"), mFullScreenEnabled)),
@@ -237,13 +235,13 @@ Setup_Video::Setup_Video():
mFpsCheckBox(new CheckBox(_("FPS limit:"))),
mFpsSlider(new Slider(10, 120)),
mFpsLabel(new Label),
- mOverlayDetail((int) config.getValue("OverlayDetail", 2)),
+ mOverlayDetail(config.getIntValue("OverlayDetail")),
mOverlayDetailSlider(new Slider(0, 2)),
mOverlayDetailField(new Label),
- mParticleDetail(3 - (int) config.getValue("particleEmitterSkip", 1)),
+ mParticleDetail(3 - config.getIntValue("particleEmitterSkip")),
mParticleDetailSlider(new Slider(0, 3)),
mParticleDetailField(new Label),
- mFontSize((int) config.getValue("fontSize", 11))
+ mFontSize(config.getIntValue("fontSize"))
{
setName(_("Video"));
@@ -388,7 +386,7 @@ void Setup_Video::apply()
{
// Full screen changes
bool fullscreen = mFsCheckBox->isSelected();
- if (fullscreen != (config.getValue("screen", false) == 1))
+ if (fullscreen != config.getBoolValue("screen"))
{
/* The OpenGL test is only necessary on Windows, since switching
* to/from full screen works fine on Linux. On Windows we'd have to
@@ -399,7 +397,7 @@ void Setup_Video::apply()
#if defined(WIN32) || defined(__APPLE__)
// checks for opengl usage
- if (!(config.getValue("opengl", false) == 1))
+ if (!config.getBoolValue("opengl"))
{
#endif
if (!graphics->setFullscreen(fullscreen))
@@ -452,20 +450,20 @@ void Setup_Video::apply()
config.setValue("fontSize", mFontSizeDropDown->getSelected() + 10);
// We sync old and new values at apply time
- mFullScreenEnabled = config.getValue("screen", false);
- mCustomCursorEnabled = config.getValue("customcursor", true);
- mShowMonsterDamageEnabled = config.getValue("showMonstersTakedDamage", false);
- mVisibleNamesEnabled = config.getValue("visiblenames", true);
- mParticleEffectsEnabled = config.getValue("particleeffects", true);
- mNameEnabled = config.getValue("showownname", false);
- mNPCLogEnabled = config.getValue("logNpcInGui", true);
+ mFullScreenEnabled = config.getBoolValue("screen");
+ mCustomCursorEnabled = config.getBoolValue("customcursor");
+ mShowMonsterDamageEnabled = config.getBoolValue("showMonstersTakedDamage");
+ mVisibleNamesEnabled = config.getBoolValue("visiblenames");
+ mParticleEffectsEnabled = config.getBoolValue("particleeffects");
+ mNameEnabled = config.getBoolValue("showownname");
+ mNPCLogEnabled = config.getBoolValue("logNpcInGui");
mSpeechMode = static_cast<Being::Speech>(
- config.getValue("speech", Being::TEXT_OVERHEAD));
- mOpacity = config.getValue("guialpha", 0.8);
- mOverlayDetail = (int) config.getValue("OverlayDetail", 2);
- mOpenGLEnabled = config.getValue("opengl", false);
- mPickupChatEnabled = config.getValue("showpickupchat", true);
- mPickupParticleEnabled = config.getValue("showpickupparticle", false);
+ config.getIntValue("speech"));
+ mOpacity = config.getFloatValue("guialpha");
+ mOverlayDetail = config.getIntValue("OverlayDetail");
+ mOpenGLEnabled = config.getBoolValue("opengl");
+ mPickupChatEnabled = config.getBoolValue("showpickupchat");
+ mPickupParticleEnabled = config.getBoolValue("showpickupparticle");
}
void Setup_Video::cancel()
diff --git a/src/gui/skilldialog.cpp b/src/gui/skilldialog.cpp
index 53528cee..168553f6 100644
--- a/src/gui/skilldialog.cpp
+++ b/src/gui/skilldialog.cpp
@@ -21,11 +21,11 @@
#include "gui/skilldialog.h"
-#include "localplayer.h"
#include "log.h"
+#include "playerinfo.h"
+#include "configuration.h"
#include "gui/setup.h"
-#include "gui/theme.h"
#include "gui/widgets/button.h"
#include "gui/widgets/container.h"
@@ -43,6 +43,7 @@
#include "resources/image.h"
#include "resources/resourcemanager.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
#include "utils/gettext.h"
@@ -87,7 +88,8 @@ struct SkillInfo
}
else
{
- icon = Theme::getImageFromTheme("unknown-item.png");
+ icon = Theme::getImageFromTheme(
+ paths.getStringValue("unknownItemFile"));
}
}
@@ -240,10 +242,6 @@ void SkillDialog::action(const gcn::ActionEvent &event)
{
setVisible(false);
}
- else
- {
- printf("Unknown event '%s'\n", event.getId().c_str());
- }
}
std::string SkillDialog::update(int id)
@@ -263,7 +261,7 @@ std::string SkillDialog::update(int id)
void SkillDialog::update()
{
mPointsLabel->setCaption(strprintf(_("Skill points available: %d"),
- player_node->getSkillPoints()));
+ PlayerInfo::getAttribute(SKILL_POINTS)));
mPointsLabel->adjustSize();
for (SkillMap::iterator it = mSkills.begin(); it != mSkills.end(); it++)
@@ -414,10 +412,10 @@ void SkillModel::updateVisibilities()
void SkillInfo::update()
{
- int baseLevel = player_node->getAttributeBase(id);
- int effLevel = player_node->getAttributeEffective(id);
+ int baseLevel = PlayerInfo::getStatBase(id);
+ int effLevel = PlayerInfo::getStatEffective(id);
- std::pair<int, int> exp = player_node->getExperience(id);
+ std::pair<int, int> exp = PlayerInfo::getStatExperience(id);
if (!modifiable && baseLevel == 0 && effLevel == 0 && exp.second == 0)
{
diff --git a/src/gui/skilldialog.h b/src/gui/skilldialog.h
index 95f8ef25..764f9d51 100644
--- a/src/gui/skilldialog.h
+++ b/src/gui/skilldialog.h
@@ -19,8 +19,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SKILL_H
-#define SKILL_H
+#ifndef SKILLDIALOG_H
+#define SKILLDIALOG_H
#include "guichanfwd.h"
diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp
index 098ecbc5..88cd5732 100644
--- a/src/gui/socialwindow.cpp
+++ b/src/gui/socialwindow.cpp
@@ -20,22 +20,19 @@
#include "gui/socialwindow.h"
-#include "beingmanager.h"
+#include "event.h"
#include "guild.h"
#include "localplayer.h"
#include "party.h"
-#include "player.h"
#include "gui/confirmdialog.h"
#include "gui/okdialog.h"
#include "gui/setup.h"
#include "gui/textdialog.h"
-#include "gui/theme.h"
#include "gui/widgets/avatarlistbox.h"
#include "gui/widgets/browserbox.h"
#include "gui/widgets/button.h"
-#include "gui/widgets/chattab.h"
#include "gui/widgets/container.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layouthelper.h"
@@ -49,6 +46,8 @@
#include "net/guildhandler.h"
#include "net/partyhandler.h"
+#include "resources/theme.h"
+
#include "utils/dtor.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
@@ -123,10 +122,9 @@ public:
std::string name = mInviteDialog->getText();
Net::getGuildHandler()->invite(mGuild->getId(), name);
- localChatTab->chatLog(strprintf(_("Invited user %s to guild %s."),
+ SERVER_NOTICE(strprintf(_("Invited user %s to guild %s."),
name.c_str(),
- mGuild->getName().c_str()),
- BY_SERVER);
+ mGuild->getName().c_str()))
mInviteDialog = NULL;
}
else if (event.getId() == "~do invite")
@@ -136,8 +134,8 @@ public:
else if (event.getId() == "yes")
{
Net::getGuildHandler()->leave(mGuild->getId());
- localChatTab->chatLog(strprintf(_("Guild %s quit requested."),
- mGuild->getName().c_str()), BY_SERVER);
+ SERVER_NOTICE(strprintf(_("Guild %s quit requested."),
+ mGuild->getName().c_str()))
mConfirmDialog = NULL;
}
else if (event.getId() == "~yes")
@@ -204,8 +202,8 @@ public:
std::string name = mInviteDialog->getText();
Net::getPartyHandler()->invite(name);
- localChatTab->chatLog(strprintf(_("Invited user %s to party."),
- name.c_str()), BY_SERVER);
+ SERVER_NOTICE(strprintf(_("Invited user %s to party."),
+ name.c_str()))
mInviteDialog = NULL;
}
else if (event.getId() == "~do invite")
@@ -215,8 +213,8 @@ public:
else if (event.getId() == "yes")
{
Net::getPartyHandler()->leave();
- localChatTab->chatLog(strprintf(_("Party %s quit requested."),
- mParty->getName().c_str()), BY_SERVER);
+ SERVER_NOTICE(strprintf(_("Party %s quit requested."),
+ mParty->getName().c_str()))
mConfirmDialog = NULL;
}
else if (event.getId() == "~yes")
@@ -440,14 +438,14 @@ void SocialWindow::action(const gcn::ActionEvent &event)
// check if they accepted the invite
if (eventId == "yes")
{
- localChatTab->chatLog(strprintf(_("Accepted party invite from %s."),
- mPartyInviter.c_str()));
+ SERVER_NOTICE(strprintf(_("Accepted party invite from %s."),
+ mPartyInviter.c_str()))
Net::getPartyHandler()->inviteResponse(mPartyInviter, true);
}
else if (eventId == "no")
{
- localChatTab->chatLog(strprintf(_("Rejected party invite from %s."),
- mPartyInviter.c_str()));
+ SERVER_NOTICE(strprintf(_("Rejected party invite from %s."),
+ mPartyInviter.c_str()))
Net::getPartyHandler()->inviteResponse(mPartyInviter, false);
}
@@ -459,14 +457,14 @@ void SocialWindow::action(const gcn::ActionEvent &event)
// check if they accepted the invite
if (eventId == "yes")
{
- localChatTab->chatLog(strprintf(_("Accepted guild invite from %s."),
- mPartyInviter.c_str()));
+ SERVER_NOTICE(strprintf(_("Accepted guild invite from %s."),
+ mPartyInviter.c_str()))
Net::getGuildHandler()->inviteResponse(mGuildInvited, true);
}
else if (eventId == "no")
{
- localChatTab->chatLog(strprintf(_("Rejected guild invite from %s."),
- mPartyInviter.c_str()));
+ SERVER_NOTICE(strprintf(_("Rejected guild invite from %s."),
+ mPartyInviter.c_str()))
Net::getGuildHandler()->inviteResponse(mGuildInvited, false);
}
@@ -499,8 +497,8 @@ void SocialWindow::action(const gcn::ActionEvent &event)
}
Net::getGuildHandler()->create(name);
- localChatTab->chatLog(strprintf(_("Creating guild called %s."),
- name.c_str()), BY_SERVER);
+ SERVER_NOTICE(strprintf(_("Creating guild called %s."),
+ name.c_str()))
mGuildCreateDialog = NULL;
}
@@ -519,8 +517,8 @@ void SocialWindow::action(const gcn::ActionEvent &event)
}
Net::getPartyHandler()->create(name);
- localChatTab->chatLog(strprintf(_("Creating party called %s."),
- name.c_str()), BY_SERVER);
+ SERVER_NOTICE(strprintf(_("Creating party called %s."),
+ name.c_str()));
mPartyCreateDialog = NULL;
}
@@ -545,14 +543,14 @@ void SocialWindow::showGuildInvite(const std::string &guildName,
// check there isnt already an invite showing
if (mGuildInvited != 0)
{
- localChatTab->chatLog(_("Received guild request, but one already "
- "exists."), BY_SERVER);
+ SERVER_NOTICE(_("Received guild request, but one already "
+ "exists."))
return;
}
std::string msg = strprintf(_("%s has invited you to join the guild %s."),
inviterName.c_str(), guildName.c_str());
- localChatTab->chatLog(msg, BY_SERVER);
+ SERVER_NOTICE(msg)
// show invite
mGuildAcceptDialog = new ConfirmDialog(_("Accept Guild Invite"), msg, this);
@@ -567,8 +565,7 @@ void SocialWindow::showPartyInvite(const std::string &partyName,
// check there isnt already an invite showing
if (mPartyInviter != "")
{
- localChatTab->chatLog(_("Received party request, but one already "
- "exists."), BY_SERVER);
+ SERVER_NOTICE(_("Received party request, but one already exists."))
return;
}
@@ -599,7 +596,7 @@ void SocialWindow::showPartyInvite(const std::string &partyName,
}
}
- localChatTab->chatLog(msg, BY_SERVER);
+ SERVER_NOTICE(msg)
// show invite
mPartyAcceptDialog = new ConfirmDialog(_("Accept Party Invite"), msg, this);
diff --git a/src/gui/specialswindow.cpp b/src/gui/specialswindow.cpp
index 44551825..b511e4a3 100644
--- a/src/gui/specialswindow.cpp
+++ b/src/gui/specialswindow.cpp
@@ -20,11 +20,9 @@
#include "gui/specialswindow.h"
-#include "localplayer.h"
#include "log.h"
#include "gui/setup.h"
-#include "gui/theme.h"
#include "gui/widgets/button.h"
#include "gui/widgets/container.h"
@@ -42,6 +40,9 @@
#include "net/net.h"
#include "net/specialhandler.h"
+#include "resources/specialdb.h"
+#include "resources/theme.h"
+
#include "utils/dtor.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
@@ -54,31 +55,24 @@
class SpecialEntry;
-struct SpecialInfo
-{
- unsigned short id;
- std::string name;
- std::string icon;
- SpecialEntry *display;
-};
class SpecialEntry : public Container
{
public:
SpecialEntry(SpecialInfo *info);
- void update();
+ void update(int current, int needed);
protected:
friend class SpecialsWindow;
SpecialInfo *mInfo;
private:
- Icon *mIcon;
- Label *mNameLabel;
- Label *mLevelLabel;
- Label *mTechLabel;
- Button *mUse;
+ Icon *mIcon; // icon to display
+ Label *mNameLabel; // name to display
+ Label *mLevelLabel; // level number label (only shown when applicable)
+ Button *mUse; // use button (only shown when applicable)
+ ProgressBar *mRechargeBar; // recharge bar (only shown when applicable)
};
SpecialsWindow::SpecialsWindow():
@@ -102,7 +96,6 @@ SpecialsWindow::SpecialsWindow():
SpecialsWindow::~SpecialsWindow()
{
// Clear gui
- loadSpecials("");
}
void SpecialsWindow::action(const gcn::ActionEvent &event)
@@ -127,91 +120,70 @@ void SpecialsWindow::action(const gcn::ActionEvent &event)
}
}
-std::string SpecialsWindow::update(int id)
-{
- // TODO
-
- return std::string();
-}
-
-void SpecialsWindow::loadSpecials(const std::string &file)
+void SpecialsWindow::draw(gcn::Graphics *graphics)
{
- // TODO: mTabs->clear();
- while (mTabs->getSelectedTabIndex() != -1)
+ // update the progress bars
+ std::map<int, Special> specialData = PlayerInfo::getSpecialStatus();
+ bool foundNew = false;
+ unsigned int found = 0; // number of entries in specialData which match mEntries
+
+ for (std::map<int, Special>::iterator i = specialData.begin();
+ i != specialData.end();
+ i++)
{
- mTabs->removeTabWithIndex(mTabs->getSelectedTabIndex());
- }
-
- for (SpecialMap::iterator it = mSpecials.begin(); it != mSpecials.end(); it++)
- {
- delete (*it).second->display;
+ std::map<int, SpecialEntry *>::iterator e = mEntries.find(i->first);
+ if (e == mEntries.end())
+ {
+ // found a new special - abort update and rebuild from scratch
+ foundNew = true;
+ break;
+ } else {
+ // update progress bar of special
+ e->second->update(i->second.currentMana, i->second.neededMana);
+ found++;
+ }
}
- delete_all(mSpecials);
- mSpecials.clear();
+ // a rebuild is needed when a) the number of specials changed or b) an existing entry isn't found anymore
+ if (foundNew || found != mEntries.size()) rebuild(specialData);
- if (file.length() == 0)
- return;
+ Window::draw(graphics);
+}
- XML::Document doc(file);
- xmlNodePtr root = doc.rootNode();
+void SpecialsWindow::rebuild(const std::map<int, Special> &specialData)
+{
+ make_dtor(mEntries);
+ mEntries.clear();
+ int vPos = 0; //vertical position of next placed element
- if (!root || !xmlStrEqual(root->name, BAD_CAST "specials"))
+ for (std::map<int, Special>::const_iterator i = specialData.begin();
+ i != specialData.end();
+ i++)
{
- logger->log("Error loading specials file: %s", file.c_str());
- return;
- }
-
- int setCount = 0;
- std::string setName;
- ScrollArea *scroll;
- FlowContainer *container;
+ logger->log("Updating special GUI for %d", i->first);
- for_each_xml_child_node(set, root)
- {
- if (xmlStrEqual(set->name, BAD_CAST "set"))
+ SpecialInfo* info = SpecialDB::get(i->first);
+ if (info)
{
- setCount++;
- setName = XML::getProperty(set, "name", strprintf(_("Specials Set %d"), setCount));
-
- container = new FlowContainer(SPECIALS_WIDTH, SPECIALS_HEIGHT);
- container->setOpaque(false);
- scroll = new ScrollArea(container);
- scroll->setOpaque(false);
- scroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
- scroll->setVerticalScrollPolicy(ScrollArea::SHOW_ALWAYS);
-
- mTabs->addTab(setName, scroll);
- for_each_xml_child_node(node, set)
- {
- if (xmlStrEqual(node->name, BAD_CAST "special"))
- {
- int id = atoi(XML::getProperty(node, "id", "-1").c_str());
- if (id == -1)
- continue;
- std::string name = XML::getProperty(node, "name", strprintf(_("Special %d"), id));
- std::string icon = XML::getProperty(node, "icon", "");
-
- SpecialInfo *special = new SpecialInfo;
- special->id = id;
- special->name = name;
- special->icon = icon;
- special->display = new SpecialEntry(special);
-
- container->add(special->display);
-
- mSpecials[id] = special;
- }
- }
+ info->rechargeCurrent = i->second.currentMana;
+ info->rechargeNeeded = i->second.neededMana;
+ SpecialEntry* entry = new SpecialEntry(info);
+ entry->setPosition(0, vPos);
+ vPos += entry->getHeight();
+ add(entry);
+ mEntries[i->first] = entry;
+ } else {
+ logger->log("Warning: No info available of special %d", i->first);
}
}
}
+
SpecialEntry::SpecialEntry(SpecialInfo *info) :
mInfo(info),
mIcon(NULL),
- mNameLabel(new Label(info->name)),
- mLevelLabel(new Label("999")),
- mUse(new Button("Use", "use", specialsWindow))
+ mLevelLabel(NULL),
+ mUse(NULL),
+ mRechargeBar(NULL)
{
setFrameSize(1);
setOpaque(false);
@@ -225,21 +197,42 @@ SpecialEntry::SpecialEntry(SpecialInfo *info) :
mIcon->setPosition(1, 0);
add(mIcon);
+
+ mNameLabel = new Label(info->name);
mNameLabel->setPosition(35, 0);
add(mNameLabel);
- mLevelLabel->setPosition(getWidth() - mLevelLabel->getWidth(), 0);
- add(mLevelLabel);
+ if (info->hasLevel)
+ {
+ mLevelLabel = new Label(toString(info->level));
+ mLevelLabel->setPosition(getWidth() - mLevelLabel->getWidth(), 0);
+ add(mLevelLabel);
+ }
+
- mNameLabel->setWidth(mLevelLabel->getX() - mNameLabel->getX() - 1);
+ if (info->isActive)
+ {
+ mUse = new Button("Use", "use", specialsWindow);
+ mUse->setPosition(getWidth() - mUse->getWidth(), 13);
+ add(mUse);
+ }
- mUse->setPosition(getWidth() - mUse->getWidth(), 13);
- add(mUse);
+ if (info->hasRechargeBar)
+ {
+ float progress = (float)info->rechargeCurrent / (float)info->rechargeNeeded;
+ mRechargeBar = new ProgressBar(progress, 100, 10, Theme::PROG_MP);
+ mRechargeBar->setSmoothProgress(false);
+ mRechargeBar->setPosition(0, 13);
+ add(mRechargeBar);
+ }
- update();
}
-void SpecialEntry::update()
+void SpecialEntry::update(int current, int needed)
{
- // TODO
+ if (mRechargeBar)
+ {
+ float progress = (float)current / (float)needed;
+ mRechargeBar->setProgress(progress);
+ }
}
diff --git a/src/gui/specialswindow.h b/src/gui/specialswindow.h
index 81384856..85abe3a4 100644
--- a/src/gui/specialswindow.h
+++ b/src/gui/specialswindow.h
@@ -25,6 +25,8 @@
#include "guichanfwd.h"
+#include "playerinfo.h"
+
#include "gui/widgets/window.h"
#include <guichan/actionlistener.hpp>
@@ -36,7 +38,7 @@ class ScrollArea;
class Tab;
class TabbedArea;
-struct SpecialInfo;
+struct SpecialEntry;
class SpecialsWindow : public Window, public gcn::ActionListener {
public:
@@ -49,20 +51,14 @@ class SpecialsWindow : public Window, public gcn::ActionListener {
*/
void action(const gcn::ActionEvent &actionEvent);
- /**
- * Update the given special's display
- */
- std::string update(int id);
-
- void loadSpecials(const std::string &file);
-
- bool hasSpecials() { return !mSpecials.empty(); }
+ void draw(gcn::Graphics *graphics);
private:
- std::vector<gcn::Button *> mSpellButtons;
- typedef std::map<int, SpecialInfo*> SpecialMap;
- SpecialMap mSpecials;
+ // (re)constructs the list of specials
+ void rebuild(const std::map<int, Special> &specialData);
+
TabbedArea *mTabs;
+ std::map<int, SpecialEntry *> mEntries;
};
extern SpecialsWindow *specialsWindow;
diff --git a/src/gui/speechbubble.cpp b/src/gui/speechbubble.cpp
index 08d00038..e0a9f8a0 100644
--- a/src/gui/speechbubble.cpp
+++ b/src/gui/speechbubble.cpp
@@ -25,10 +25,12 @@
#include "graphics.h"
#include "gui/gui.h"
-#include "gui/theme.h"
+#include "gui/widgets/label.h"
#include "gui/widgets/textbox.h"
+#include "resources/theme.h"
+
#include <guichan/font.hpp>
#include <guichan/widgets/label.hpp>
@@ -40,7 +42,7 @@ SpeechBubble::SpeechBubble():
setMinWidth(29);
setMinHeight(29);
- mCaption = new gcn::Label;
+ mCaption = new Label;
mCaption->setFont(boldFont);
mSpeechBox = new TextBox;
diff --git a/src/gui/speechbubble.h b/src/gui/speechbubble.h
index 8682ab7e..6017398a 100644
--- a/src/gui/speechbubble.h
+++ b/src/gui/speechbubble.h
@@ -23,10 +23,10 @@
#ifndef SPEECHBUBBLE_H
#define SPEECHBUBBLE_H
-#include "gui/theme.h"
-
#include "gui/widgets/popup.h"
+#include "resources/theme.h"
+
class TextBox;
class SpeechBubble : public Popup
diff --git a/src/gui/statuswindow.cpp b/src/gui/statuswindow.cpp
index ede85133..493f5ee6 100644
--- a/src/gui/statuswindow.cpp
+++ b/src/gui/statuswindow.cpp
@@ -22,11 +22,10 @@
#include "gui/statuswindow.h"
#include "localplayer.h"
+#include "playerinfo.h"
#include "units.h"
-#include "gui/ministatus.h"
#include "gui/setup.h"
-#include "gui/theme.h"
#include "gui/widgets/button.h"
#include "gui/widgets/label.h"
@@ -38,6 +37,9 @@
#include "net/net.h"
#include "net/playerhandler.h"
+#include "net/gamehandler.h"
+
+#include "resources/theme.h"
#include "utils/gettext.h"
#include "utils/mathutils.h"
@@ -94,6 +96,8 @@ class ChangeDisplay : public AttrDisplay, gcn::ActionListener
StatusWindow::StatusWindow():
Window(player_node->getName())
{
+ listen("Attributes");
+
setWindowName("Status");
setupWindow->registerWindowForReset(this);
setResizable(true);
@@ -109,21 +113,25 @@ StatusWindow::StatusWindow():
mLvlLabel = new Label(strprintf(_("Level: %d"), 0));
mMoneyLabel = new Label(strprintf(_("Money: %s"), ""));
- int max = player_node->getMaxHp();
+ int max = PlayerInfo::getAttribute(MAX_HP);
mHpLabel = new Label(_("HP:"));
- mHpBar = new ProgressBar(max ? (float) player_node->getHp() / max: 0,
+ mHpBar = new ProgressBar(max ? (float) PlayerInfo::getAttribute(HP) / max: 0,
80, 15, Theme::PROG_HP);
- max = player_node->getExpNeeded();
+ max = PlayerInfo::getAttribute(EXP_NEEDED);
mXpLabel = new Label(_("Exp:"));
- mXpBar = new ProgressBar(max ? (float) player_node->getExp() / max : 0,
+ mXpBar = new ProgressBar(max ? (float) PlayerInfo::getAttribute(EXP) / max : 0,
80, 15, Theme::PROG_EXP);
- max = player_node->getMaxMP();
- mMpLabel = new Label(_("MP:"));
- mMpBar = new ProgressBar(max ? (float) player_node->getMaxMP() / max : 0,
+ bool magicBar = Net::getGameHandler()->canUseMagicBar();
+ if (magicBar)
+ {
+ max = PlayerInfo::getAttribute(MAX_MP);
+ mMpLabel = new Label(_("MP:"));
+ mMpBar = new ProgressBar(max ? (float) PlayerInfo::getAttribute(MAX_MP) / max : 0,
80, 15, Net::getPlayerHandler()->canUseMagic() ?
Theme::PROG_MP : Theme::PROG_NO_MP);
+ }
place(0, 0, mLvlLabel, 3);
// 5, 0 Job Level
@@ -132,9 +140,12 @@ StatusWindow::StatusWindow():
place(1, 1, mHpBar, 4);
place(5, 1, mXpLabel).setPadding(3);
place(6, 1, mXpBar, 5);
- place(0, 2, mMpLabel).setPadding(3);
- // 5, 2 and 6, 2 Job Progress Bar
- place(1, 2, mMpBar, 4);
+ if (magicBar)
+ {
+ place(0, 2, mMpLabel).setPadding(3);
+ // 5, 2 and 6, 2 Job Progress Bar
+ place(1, 2, mMpBar, 4);
+ }
if (Net::getPlayerHandler()->getJobLocation() > 0)
{
@@ -178,98 +189,101 @@ StatusWindow::StatusWindow():
loadWindowState();
- update(HP);
- update(MP);
- update(EXP);
- update(MONEY);
- update(CHAR_POINTS); // This also updates all attributes (none atm)
- update(LEVEL);
- int job = Net::getPlayerHandler()->getJobLocation();
- if (job > 0)
- {
- update(job);
- }
-}
-
-std::string StatusWindow::update(int id)
-{
- if (miniStatusWindow)
- miniStatusWindow->update(id);
-
- if (id == HP)
- {
- updateHPBar(mHpBar, true);
-
- return _("HP");
- }
- else if (id == MP)
- {
+ // Update bars
+ updateHPBar(mHpBar, true);
+ if (magicBar)
updateMPBar(mMpBar, true);
+ updateXPBar(mXpBar, false);
- return _("MP");
- }
- else if (id == EXP)
- {
- updateXPBar(mXpBar, false);
- return _("Exp");
- }
- else if (id == MONEY)
- {
- int money = player_node->getMoney();
- mMoneyLabel->setCaption(strprintf(_("Money: %s"),
- Units::formatCurrency(money).c_str()));
- mMoneyLabel->adjustSize();
-
- return _("Money");
- }
- else if (id == Net::getPlayerHandler()->getJobLocation())
- {
- mJobLvlLabel->setCaption(strprintf(_("Job: %d"),
- player_node->getAttributeBase(id)));
- mJobLvlLabel->adjustSize();
+ mMoneyLabel->setCaption(strprintf(_("Money: %s"),
+ Units::formatCurrency(PlayerInfo::getAttribute(MONEY)).c_str()));
+ mMoneyLabel->adjustSize();
+ mCharacterPointsLabel->setCaption(strprintf(_("Character points: %d"),
+ PlayerInfo::getAttribute(CHAR_POINTS)));
+ mCharacterPointsLabel->adjustSize();
- updateProgressBar(mJobBar, id, false);
+ mLvlLabel->setCaption(strprintf(_("Level: %d"),
+ PlayerInfo::getAttribute(LEVEL)));
+ mLvlLabel->adjustSize();
+}
- return _("Job");
- }
- else if (id == CHAR_POINTS)
+void StatusWindow::event(const std::string &channel, const Mana::Event &event)
+{
+ if (event.getName() == "UpdateAttribute")
{
- mCharacterPointsLabel->setCaption(strprintf(_("Character points: %d"),
- player_node->getCharacterPoints()));
- mCharacterPointsLabel->adjustSize();
-
- if (Net::getPlayerHandler()->canCorrectAttributes())
- {
- mCorrectionPointsLabel->setCaption(strprintf(_("Correction points: %d"),
- player_node->getCorrectionPoints()));
- mCorrectionPointsLabel->adjustSize();
- }
-
- for (Attrs::iterator it = mAttrs.begin(); it != mAttrs.end(); it++)
+ switch(event.getInt("id"))
{
- it->second->update();
+ case HP: case MAX_HP:
+ updateHPBar(mHpBar, true);
+ break;
+
+ case MP: case MAX_MP:
+ updateMPBar(mMpBar, true);
+ break;
+
+ case EXP: case EXP_NEEDED:
+ updateXPBar(mXpBar, false);
+ break;
+
+ case MONEY:
+ mMoneyLabel->setCaption(strprintf(_("Money: %s"),
+ Units::formatCurrency(
+ event.getInt("newValue")).c_str()));
+ mMoneyLabel->adjustSize();
+ break;
+
+ case CHAR_POINTS:
+ mCharacterPointsLabel->setCaption(strprintf(
+ _("Character points: %d"),
+ event.getInt("newValue")));
+ mCharacterPointsLabel->adjustSize();
+ // Update all attributes
+ for (Attrs::iterator it = mAttrs.begin();
+ it != mAttrs.end(); it++)
+ it->second->update();
+ break;
+
+ case CORR_POINTS:
+ mCorrectionPointsLabel->setCaption(strprintf(
+ _("Correction points: %d"),
+ event.getInt("newValue")));
+ mCorrectionPointsLabel->adjustSize();
+ // Update all attributes
+ for (Attrs::iterator it = mAttrs.begin();
+ it != mAttrs.end(); it++)
+ it->second->update();
+ break;
+
+ case LEVEL:
+ mLvlLabel->setCaption(strprintf(_("Level: %d"),
+ event.getInt("newValue")));
+ mLvlLabel->adjustSize();
+ break;
}
}
- else if (id == LEVEL)
+ else if (event.getName() == "UpdateStat")
{
- mLvlLabel->setCaption(strprintf(_("Level: %d"),
- player_node->getLevel()));
- mLvlLabel->adjustSize();
+ int id = event.getInt("id");
- return _("Level");
- }
- else
- {
- Attrs::iterator it = mAttrs.find(id);
+ if (id == Net::getPlayerHandler()->getJobLocation())
+ {
+
+ mJobLvlLabel->setCaption(strprintf(_("Job: %d"),
+ PlayerInfo::getStatBase(id)));
+ mJobLvlLabel->adjustSize();
- if (it != mAttrs.end())
+ updateProgressBar(mJobBar, id, false);
+ }
+ else
{
- return it->second->update();
+ Attrs::iterator it = mAttrs.find(id);
+ if (it != mAttrs.end())
+ {
+ it->second->update();
+ }
}
}
-
- return "";
}
void StatusWindow::setPointsNeeded(int id, int needed)
@@ -306,32 +320,37 @@ void StatusWindow::addAttribute(int id, const std::string &name,
void StatusWindow::updateHPBar(ProgressBar *bar, bool showMax)
{
+ if (!bar)
+ return;
if (showMax)
- bar->setText(toString(player_node->getHp()) +
- "/" + toString(player_node->getMaxHp()));
+ bar->setText(toString(PlayerInfo::getAttribute(HP)) +
+ "/" + toString(PlayerInfo::getAttribute(MAX_HP)));
else
- bar->setText(toString(player_node->getHp()));
+ bar->setText(toString(PlayerInfo::getAttribute(HP)));
float prog = 1.0;
- if (player_node->getMaxHp() > 0)
- prog = (float) player_node->getHp() / player_node->getMaxHp();
+ if (PlayerInfo::getAttribute(MAX_HP) > 0)
+ prog = (float) PlayerInfo::getAttribute(HP) / PlayerInfo::getAttribute(MAX_HP);
bar->setProgress(prog);
}
void StatusWindow::updateMPBar(ProgressBar *bar, bool showMax)
{
+ if (!bar)
+ return;
+
if (showMax)
- bar->setText(toString(player_node->getMP()) +
- "/" + toString(player_node->getMaxMP()));
+ bar->setText(toString(PlayerInfo::getAttribute(MP)) +
+ "/" + toString(PlayerInfo::getAttribute(MAX_MP)));
else
- bar->setText(toString(player_node->getMP()));
+ bar->setText(toString(PlayerInfo::getAttribute(MP)));
float prog = 1.0f;
- if (player_node->getMaxMP() > 0)
- prog = (float) player_node->getMP() / player_node->getMaxMP();
+ if (PlayerInfo::getAttribute(MAX_MP) > 0)
+ prog = (float) PlayerInfo::getAttribute(MP) / PlayerInfo::getAttribute(MAX_MP);
if (Net::getPlayerHandler()->canUseMagic())
bar->setProgressPalette(Theme::PROG_MP);
@@ -344,6 +363,9 @@ void StatusWindow::updateMPBar(ProgressBar *bar, bool showMax)
void StatusWindow::updateProgressBar(ProgressBar *bar, int value, int max,
bool percent)
{
+ if (!bar)
+ return;
+
if (max == 0)
{
bar->setText(_("Max"));
@@ -364,13 +386,16 @@ void StatusWindow::updateProgressBar(ProgressBar *bar, int value, int max,
void StatusWindow::updateXPBar(ProgressBar *bar, bool percent)
{
- updateProgressBar(bar, player_node->getExp(),
- player_node->getExpNeeded(), percent);
+ if (!bar)
+ return;
+
+ updateProgressBar(bar, PlayerInfo::getAttribute(EXP),
+ PlayerInfo::getAttribute(EXP_NEEDED), percent);
}
void StatusWindow::updateProgressBar(ProgressBar *bar, int id, bool percent)
{
- std::pair<int, int> exp = player_node->getExperience(id);
+ std::pair<int, int> exp = PlayerInfo::getStatExperience(id);
updateProgressBar(bar, exp.first, exp.second, percent);
}
@@ -395,8 +420,8 @@ AttrDisplay::~AttrDisplay()
std::string AttrDisplay::update()
{
- int base = player_node->getAttributeBase(mId);
- int bonus = player_node->getAttributeEffective(mId) - base;
+ int base = PlayerInfo::getStatBase(mId);
+ int bonus = PlayerInfo::getStatMod(mId);
std::string value = toString(base);
if (bonus)
value += strprintf(" (%+d)", bonus);
@@ -460,9 +485,9 @@ std::string ChangeDisplay::update()
if (mDec)
{
- mDec->setEnabled(player_node->getCorrectionPoints());
+ mDec->setEnabled(PlayerInfo::getAttribute(CORR_POINTS));
}
- mInc->setEnabled(player_node->getCharacterPoints() >= mNeeded &&
+ mInc->setEnabled(PlayerInfo::getAttribute(CHAR_POINTS) >= mNeeded &&
mNeeded > 0);
return AttrDisplay::update();
@@ -480,24 +505,25 @@ void ChangeDisplay::action(const gcn::ActionEvent &event)
if (Net::getPlayerHandler()->canCorrectAttributes() &&
event.getSource() == mDec)
{
- int newcorpoints = player_node->getCorrectionPoints() - 1;
- player_node->setCorrectionPoints(newcorpoints);
- int newpoints = player_node->getCharacterPoints() + 1;
- player_node->setCharacterPoints(newpoints);
- int newbase = player_node->getAttributeBase(mId) - 1;
- player_node->setAttributeBase(mId, newbase);
- int newmod = player_node->getAttributeEffective(mId) - 1;
- player_node->setAttributeEffective(mId, newmod);
+ int newcorpoints = PlayerInfo::getAttribute(CORR_POINTS) - 1;
+ PlayerInfo::setAttribute(CORR_POINTS, newcorpoints);
+
+ int newpoints = PlayerInfo::getAttribute(CHAR_POINTS) + 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, newpoints);
+
+ int newbase = PlayerInfo::getStatBase(mId) - 1;
+ PlayerInfo::setStatBase(mId, newbase);
+
Net::getPlayerHandler()->decreaseAttribute(mId);
}
else if (event.getSource() == mInc)
{
- int newpoints = player_node->getCharacterPoints() - 1;
- player_node->setCharacterPoints(newpoints);
- int newbase = player_node->getAttributeBase(mId) + 1;
- player_node->setAttributeBase(mId, newbase);
- int newmod = player_node->getAttributeEffective(mId) + 1;
- player_node->setAttributeEffective(mId, newmod);
+ int newpoints = PlayerInfo::getAttribute(CHAR_POINTS) - 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, newpoints);
+
+ int newbase = PlayerInfo::getStatBase(mId) + 1;
+ PlayerInfo::setStatBase(mId, newbase);
+
Net::getPlayerHandler()->increaseAttribute(mId);
}
}
diff --git a/src/gui/statuswindow.h b/src/gui/statuswindow.h
index a1fc4b4b..5be09b6a 100644
--- a/src/gui/statuswindow.h
+++ b/src/gui/statuswindow.h
@@ -23,6 +23,7 @@
#define STATUS_H
#include "guichanfwd.h"
+#include "listener.h"
#include "gui/widgets/window.h"
@@ -40,24 +41,15 @@ class VertContainer;
*
* \ingroup Interface
*/
-class StatusWindow : public Window
+class StatusWindow : public Window, public Mana::Listener
{
public:
- enum { // Some update constants
- HP = -1,
- MP = -2,
- EXP = -3,
- MONEY = -4,
- CHAR_POINTS = -5,
- LEVEL = -6
- };
-
/**
* Constructor.
*/
StatusWindow();
- std::string update(int id);
+ void event(const std::string &channel, const Mana::Event &event);
void setPointsNeeded(int id, int needed);
diff --git a/src/gui/textpopup.cpp b/src/gui/textpopup.cpp
index 6aeae319..d0a0c495 100644
--- a/src/gui/textpopup.cpp
+++ b/src/gui/textpopup.cpp
@@ -26,6 +26,8 @@
#include "gui/gui.h"
#include "gui/palette.h"
+#include "gui/widgets/label.h"
+
#include "graphics.h"
#include "units.h"
@@ -40,10 +42,10 @@ TextPopup::TextPopup():
{
const int fontHeight = getFont()->getHeight();
- mText1 = new gcn::Label;
+ mText1 = new Label;
mText1->setPosition(getPadding(), getPadding());
- mText2 = new gcn::Label;
+ mText2 = new Label;
mText2->setPosition(getPadding(), fontHeight + getPadding());
add(mText1);
diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp
index dcb38e8e..bfb61c33 100644
--- a/src/gui/trade.cpp
+++ b/src/gui/trade.cpp
@@ -21,9 +21,11 @@
#include "gui/trade.h"
+#include "event.h"
#include "inventory.h"
#include "item.h"
#include "localplayer.h"
+#include "playerinfo.h"
#include "units.h"
#include "gui/inventorywindow.h"
@@ -31,7 +33,6 @@
#include "gui/setup.h"
#include "gui/widgets/button.h"
-#include "gui/widgets/chattab.h"
#include "gui/widgets/itemcontainer.h"
#include "gui/widgets/label.h"
#include "gui/widgets/scrollarea.h"
@@ -59,7 +60,7 @@ TradeWindow::TradeWindow():
mMyInventory(new Inventory(Inventory::TRADE)),
mPartnerInventory(new Inventory(Inventory::TRADE)),
mStatus(PROPOSING)
-{
+{
setWindowName("Trade");
setResizable(true);
setCloseButton(true);
@@ -96,7 +97,7 @@ TradeWindow::TradeWindow():
mMoneyLabel = new Label(strprintf(_("You get %s"), ""));
gcn::Label *mMoneyLabel2 = new Label(_("You give:"));
-
+
mMoneyField = new TextField;
mMoneyField->setWidth(40);
mMoneyChangeButton = new Button(_("Change"), "money", this);
@@ -270,9 +271,8 @@ void TradeWindow::action(const gcn::ActionEvent &event)
if (mMyInventory->contains(item))
{
- localChatTab->chatLog(_("Failed adding item. You can not "
- "overlap one kind of item on the window."),
- BY_SERVER);
+ SERVER_NOTICE(_("Failed adding item. You can not "
+ "overlap one kind of item on the window."))
return;
}
@@ -285,7 +285,7 @@ void TradeWindow::action(const gcn::ActionEvent &event)
{
setVisible(false);
reset();
- player_node->setTrading(false);
+ PlayerInfo::setTrading(false);
Net::getTradeHandler()->cancel();
}
@@ -310,11 +310,10 @@ void TradeWindow::action(const gcn::ActionEvent &event)
return;
int v = atoi(mMoneyField->getText().c_str());
- int curMoney = player_node->getMoney();
+ int curMoney = PlayerInfo::getAttribute(MONEY);
if (v > curMoney)
{
- localChatTab->chatLog(_("You don't have enough money."),
- BY_SERVER);
+ SERVER_NOTICE(_("You don't have enough money."))
v = curMoney;
}
Net::getTradeHandler()->setMoney(v);
diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp
index 7448a102..23d23b5e 100644
--- a/src/gui/updatewindow.cpp
+++ b/src/gui/updatewindow.cpp
@@ -476,7 +476,7 @@ void UpdaterWindow::logic()
// This statement checks to see if the file type is music, and if download-music is true
// If it fails, this statement returns true, and results in not downloading the file
// Else it will ignore the break, and download the file.
- if ( !(thisFile.type == "music" && config.getValue("download-music", false)) )
+ if ( !(thisFile.type == "music" && config.getBoolValue("download-music")) )
{
mUpdateIndex++;
break;
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index 99325db8..f63fe5c6 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -21,16 +21,14 @@
#include "gui/viewport.h"
+#include "actorspritemanager.h"
#include "client.h"
-#include "beingmanager.h"
#include "configuration.h"
-#include "flooritemmanager.h"
#include "graphics.h"
#include "keyboardconfig.h"
#include "localplayer.h"
#include "map.h"
-#include "monster.h"
-#include "npc.h"
+#include "playerinfo.h"
#include "textmanager.h"
#include "gui/gui.h"
@@ -40,7 +38,6 @@
#include "net/net.h"
-#include "resources/monsterinfo.h"
#include "resources/resourcemanager.h"
#include "utils/stringutils.h"
@@ -62,10 +59,10 @@ Viewport::Viewport():
setOpaque(false);
addMouseListener(this);
- mScrollLaziness = (int) config.getValue("ScrollLaziness", 16);
- mScrollRadius = (int) config.getValue("ScrollRadius", 0);
- mScrollCenterOffsetX = (int) config.getValue("ScrollCenterOffsetX", 0);
- mScrollCenterOffsetY = (int) config.getValue("ScrollCenterOffsetY", 0);
+ mScrollLaziness = config.getIntValue("ScrollLaziness");
+ mScrollRadius = config.getIntValue("ScrollRadius");
+ mScrollCenterOffsetX = config.getIntValue("ScrollCenterOffsetX");
+ mScrollCenterOffsetY = config.getIntValue("ScrollCenterOffsetY");
config.addListener("ScrollLaziness", this);
config.addListener("ScrollRadius", this);
@@ -207,12 +204,16 @@ void Viewport::draw(gcn::Graphics *gcnGraphics)
}
// Draw player names, speech, and emotion sprite as needed
- const Beings &beings = beingManager->getAll();
- for (Beings::const_iterator i = beings.begin(), i_end = beings.end();
- i != i_end; ++i)
+ const ActorSprites &actors = actorSpriteManager->getAll();
+ for (ActorSpritesConstIterator it = actors.begin(), it_end = actors.end();
+ it != it_end; it++)
{
- (*i)->drawSpeech((int) mPixelViewX, (int) mPixelViewY);
- (*i)->drawEmotion(graphics, (int) mPixelViewX, (int) mPixelViewY);
+ if ((*it)->getType() == ActorSprite::FLOOR_ITEM)
+ continue;
+
+ Being *b = static_cast<Being*>(*it);
+ b->drawSpeech((int) mPixelViewX, (int) mPixelViewY);
+ b->drawEmotion(graphics, (int) mPixelViewX, (int) mPixelViewY);
}
if (miniStatusWindow)
@@ -345,7 +346,7 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
return;
// Check if we are busy
- if (NPC::isTalking())
+ if (PlayerInfo::isTalking())
return;
mPlayerFollowMouse = false;
@@ -381,33 +382,20 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
// Interact with some being
if (mHoverBeing)
{
- switch (mHoverBeing->getType())
+ if (mHoverBeing->canTalk())
+ mHoverBeing->talkTo();
+ else
{
- // Talk to NPCs
- case Being::NPC:
- static_cast<NPC*>(mHoverBeing)->talk();
- break;
-
- // Attack or walk to monsters or players
- case Being::MONSTER:
- case Being::PLAYER:
- // Ignore it if its dead
- if (!mHoverBeing->isAlive())
- break;
-
+ // Ignore it if its dead
+ if (mHoverBeing->isAlive())
+ {
if (player_node->withinAttackRange(mHoverBeing) ||
keyboard.isKeyActive(keyboard.KEY_ATTACK))
- {
player_node->attack(mHoverBeing,
!keyboard.isKeyActive(keyboard.KEY_TARGET));
- }
else
- {
player_node->setGotoTarget(mHoverBeing);
- }
- break;
- default:
- break;
+ }
}
// Picks up a item if we clicked on one
}
@@ -433,8 +421,8 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
else if (event.getButton() == gcn::MouseEvent::MIDDLE)
{
// Find the being nearest to the clicked position
- Being *target = beingManager->findNearestLivingBeing(
- pixelX, pixelY, 20, Being::MONSTER);
+ Being *target = actorSpriteManager->findNearestLivingBeing(
+ pixelX, pixelY, 20, ActorSprite::MONSTER);
if (target)
player_node->setTarget(target);
@@ -460,9 +448,9 @@ void Viewport::mouseDragged(gcn::MouseEvent &event)
}
else
{
- if (mLocalWalkTime != player_node->getWalkTime())
+ if (mLocalWalkTime != player_node->getActionTime())
{
- mLocalWalkTime = player_node->getWalkTime();
+ mLocalWalkTime = player_node->getActionTime();
int destX = (event.getX() + mPixelViewX + 16) /
mMap->getTileWidth();
int destY = (event.getY() + mPixelViewY + 16) /
@@ -494,8 +482,8 @@ void Viewport::closePopupMenu()
void Viewport::optionChanged(const std::string &name)
{
- mScrollLaziness = (int) config.getValue("ScrollLaziness", 32);
- mScrollRadius = (int) config.getValue("ScrollRadius", 32);
+ mScrollLaziness = config.getIntValue("ScrollLaziness");
+ mScrollRadius = config.getIntValue("ScrollRadius");
}
void Viewport::mouseMoved(gcn::MouseEvent &event)
@@ -507,27 +495,28 @@ void Viewport::mouseMoved(gcn::MouseEvent &event)
const int x = (event.getX() + (int) mPixelViewX);
const int y = (event.getY() + (int) mPixelViewY);
- mHoverBeing = beingManager->findBeingByPixel(x, y);
- if (mHoverBeing && mHoverBeing->getType() == Being::PLAYER)
- mBeingPopup->show(getMouseX(), getMouseY(),
- static_cast<Player*>(mHoverBeing));
- else
- mBeingPopup->setVisible(false);
+ if (mHoverBeing)
+ mHoverBeing->removeActorSpriteListener(this);
+ mHoverBeing = actorSpriteManager->findBeingByPixel(x, y);
+ mBeingPopup->show(getMouseX(), getMouseY(), mHoverBeing);
- mHoverItem = floorItemManager->findByCoordinates(x / mMap->getTileWidth(),
- y / mMap->getTileHeight());
+ if (mHoverItem)
+ mHoverItem->removeActorSpriteListener(this);
+ mHoverItem = actorSpriteManager->findItem(x / mMap->getTileWidth(),
+ y / mMap->getTileHeight());
if (mHoverBeing)
{
+ mHoverBeing->addActorSpriteListener(this);
switch (mHoverBeing->getType())
{
// NPCs
- case Being::NPC:
+ case ActorSprite::NPC:
gui->setCursorType(Gui::CURSOR_TALK);
break;
// Monsters
- case Being::MONSTER:
+ case ActorSprite::MONSTER:
gui->setCursorType(Gui::CURSOR_FIGHT);
break;
default:
@@ -538,6 +527,7 @@ void Viewport::mouseMoved(gcn::MouseEvent &event)
}
else if (mHoverItem)
{
+ mHoverItem->addActorSpriteListener(this);
gui->setCursorType(Gui::CURSOR_PICKUP);
}
else
@@ -549,7 +539,7 @@ void Viewport::mouseMoved(gcn::MouseEvent &event)
void Viewport::toggleDebugPath()
{
mShowDebugPath++;
- if (mShowDebugPath > Map::MAP_SPECIAL)
+ if (mShowDebugPath > Map::MAP_SPECIAL3)
mShowDebugPath = Map::MAP_NORMAL;
if (mMap)
{
@@ -562,8 +552,11 @@ void Viewport::hideBeingPopup()
mBeingPopup->setVisible(false);
}
-void Viewport::clearHoverBeing(Being *being)
+void Viewport::actorSpriteDestroyed(const ActorSprite &actorSprite)
{
- if (mHoverBeing == being)
+ if (&actorSprite == mHoverBeing)
mHoverBeing = 0;
+
+ if (&actorSprite == mHoverItem)
+ mHoverItem = 0;
}
diff --git a/src/gui/viewport.h b/src/gui/viewport.h
index 9658f934..eaf23085 100644
--- a/src/gui/viewport.h
+++ b/src/gui/viewport.h
@@ -22,7 +22,8 @@
#ifndef VIEWPORT_H
#define VIEWPORT_H
-#include "beingmanager.h"
+#include "actorspritelistener.h"
+#include "actorspritemanager.h"
#include "configlistener.h"
#include "position.h"
@@ -30,6 +31,7 @@
#include <guichan/mouselistener.hpp>
+class ActorSprite;
class Being;
class BeingPopup;
class FloorItem;
@@ -52,7 +54,7 @@ const int walkingMouseDelay = 500;
* coordinates.
*/
class Viewport : public WindowContainer, public gcn::MouseListener,
- public ConfigListener
+ public ConfigListener, public ActorSpriteListener
{
public:
/**
@@ -158,11 +160,7 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
*/
void hideBeingPopup();
- protected:
- friend class BeingManager;
-
- /// Clears the hovered being if it matches
- void clearHoverBeing(Being *being);
+ void actorSpriteDestroyed(const ActorSprite &actorSprite);
private:
/**
diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp
index 6ec4d1e8..6551aa04 100644
--- a/src/gui/widgets/avatarlistbox.cpp
+++ b/src/gui/widgets/avatarlistbox.cpp
@@ -25,10 +25,10 @@
#include "gui/chat.h"
#include "gui/gui.h"
#include "gui/palette.h"
-#include "gui/theme.h"
#include "resources/image.h"
#include "resources/resourcemanager.h"
+#include "resources/theme.h"
#include "utils/stringutils.h"
diff --git a/src/gui/widgets/browserbox.cpp b/src/gui/widgets/browserbox.cpp
index d43afed7..d890f138 100644
--- a/src/gui/widgets/browserbox.cpp
+++ b/src/gui/widgets/browserbox.cpp
@@ -21,10 +21,10 @@
#include "gui/widgets/browserbox.h"
-#include "gui/theme.h"
-
#include "gui/widgets/linkhandler.h"
+#include "resources/theme.h"
+
#include <guichan/graphics.hpp>
#include <guichan/font.hpp>
#include <guichan/cliprectangle.hpp>
diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp
index 26e0ad90..3d3a07c2 100644
--- a/src/gui/widgets/button.cpp
+++ b/src/gui/widgets/button.cpp
@@ -25,9 +25,9 @@
#include "graphics.h"
#include "gui/palette.h"
-#include "gui/theme.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
@@ -125,8 +125,8 @@ Button::~Button()
void Button::updateAlpha()
{
- float alpha = std::max(config.getValue("guialpha", 0.8f),
- (double) Theme::instance()->getMinimumOpacity());
+ float alpha = std::max(config.getFloatValue("guialpha"),
+ Theme::instance()->getMinimumOpacity());
if (mAlpha != alpha)
{
diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/chattab.cpp
index 39ea6887..fbde2c9c 100644
--- a/src/gui/widgets/chattab.cpp
+++ b/src/gui/widgets/chattab.cpp
@@ -21,6 +21,7 @@
#include "gui/widgets/chattab.h"
+#include "chatlog.h"
#include "commandhandler.h"
#include "configuration.h"
#include "localplayer.h"
@@ -50,7 +51,7 @@ ChatTab::ChatTab(const std::string &name) : Tab()
mTextOutput = new BrowserBox(BrowserBox::AUTO_WRAP);
mTextOutput->setOpaque(false);
- mTextOutput->setMaxRow((int) config.getValue("ChatLogLength", 0));
+ mTextOutput->setMaxRow((int) config.getIntValue("ChatLogLength"));
mTextOutput->setLinkHandler(chatWindow->mItemLinkHandler);
mScrollArea = new ScrollArea(mTextOutput);
@@ -71,7 +72,7 @@ ChatTab::~ChatTab()
delete mScrollArea;
}
-void ChatTab::chatLog(std::string line, int own, bool ignoreRecord)
+void ChatTab::chatLog(std::string line, Own own, bool ignoreRecord)
{
// Trim whitespace
trim(line);
@@ -180,6 +181,9 @@ void ChatTab::chatLog(std::string line, int own, bool ignoreRecord)
line = lineColor + timeStr.str() + tmp.nick + tmp.text;
+ if (config.getBoolValue("enableChatLog"))
+ saveToLogFile(line);
+
// We look if the Vertical Scroll Bar is set at the max before
// adding a row, otherwise the max will always be a row higher
// at comparison.
@@ -275,6 +279,12 @@ void ChatTab::handleCommand(const std::string &msg)
commandHandler->handleCommand(msg, this);
}
+void ChatTab::saveToLogFile(std::string &msg)
+{
+ if (chatLogger)
+ chatLogger->log(msg);
+}
+
void ChatTab::addRow(std::string &line)
{
std::string::size_type idx = 0;
diff --git a/src/gui/widgets/chattab.h b/src/gui/widgets/chattab.h
index 7fd3931e..f5682668 100644
--- a/src/gui/widgets/chattab.h
+++ b/src/gui/widgets/chattab.h
@@ -30,18 +30,6 @@ class BrowserBox;
class Recorder;
class ScrollArea;
-enum
-{
- BY_GM,
- BY_PLAYER,
- BY_OTHER,
- BY_SERVER,
- BY_CHANNEL,
- ACT_WHISPER, // getting whispered at
- ACT_IS, // equivalent to "/me" on IRC
- BY_LOGGER
-};
-
/**
* A tab for the chat window. This is special to ease chat handling.
*/
@@ -62,7 +50,8 @@ class ChatTab : public Tab
* @param channelName which channel to send the message to.
* @param ignoreRecord should this not be recorded?
*/
- void chatLog(std::string line, int own = BY_SERVER, bool ignoreRecord = false);
+ void chatLog(std::string line, Own own = BY_SERVER,
+ bool ignoreRecord = false);
/**
* Adds the text to the message list
@@ -111,6 +100,8 @@ class ChatTab : public Tab
const std::string &args)
{ return false; }
+ virtual void saveToLogFile(std::string &msg);
+
protected:
friend class ChatWindow;
friend class WhisperWindow;
diff --git a/src/gui/widgets/checkbox.cpp b/src/gui/widgets/checkbox.cpp
index f9002166..6a44132d 100644
--- a/src/gui/widgets/checkbox.cpp
+++ b/src/gui/widgets/checkbox.cpp
@@ -25,9 +25,9 @@
#include "graphics.h"
#include "gui/palette.h"
-#include "gui/theme.h"
#include "resources/image.h"
+#include "resources/theme.h"
int CheckBox::instances = 0;
float CheckBox::mAlpha = 1.0;
@@ -92,8 +92,8 @@ void CheckBox::draw(gcn::Graphics* graphics)
void CheckBox::updateAlpha()
{
- float alpha = std::max(config.getValue("guialpha", 0.8f),
- (double) Theme::instance()->getMinimumOpacity());
+ float alpha = std::max(config.getFloatValue("guialpha"),
+ Theme::instance()->getMinimumOpacity());
if (mAlpha != alpha)
{
diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp
index 6c3417e7..ced9c38b 100644
--- a/src/gui/widgets/dropdown.cpp
+++ b/src/gui/widgets/dropdown.cpp
@@ -26,12 +26,12 @@
#include "gui/palette.h"
#include "gui/sdlinput.h"
-#include "gui/theme.h"
#include "gui/widgets/listbox.h"
#include "gui/widgets/scrollarea.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
@@ -110,8 +110,8 @@ DropDown::~DropDown()
void DropDown::updateAlpha()
{
- float alpha = std::max(config.getValue("guialpha", 0.8f),
- (double) Theme::instance()->getMinimumOpacity());
+ float alpha = std::max(config.getFloatValue("guialpha"),
+ Theme::instance()->getMinimumOpacity());
if (mAlpha != alpha)
{
diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp
index 82fb9f8d..7a24c464 100644
--- a/src/gui/widgets/emoteshortcutcontainer.cpp
+++ b/src/gui/widgets/emoteshortcutcontainer.cpp
@@ -32,10 +32,10 @@
#include "log.h"
#include "gui/palette.h"
-#include "gui/theme.h"
#include "resources/emotedb.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
@@ -51,7 +51,7 @@ EmoteShortcutContainer::EmoteShortcutContainer():
mBackgroundImg = Theme::getImageFromTheme("item_shortcut_bgr.png");
- mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8));
+ mBackgroundImg->setAlpha(config.getFloatValue("guialpha"));
// Setup emote sprites
for (int i = 0; i <= EmoteDB::getLast(); i++)
@@ -72,9 +72,9 @@ EmoteShortcutContainer::~EmoteShortcutContainer()
void EmoteShortcutContainer::draw(gcn::Graphics *graphics)
{
- if (config.getValue("guialpha", 0.8) != mAlpha)
+ if (config.getFloatValue("guialpha") != mAlpha)
{
- mAlpha = config.getValue("guialpha", 0.8);
+ mAlpha = config.getFloatValue("guialpha");
mBackgroundImg->setAlpha(mAlpha);
}
diff --git a/src/gui/widgets/itemcontainer.cpp b/src/gui/widgets/itemcontainer.cpp
index 7648eb24..b98cac66 100644
--- a/src/gui/widgets/itemcontainer.cpp
+++ b/src/gui/widgets/itemcontainer.cpp
@@ -32,7 +32,6 @@
#include "gui/outfitwindow.h"
#include "gui/palette.h"
#include "gui/sdlinput.h"
-#include "gui/theme.h"
#include "gui/viewport.h"
#include "net/net.h"
@@ -40,6 +39,7 @@
#include "resources/image.h"
#include "resources/iteminfo.h"
+#include "resources/theme.h"
#include "utils/stringutils.h"
diff --git a/src/gui/widgets/itemshortcutcontainer.cpp b/src/gui/widgets/itemshortcutcontainer.cpp
index 83efd4d4..f2982de9 100644
--- a/src/gui/widgets/itemshortcutcontainer.cpp
+++ b/src/gui/widgets/itemshortcutcontainer.cpp
@@ -27,16 +27,16 @@
#include "item.h"
#include "itemshortcut.h"
#include "keyboardconfig.h"
-#include "localplayer.h"
+#include "playerinfo.h"
#include "gui/inventorywindow.h"
#include "gui/itempopup.h"
#include "gui/palette.h"
-#include "gui/theme.h"
#include "gui/viewport.h"
#include "resources/image.h"
#include "resources/iteminfo.h"
+#include "resources/theme.h"
#include "utils/stringutils.h"
@@ -53,7 +53,7 @@ ItemShortcutContainer::ItemShortcutContainer():
mBackgroundImg = Theme::getImageFromTheme("item_shortcut_bgr.png");
mMaxItems = itemShortcut->getItemCount();
- mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8));
+ mBackgroundImg->setAlpha(config.getFloatValue("guialpha"));
mBoxHeight = mBackgroundImg->getHeight();
mBoxWidth = mBackgroundImg->getWidth();
@@ -67,9 +67,9 @@ ItemShortcutContainer::~ItemShortcutContainer()
void ItemShortcutContainer::draw(gcn::Graphics *graphics)
{
- if (config.getValue("guialpha", 0.8) != mAlpha)
+ if (config.getFloatValue("guialpha") != mAlpha)
{
- mAlpha = config.getValue("guialpha", 0.8);
+ mAlpha = config.getFloatValue("guialpha");
mBackgroundImg->setAlpha(mAlpha);
}
@@ -94,7 +94,7 @@ void ItemShortcutContainer::draw(gcn::Graphics *graphics)
continue;
Item *item =
- player_node->getInventory()->findItem(itemShortcut->getItem(i));
+ PlayerInfo::getInventory()->findItem(itemShortcut->getItem(i));
if (item)
{
@@ -151,7 +151,7 @@ void ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event)
if (itemId < 0)
return;
- Item *item = player_node->getInventory()->findItem(itemId);
+ Item *item = PlayerInfo::getInventory()->findItem(itemId);
if (item)
{
@@ -187,7 +187,7 @@ void ItemShortcutContainer::mousePressed(gcn::MouseEvent &event)
}
else if (event.getButton() == gcn::MouseEvent::RIGHT)
{
- Item *item = player_node->getInventory()->
+ Item *item = PlayerInfo::getInventory()->
findItem(itemShortcut->getItem(index));
if (!item)
@@ -240,7 +240,7 @@ void ItemShortcutContainer::mouseMoved(gcn::MouseEvent &event)
if (itemId < 0)
return;
- Item *item = player_node->getInventory()->findItem(itemId);
+ Item *item = PlayerInfo::getInventory()->findItem(itemId);
if (item)
{
diff --git a/src/gui/widgets/label.cpp b/src/gui/widgets/label.cpp
index 4c607edf..939e9fc0 100644
--- a/src/gui/widgets/label.cpp
+++ b/src/gui/widgets/label.cpp
@@ -20,19 +20,20 @@
#include "gui/widgets/label.h"
-#include "gui/theme.h"
+#include "resources/theme.h"
Label::Label()
{
+ setForegroundColor(Theme::getThemeColor(Theme::TEXT));
}
Label::Label(const std::string &caption) :
gcn::Label(caption)
{
+ setForegroundColor(Theme::getThemeColor(Theme::TEXT));
}
void Label::draw(gcn::Graphics *graphics)
{
- setForegroundColor(Theme::getThemeColor(Theme::TEXT));
gcn::Label::draw(static_cast<gcn::Graphics*>(graphics));
}
diff --git a/src/gui/widgets/listbox.cpp b/src/gui/widgets/listbox.cpp
index ef591023..d79d8d0c 100644
--- a/src/gui/widgets/listbox.cpp
+++ b/src/gui/widgets/listbox.cpp
@@ -25,7 +25,8 @@
#include "gui/palette.h"
#include "gui/sdlinput.h"
-#include "gui/theme.h"
+
+#include "resources/theme.h"
#include <guichan/font.hpp>
#include <guichan/graphics.hpp>
@@ -45,8 +46,8 @@ ListBox::~ListBox()
void ListBox::updateAlpha()
{
- float alpha = std::max(config.getValue("guialpha", 0.8),
- (double) Theme::instance()->getMinimumOpacity());
+ float alpha = std::max(config.getFloatValue("guialpha"),
+ Theme::instance()->getMinimumOpacity());
if (mAlpha != alpha)
mAlpha = alpha;
diff --git a/src/gui/widgets/playerbox.cpp b/src/gui/widgets/playerbox.cpp
index 57cbec6f..559ac5a6 100644
--- a/src/gui/widgets/playerbox.cpp
+++ b/src/gui/widgets/playerbox.cpp
@@ -22,13 +22,12 @@
#include "gui/widgets/playerbox.h"
#include "animatedsprite.h"
+#include "being.h"
#include "configuration.h"
#include "graphics.h"
-#include "player.h"
-
-#include "gui/theme.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
@@ -36,8 +35,8 @@ int PlayerBox::instances = 0;
float PlayerBox::mAlpha = 1.0;
ImageRect PlayerBox::background;
-PlayerBox::PlayerBox(const Player *player):
- mPlayer(player)
+PlayerBox::PlayerBox(const Being *being):
+ mBeing(being)
{
setFrameSize(2);
@@ -57,7 +56,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));
+ background.grid[a]->setAlpha(config.getFloatValue("guialpha"));
a++;
}
}
@@ -72,7 +71,7 @@ PlayerBox::~PlayerBox()
{
instances--;
- mPlayer = 0;
+ mBeing = 0;
if (instances == 0)
{
@@ -82,20 +81,20 @@ PlayerBox::~PlayerBox()
void PlayerBox::draw(gcn::Graphics *graphics)
{
- if (mPlayer)
+ if (mBeing)
{
// Draw character
const int bs = getFrameSize();
- const int x = getWidth() / 2 + bs;
- const int y = getHeight() - bs;
- mPlayer->drawSpriteAt(static_cast<Graphics*>(graphics), x, y);
+ const int x = getWidth() / 2 + bs - 16;
+ const int y = getHeight() - bs - 32;
+ mBeing->drawSpriteAt(static_cast<Graphics*>(graphics), x, y);
}
- if (config.getValue("guialpha", 0.8) != mAlpha)
+ if (config.getFloatValue("guialpha") != mAlpha)
{
for (int a = 0; a < 9; a++)
{
- background.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
+ background.grid[a]->setAlpha(config.getFloatValue("guialpha"));
}
}
}
diff --git a/src/gui/widgets/playerbox.h b/src/gui/widgets/playerbox.h
index 33b4a628..4505367f 100644
--- a/src/gui/widgets/playerbox.h
+++ b/src/gui/widgets/playerbox.h
@@ -24,8 +24,8 @@
#include <guichan/widgets/scrollarea.hpp>
+class Being;
class ImageRect;
-class Player;
/**
* A box showing a player character.
@@ -39,7 +39,7 @@ class PlayerBox : public gcn::ScrollArea
* Constructor. Takes the initial player character that this box should
* display, which defaults to <code>NULL</code>.
*/
- PlayerBox(const Player *player = 0);
+ PlayerBox(const Being *being = 0);
/**
* Destructor.
@@ -51,7 +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 Being *being) { mBeing = being; }
/**
* Draws the scroll area.
@@ -64,7 +64,7 @@ class PlayerBox : public gcn::ScrollArea
void drawFrame(gcn::Graphics *graphics);
private:
- const Player *mPlayer; /**< The character used for display */
+ const Being *mBeing; /**< The character used for display */
static float mAlpha;
static int instances;
diff --git a/src/gui/widgets/popup.cpp b/src/gui/widgets/popup.cpp
index 4dc58f72..e242bcf4 100644
--- a/src/gui/widgets/popup.cpp
+++ b/src/gui/widgets/popup.cpp
@@ -26,12 +26,12 @@
#include "graphics.h"
#include "log.h"
-#include "gui/theme.h"
#include "gui/viewport.h"
#include "gui/widgets/windowcontainer.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include <guichan/exception.hpp>
diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp
index 028658ab..15838952 100644
--- a/src/gui/widgets/progressbar.cpp
+++ b/src/gui/widgets/progressbar.cpp
@@ -27,9 +27,9 @@
#include "gui/gui.h"
#include "gui/palette.h"
-#include "gui/theme.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
@@ -123,8 +123,8 @@ void ProgressBar::logic()
void ProgressBar::updateAlpha()
{
- float alpha = std::max(config.getValue("guialpha", 0.8),
- (double) Theme::instance()->getMinimumOpacity());
+ float alpha = std::max(config.getFloatValue("guialpha"),
+ Theme::instance()->getMinimumOpacity());
if (mAlpha != alpha)
{
diff --git a/src/gui/widgets/progressindicator.cpp b/src/gui/widgets/progressindicator.cpp
index 6bda617f..91b40751 100644
--- a/src/gui/widgets/progressindicator.cpp
+++ b/src/gui/widgets/progressindicator.cpp
@@ -23,11 +23,10 @@
#include "graphics.h"
#include "simpleanimation.h"
-#include "gui/theme.h"
-
#include "resources/animation.h"
#include "resources/imageset.h"
#include "resources/resourcemanager.h"
+#include "resources/theme.h"
#include <guichan/widgets/label.hpp>
diff --git a/src/gui/widgets/radiobutton.cpp b/src/gui/widgets/radiobutton.cpp
index 96797225..1296feb6 100644
--- a/src/gui/widgets/radiobutton.cpp
+++ b/src/gui/widgets/radiobutton.cpp
@@ -24,9 +24,8 @@
#include "configuration.h"
#include "graphics.h"
-#include "gui/theme.h"
-
#include "resources/image.h"
+#include "resources/theme.h"
int RadioButton::instances = 0;
float RadioButton::mAlpha = 1.0;
@@ -78,9 +77,9 @@ RadioButton::~RadioButton()
void RadioButton::drawBox(gcn::Graphics* graphics)
{
- if (config.getValue("guialpha", 0.8) != mAlpha)
+ if (config.getFloatValue("guialpha") != mAlpha)
{
- mAlpha = config.getValue("guialpha", 0.8);
+ mAlpha = config.getFloatValue("guialpha");
radioNormal->setAlpha(mAlpha);
radioChecked->setAlpha(mAlpha);
radioDisabled->setAlpha(mAlpha);
diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp
index f0c3691c..7850643f 100644
--- a/src/gui/widgets/resizegrip.cpp
+++ b/src/gui/widgets/resizegrip.cpp
@@ -24,9 +24,8 @@
#include "configuration.h"
#include "graphics.h"
-#include "gui/theme.h"
-
#include "resources/image.h"
+#include "resources/theme.h"
#include <guichan/graphics.hpp>
@@ -59,9 +58,9 @@ ResizeGrip::~ResizeGrip()
void ResizeGrip::draw(gcn::Graphics *graphics)
{
- if (config.getValue("guialpha", 0.8) != mAlpha)
+ if (config.getFloatValue("guialpha") != mAlpha)
{
- mAlpha = config.getValue("guialpha", 0.8);
+ mAlpha = config.getFloatValue("guialpha");
gripImage->setAlpha(mAlpha);
}
diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp
index 0c7f4d7d..7d42883a 100644
--- a/src/gui/widgets/scrollarea.cpp
+++ b/src/gui/widgets/scrollarea.cpp
@@ -24,9 +24,8 @@
#include "configuration.h"
#include "graphics.h"
-#include "gui/theme.h"
-
#include "resources/image.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
@@ -108,7 +107,7 @@ void ScrollArea::init()
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));
+ background.grid[a]->setAlpha(config.getFloatValue("guialpha"));
a++;
}
}
@@ -135,8 +134,8 @@ void ScrollArea::init()
vsgridx[x], vsgridy[y],
vsgridx[x + 1] - vsgridx[x],
vsgridy[y + 1] - vsgridy[y]);
- vMarker.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
- vMarkerHi.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
+ vMarker.grid[a]->setAlpha(config.getFloatValue("guialpha"));
+ vMarkerHi.grid[a]->setAlpha(config.getFloatValue("guialpha"));
a++;
}
}
@@ -213,8 +212,8 @@ void ScrollArea::logic()
void ScrollArea::updateAlpha()
{
- float alpha = std::max(config.getValue("guialpha", 0.8),
- (double) Theme::instance()->getMinimumOpacity());
+ float alpha = std::max(config.getFloatValue("guialpha"),
+ Theme::instance()->getMinimumOpacity());
if (alpha != mAlpha)
{
diff --git a/src/gui/widgets/shoplistbox.cpp b/src/gui/widgets/shoplistbox.cpp
index 2f5fab34..c0a79500 100644
--- a/src/gui/widgets/shoplistbox.cpp
+++ b/src/gui/widgets/shoplistbox.cpp
@@ -26,12 +26,12 @@
#include "shopitem.h"
#include "gui/itempopup.h"
-#include "gui/theme.h"
#include "gui/viewport.h"
#include "gui/widgets/shopitems.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include <guichan/font.hpp>
#include <guichan/listmodel.hpp>
@@ -71,8 +71,8 @@ void ShopListBox::draw(gcn::Graphics *gcnGraphics)
if (!mListModel)
return;
- if (config.getValue("guialpha", 0.8) != mAlpha)
- mAlpha = config.getValue("guialpha", 0.8);
+ if (config.getFloatValue("guialpha") != mAlpha)
+ mAlpha = config.getFloatValue("guialpha");
int alpha = (int)(mAlpha * 255.0f);
const gcn::Color* highlightColor =
diff --git a/src/gui/widgets/slider.cpp b/src/gui/widgets/slider.cpp
index 6a9a5c7c..c044d55d 100644
--- a/src/gui/widgets/slider.cpp
+++ b/src/gui/widgets/slider.cpp
@@ -24,9 +24,8 @@
#include "configuration.h"
#include "graphics.h"
-#include "gui/theme.h"
-
#include "resources/image.h"
+#include "resources/theme.h"
Image *Slider::hStart, *Slider::hMid, *Slider::hEnd, *Slider::hGrip;
Image *Slider::vStart, *Slider::vMid, *Slider::vEnd, *Slider::vGrip;
@@ -126,8 +125,8 @@ void Slider::init()
void Slider::updateAlpha()
{
- float alpha = std::max(config.getValue("guialpha", 0.8),
- (double) Theme::instance()->getMinimumOpacity());
+ float alpha = std::max(config.getFloatValue("guialpha"),
+ Theme::instance()->getMinimumOpacity());
if (alpha != mAlpha)
{
diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp
index 2ab126dd..10a51afe 100644
--- a/src/gui/widgets/tab.cpp
+++ b/src/gui/widgets/tab.cpp
@@ -25,11 +25,11 @@
#include "graphics.h"
#include "gui/palette.h"
-#include "gui/theme.h"
#include "gui/widgets/tabbedarea.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
@@ -118,8 +118,8 @@ void Tab::init()
void Tab::updateAlpha()
{
- float alpha = std::max(config.getValue("guialpha", 0.8),
- (double) Theme::instance()->getMinimumOpacity());
+ float alpha = std::max(config.getFloatValue("guialpha"),
+ Theme::instance()->getMinimumOpacity());
// TODO We don't need to do this for every tab on every draw
// Maybe use a config listener to do it as the value changes.
diff --git a/src/gui/widgets/table.cpp b/src/gui/widgets/table.cpp
index f0887ed7..3d8680ce 100644
--- a/src/gui/widgets/table.cpp
+++ b/src/gui/widgets/table.cpp
@@ -24,7 +24,8 @@
#include "configuration.h"
#include "gui/sdlinput.h"
-#include "gui/theme.h"
+
+#include "resources/theme.h"
#include "utils/dtor.h"
@@ -270,8 +271,8 @@ void GuiTable::draw(gcn::Graphics* graphics)
if (!mModel)
return;
- if (config.getValue("guialpha", 0.8) != mAlpha)
- mAlpha = config.getValue("guialpha", 0.8);
+ if (config.getFloatValue("guialpha") != mAlpha)
+ mAlpha = config.getFloatValue("guialpha");
if (mOpaque)
{
diff --git a/src/gui/widgets/textbox.cpp b/src/gui/widgets/textbox.cpp
index f248f35d..5b112e54 100644
--- a/src/gui/widgets/textbox.cpp
+++ b/src/gui/widgets/textbox.cpp
@@ -21,7 +21,7 @@
#include "gui/widgets/textbox.h"
-#include "gui/theme.h"
+#include "resources/theme.h"
#include <guichan/font.hpp>
diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp
index 4453f522..9696cd59 100644
--- a/src/gui/widgets/textfield.cpp
+++ b/src/gui/widgets/textfield.cpp
@@ -26,9 +26,9 @@
#include "gui/palette.h"
#include "gui/sdlinput.h"
-#include "gui/theme.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include "utils/copynpaste.h"
#include "utils/dtor.h"
@@ -65,7 +65,7 @@ TextField::TextField(const std::string &text, bool loseFocusOnTab):
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));
+ skin.grid[a]->setAlpha(config.getFloatValue("guialpha"));
a++;
}
}
@@ -86,8 +86,8 @@ TextField::~TextField()
void TextField::updateAlpha()
{
- float alpha = std::max(config.getValue("guialpha", 0.8),
- (double) Theme::instance()->getMinimumOpacity());
+ float alpha = std::max(config.getFloatValue("guialpha"),
+ Theme::instance()->getMinimumOpacity());
if (alpha != mAlpha)
{
diff --git a/src/gui/widgets/textpreview.cpp b/src/gui/widgets/textpreview.cpp
index 10426d7c..869ebd35 100644
--- a/src/gui/widgets/textpreview.cpp
+++ b/src/gui/widgets/textpreview.cpp
@@ -45,8 +45,8 @@ TextPreview::TextPreview(const std::string &text):
void TextPreview::draw(gcn::Graphics* graphics)
{
- if (config.getValue("guialpha", 0.8) != mAlpha)
- mAlpha = config.getValue("guialpha", 0.8);
+ if (config.getFloatValue("guialpha") != mAlpha)
+ mAlpha = config.getFloatValue("guialpha");
int alpha = (int) (mAlpha * 255.0f);
diff --git a/src/gui/widgets/whispertab.cpp b/src/gui/widgets/whispertab.cpp
index 7542e251..864f1f51 100644
--- a/src/gui/widgets/whispertab.cpp
+++ b/src/gui/widgets/whispertab.cpp
@@ -21,14 +21,15 @@
#include "whispertab.h"
+#include "chatlog.h"
#include "commandhandler.h"
#include "localplayer.h"
-#include "gui/theme.h"
-
#include "net/chathandler.h"
#include "net/net.h"
+#include "resources/theme.h"
+
#include "utils/gettext.h"
#include "utils/stringutils.h"
@@ -115,3 +116,9 @@ bool WhisperTab::handleCommand(const std::string &type,
return true;
}
+
+void WhisperTab::saveToLogFile(std::string &msg)
+{
+ if (chatLogger)
+ chatLogger->log(getNick(), msg);
+}
diff --git a/src/gui/widgets/whispertab.h b/src/gui/widgets/whispertab.h
index 447a8fe0..20a07449 100644
--- a/src/gui/widgets/whispertab.h
+++ b/src/gui/widgets/whispertab.h
@@ -39,6 +39,8 @@ class WhisperTab : public ChatTab
bool handleCommand(const std::string &type,
const std::string &args);
+ void saveToLogFile(std::string &msg);
+
protected:
friend class ChatWindow;
diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp
index 118ee7c0..aa8e6df3 100644
--- a/src/gui/widgets/window.cpp
+++ b/src/gui/widgets/window.cpp
@@ -26,7 +26,6 @@
#include "gui/gui.h"
#include "gui/palette.h"
-#include "gui/theme.h"
#include "gui/viewport.h"
#include "gui/widgets/layout.h"
@@ -34,6 +33,7 @@
#include "gui/widgets/windowcontainer.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include <guichan/exception.hpp>
#include <guichan/focushandler.hpp>
@@ -697,8 +697,8 @@ int Window::getResizeHandles(gcn::MouseEvent &event)
int Window::getGuiAlpha()
{
- float alpha = std::max(config.getValue("guialpha", 0.8),
- (double) Theme::instance()->getMinimumOpacity());
+ float alpha = std::max(config.getFloatValue("guialpha"),
+ Theme::instance()->getMinimumOpacity());
return (int) (alpha * 255.0f);
}
diff --git a/src/gui/windowmenu.cpp b/src/gui/windowmenu.cpp
index 5af5a202..76e6bc1f 100644
--- a/src/gui/windowmenu.cpp
+++ b/src/gui/windowmenu.cpp
@@ -58,7 +58,7 @@ WindowMenu::WindowMenu():
if (skillDialog->hasSkills())
addButton(N_("Skills"), x, h);
- if (specialsWindow->hasSpecials())
+ // if (specialsWindow->hasSpecials())
addButton(N_("Specials"), x, h);
addButton(N_("Social"), x, h);
diff --git a/src/guild.cpp b/src/guild.cpp
index 029cde7f..00d8614e 100644
--- a/src/guild.cpp
+++ b/src/guild.cpp
@@ -21,8 +21,7 @@
#include "guild.h"
-#include "beingmanager.h"
-#include "player.h"
+#include "actorspritemanager.h"
GuildMember::GuildMember(Guild *guild, int id, const std::string &name):
Avatar(name), mId(id), mGuild(guild)
@@ -150,10 +149,8 @@ void Guild::removeFromMembers()
itr_end = mMembers.end();
while(itr != itr_end)
{
- Being *b = beingManager->findBeing((*itr)->getID());
-
- if (b->getType() == Being::PLAYER)
- static_cast<Player*>(b)->removeGuild(getId());
+ Being *b = actorSpriteManager->findBeing((*itr)->getID());
+ b->removeGuild(getId());
++itr;
}
}
diff --git a/src/imageparticle.cpp b/src/imageparticle.cpp
index feb9548d..76c05d64 100644
--- a/src/imageparticle.cpp
+++ b/src/imageparticle.cpp
@@ -39,10 +39,10 @@ ImageParticle::~ImageParticle()
mImage->decRef();
}
-void ImageParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
+bool ImageParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
{
if (!mAlive || !mImage)
- return;
+ return false;
int screenX = (int) mPos.x + offsetX - mImage->getWidth() / 2;
int screenY = (int) mPos.y - (int)mPos.z + offsetY - mImage->getHeight()/2;
@@ -52,9 +52,7 @@ void ImageParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
screenX > graphics->getWidth() ||
screenY + mImage->getHeight() < 0 ||
screenY > graphics->getHeight())
- {
- return;
- }
+ return false;
float alphafactor = mAlpha;
@@ -65,5 +63,5 @@ void ImageParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
alphafactor *= (float) mLifetimePast / (float) mFadeIn;
mImage->setAlpha(alphafactor);
- graphics->drawImage(mImage, screenX, screenY);
+ return graphics->drawImage(mImage, screenX, screenY);
}
diff --git a/src/imageparticle.h b/src/imageparticle.h
index bc32400d..23909fa3 100644
--- a/src/imageparticle.h
+++ b/src/imageparticle.h
@@ -49,7 +49,7 @@ class ImageParticle : public Particle
/**
* Draws the particle image
*/
- virtual void draw(Graphics *graphics, int offsetX, int offsetY) const;
+ virtual bool draw(Graphics *graphics, int offsetX, int offsetY) const;
protected:
Image *mImage; /**< The image used for this particle. */
diff --git a/src/imagesprite.cpp b/src/imagesprite.cpp
new file mode 100644
index 00000000..504aba96
--- /dev/null
+++ b/src/imagesprite.cpp
@@ -0,0 +1,44 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "imagesprite.h"
+
+#include "graphics.h"
+
+ImageSprite::ImageSprite(Image *image):
+ mImage(image)
+{
+ mAlpha = mImage->getAlpha();
+
+ mImage->incRef();
+}
+
+ImageSprite::~ImageSprite()
+{
+ mImage->decRef();
+}
+
+bool ImageSprite::draw(Graphics* graphics, int posX, int posY) const
+{
+ if (mImage->getAlpha() != mAlpha)
+ mImage->setAlpha(mAlpha);
+
+ return graphics->drawImage(mImage, posX, posY);
+}
diff --git a/src/imagesprite.h b/src/imagesprite.h
new file mode 100644
index 00000000..3a3678d9
--- /dev/null
+++ b/src/imagesprite.h
@@ -0,0 +1,73 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IMAGESPRITE_H
+#define IMAGESPRITE_H
+
+#include "sprite.h"
+
+#include "resources/image.h"
+
+class Graphics;
+
+class ImageSprite : public Sprite
+{
+public:
+ ImageSprite(Image *image);
+
+ ~ImageSprite();
+
+ bool reset()
+ { return false; }
+
+ bool play(std::string action)
+ { return false; }
+
+ bool update(int time)
+ { return false; }
+
+ bool draw(Graphics* graphics, int posX, int posY) const;
+
+ int getWidth() const
+ { return mImage->getWidth(); }
+
+ int getHeight() const
+ { return mImage->getHeight(); }
+
+ const Image* getImage() const
+ { return mImage; }
+
+ virtual bool setDirection(SpriteDirection direction)
+ { return false; }
+
+ int getNumberOfLayers()
+ { return 1; }
+
+ size_t getCurrentFrame() const
+ { return 0; }
+
+ size_t getFrameCount() const
+ { return 1; }
+
+private:
+ Image *mImage;
+};
+
+#endif // IMAGESPRITE_H
diff --git a/src/item.cpp b/src/item.cpp
index b434387e..6b13dd1b 100644
--- a/src/item.cpp
+++ b/src/item.cpp
@@ -21,12 +21,12 @@
#include "item.h"
-#include "gui/theme.h"
+#include "configuration.h"
#include "resources/image.h"
#include "resources/iteminfo.h"
#include "resources/resourcemanager.h"
-#include "configuration.h"
+#include "resources/theme.h"
Item::Item(int id, int quantity, bool equipment, bool equipped):
mImage(0),
@@ -58,8 +58,9 @@ void Item::setId(int id)
mDrawImage->decRef();
ResourceManager *resman = ResourceManager::getInstance();
- std::string imagePath = paths.getValue("itemIcons", "graphics/items/")
- + getInfo().getImageName();
+ SpriteDisplay display = getInfo().getDisplay();
+ std::string imagePath = paths.getStringValue("itemIcons")
+ + display.image;
mImage = resman->getImage(imagePath);
mDrawImage = resman->getImage(imagePath);
diff --git a/src/itemshortcut.cpp b/src/itemshortcut.cpp
index 88b04347..064fdbc6 100644
--- a/src/itemshortcut.cpp
+++ b/src/itemshortcut.cpp
@@ -23,7 +23,7 @@
#include "inventory.h"
#include "item.h"
#include "itemshortcut.h"
-#include "localplayer.h"
+#include "playerinfo.h"
#include "net/inventoryhandler.h"
#include "net/net.h"
@@ -66,7 +66,7 @@ void ItemShortcut::useItem(int index)
{
if (mItems[index])
{
- Item *item = player_node->getInventory()->findItem(mItems[index]);
+ Item *item = PlayerInfo::getInventory()->findItem(mItems[index]);
if (item && item->getQuantity())
{
if (item->isEquipment())
diff --git a/src/joystick.cpp b/src/joystick.cpp
index f440c61f..9864a12b 100644
--- a/src/joystick.cpp
+++ b/src/joystick.cpp
@@ -61,11 +61,11 @@ Joystick::Joystick(int no):
logger->log("Hats: %i", SDL_JoystickNumHats(mJoystick));
logger->log("Buttons: %i", SDL_JoystickNumButtons(mJoystick));
- mEnabled = (int) config.getValue("joystickEnabled", 0) != 0;
- mUpTolerance = (int) config.getValue("upTolerance", 100);
- mDownTolerance = (int) config.getValue("downTolerance", 100);
- mLeftTolerance = (int) config.getValue("leftTolerance", 100);
- mRightTolerance = (int) config.getValue("rightTolerance", 100);
+ mEnabled = config.getBoolValue("joystickEnabled");
+ mUpTolerance = config.getIntValue("upTolerance");
+ mDownTolerance = config.getIntValue("downTolerance");
+ mLeftTolerance = config.getIntValue("leftTolerance");
+ mRightTolerance = config.getIntValue("rightTolerance");
}
Joystick::~Joystick()
diff --git a/src/listener.cpp b/src/listener.cpp
new file mode 100644
index 00000000..a9182c42
--- /dev/null
+++ b/src/listener.cpp
@@ -0,0 +1,43 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "listener.h"
+
+#include "event.h"
+
+namespace Mana
+{
+
+Listener::~Listener()
+{
+ Event::remove(this);
+}
+
+void Listener::listen(const std::string &channel)
+{
+ Event::bind(this, channel);
+}
+
+void Listener::ignore(const std::string &channel)
+{
+ Event::unbind(this, channel);
+}
+
+} // namespace Mana
diff --git a/src/listener.h b/src/listener.h
new file mode 100644
index 00000000..db7b3221
--- /dev/null
+++ b/src/listener.h
@@ -0,0 +1,45 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LISTENER_H
+#define LISTENER_H
+
+#include "event.h"
+
+#include <string>
+
+namespace Mana
+{
+
+class Listener
+{
+public:
+ virtual ~Listener();
+
+ void listen(const std::string &channel);
+
+ void ignore(const std::string &channel);
+
+ virtual void event(const std::string &channel, const Event &event) = 0;
+};
+
+} // namespace Mana
+
+#endif
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 9c64c6dc..33a07373 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -24,29 +24,21 @@
#include "client.h"
#include "configuration.h"
#include "effectmanager.h"
-#include "equipment.h"
+#include "event.h"
#include "flooritem.h"
#include "graphics.h"
#include "guild.h"
-#include "inventory.h"
#include "item.h"
#include "log.h"
#include "map.h"
-#include "monster.h"
#include "particle.h"
+#include "playerinfo.h"
#include "simpleanimation.h"
#include "sound.h"
-#include "statuseffect.h"
#include "text.h"
#include "gui/gui.h"
-#include "gui/inventorywindow.h"
-#include "gui/ministatus.h"
#include "gui/okdialog.h"
-#include "gui/skilldialog.h"
-#include "gui/statuswindow.h"
-#include "gui/theme.h"
-#include "gui/userpalette.h"
#include "gui/widgets/chattab.h"
@@ -61,9 +53,10 @@
#include "resources/animation.h"
#include "resources/imageset.h"
-#include "resources/itemdb.h"
#include "resources/iteminfo.h"
#include "resources/resourcemanager.h"
+#include "resources/theme.h"
+#include "resources/userpalette.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
@@ -80,62 +73,37 @@ const short walkingKeyboardDelay = 1000;
LocalPlayer *player_node = NULL;
LocalPlayer::LocalPlayer(int id, int subtype):
- Player(id, subtype, 0),
- mEquipment(new Equipment),
+ Being(id, PLAYER, subtype, 0),
mAttackRange(0),
mTargetTime(-1),
mLastTarget(-1),
- mCharacterPoints(0),
- mCorrectionPoints(0),
- mSpecialRechargeUpdateNeeded(0),
- mLevel(1),
- mExp(0), mExpNeeded(0),
- mMp(0), mMaxMp(0),
- mMoney(0),
- mTotalWeight(1), mMaxWeight(1),
- mHp(1), mMaxHp(1),
- mSkillPoints(0),
mTarget(NULL),
mPlayerFollowed(""),
mPickUpTarget(NULL),
- mTrading(false), mGoingToTarget(false), mKeepAttacking(false),
+ mGoingToTarget(false), mKeepAttacking(false),
mLastAction(-1),
mWalkingDir(0),
mPathSetByMouse(false),
- mInventory(new Inventory(Inventory::INVENTORY)),
mLocalWalkTime(-1),
mMessageTime(0),
mAwayDialog(0),
mAfkTime(0),
mAwayMode(false)
{
+ listen("Attributes");
+
mAwayListener = new AwayListener();
mUpdateName = true;
- mTextColor = &Theme::getThemeColor(Theme::PLAYER);
- mNameColor = &userPalette->getColor(UserPalette::SELF);
-
- initTargetCursor();
-
config.addListener("showownname", this);
setShowName(config.getValue("showownname", 1));
}
LocalPlayer::~LocalPlayer()
{
- delete mInventory;
-
config.removeListener("showownname", this);
- 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();
- }
-
delete mAwayDialog;
delete mAwayListener;
}
@@ -170,21 +138,7 @@ void LocalPlayer::logic()
mMessageTime--;
}
- if ((mSpecialRechargeUpdateNeeded%11) == 0)
- {
- mSpecialRechargeUpdateNeeded = 0;
- for (std::map<int, Special>::iterator i = mSpecials.begin();
- i != mSpecials.end();
- i++)
- {
- i->second.currentMana += i->second.recharge;
- if (i->second.currentMana > i->second.neededMana)
- {
- i->second.currentMana = i->second.neededMana;
- }
- }
- }
- mSpecialRechargeUpdateNeeded++;
+ PlayerInfo::logic();
// Targeting allowed 4 times a second
if (get_elapsed_time(mLastTarget) >= 250)
@@ -200,11 +154,10 @@ void LocalPlayer::logic()
if (mTarget)
{
- if (mTarget->getType() == Being::NPC)
+ if (mTarget->getType() == ActorSprite::NPC)
{
// NPCs are always in range
- mTarget->setTargetAnimation(
- mTargetCursor[0][mTarget->getTargetCursorSize()]);
+ mTarget->setTargetType(TCT_IN_RANGE);
}
else
{
@@ -220,10 +173,10 @@ void LocalPlayer::logic()
abs(mTarget->getTileY() - getTileY());
const int attackRange = getAttackRange();
- const int inRange = rangeX > attackRange || rangeY > attackRange
- ? 1 : 0;
- mTarget->setTargetAnimation(
- mTargetCursor[inRange][mTarget->getTargetCursorSize()]);
+ const TargetCursorType targetType = rangeX > attackRange ||
+ rangeY > attackRange ?
+ TCT_NORMAL : TCT_IN_RANGE;
+ mTarget->setTargetType(targetType);
if (!mTarget->isAlive())
stopAttack();
@@ -233,7 +186,7 @@ void LocalPlayer::logic()
}
}
- Player::logic();
+ Being::logic();
}
void LocalPlayer::setAction(Action action, int attackType)
@@ -244,12 +197,7 @@ void LocalPlayer::setAction(Action action, int attackType)
setTarget(NULL);
}
- Player::setAction(action, attackType);
-}
-
-void LocalPlayer::setGM(bool gm)
-{
- mIsGM = gm;
+ Being::setAction(action, attackType);
}
void LocalPlayer::setGMLevel(int level)
@@ -635,7 +583,7 @@ void LocalPlayer::nextTile(unsigned char dir = 0)
}
- Player::nextTile();
+ Being::nextTile();
}
else
{
@@ -674,7 +622,6 @@ void LocalPlayer::inviteToGuild(Being *being)
{
if (being->getType() != PLAYER)
return;
- Player *player = static_cast<Player*>(being);
// TODO: Allow user to choose which guild to invite being to
// For now, just invite to the first guild you have permissions to invite with
@@ -684,31 +631,19 @@ void LocalPlayer::inviteToGuild(Being *being)
{
if (checkInviteRights(itr->second->getName()))
{
- Net::getGuildHandler()->invite(itr->second->getId(), player);
+ Net::getGuildHandler()->invite(itr->second->getId(), being);
return;
}
}
}
-void LocalPlayer::clearInventory()
-{
- mEquipment->clear();
- mInventory->clear();
-}
-
-void LocalPlayer::setInvItem(int index, int id, int amount)
-{
- bool equipment = false;
- int itemType = ItemDB::get(id).getType();
- if (itemType != ITEM_UNUSABLE && itemType != ITEM_USABLE)
- equipment = true;
- mInventory->setItem(index, id, amount, equipment);
-}
-
void LocalPlayer::pickUp(FloorItem *item)
{
- int dx = item->getX() - (int) getPosition().x / 32;
- int dy = item->getY() - (int) getPosition().y / 32;
+ if (!item)
+ return;
+
+ int dx = item->getTileX() - (int) getPosition().x / 32;
+ int dy = item->getTileY() - (int) getPosition().y / 32;
if (dx * dx + dy * dy < 4)
{
@@ -719,18 +654,26 @@ void LocalPlayer::pickUp(FloorItem *item)
{
if (Net::getNetworkType() == ServerInfo::MANASERV)
{
- setDestination(item->getX() * 32 + 16, item->getY() * 32 + 16);
+ setDestination(item->getPixelX() + 16, item->getPixelY() + 16);
mPickUpTarget = item;
+ mPickUpTarget->addActorSpriteListener(this);
}
else
{
- setDestination(item->getX(), item->getY());
+ setDestination(item->getTileX(), item->getTileY());
mPickUpTarget = item;
+ mPickUpTarget->addActorSpriteListener(this);
stopAttack();
}
}
}
+void LocalPlayer::actorSpriteDestroyed(const ActorSprite &actorSprite)
+{
+ if (mPickUpTarget == &actorSprite)
+ mPickUpTarget = 0;
+}
+
Being *LocalPlayer::getTarget() const
{
return mTarget;
@@ -757,15 +700,24 @@ void LocalPlayer::setTarget(Being *target)
mTargetTime = -1;
}
+ Being *oldTarget = 0;
if (mTarget)
+ {
mTarget->untarget();
+ oldTarget = mTarget;
+ }
- if (mTarget && mTarget->getType() == Being::MONSTER)
+ if (mTarget && mTarget->getType() == ActorSprite::MONSTER)
mTarget->setShowName(false);
mTarget = target;
- if (target && target->getType() == Being::MONSTER)
+ if (oldTarget)
+ oldTarget->updateName();
+ if (mTarget)
+ mTarget->updateName();
+
+ if (target && target->getType() == ActorSprite::MONSTER)
target->setShowName(true);
}
@@ -822,11 +774,11 @@ void LocalPlayer::setWalkingDir(int dir)
mWalkingDir = dir;
// If we're not already walking, start walking.
- if (mAction != WALK && dir)
+ if (mAction != MOVE && dir)
{
startWalking(dir);
}
- else if (mAction == WALK && (Net::getNetworkType() == ServerInfo::MANASERV))
+ else if (mAction == MOVE && (Net::getNetworkType() == ServerInfo::MANASERV))
{
nextTile(dir);
}
@@ -839,7 +791,7 @@ void LocalPlayer::startWalking(unsigned char dir)
if (!mMap || !dir)
return;
- if (mAction == WALK && !mPath.empty())
+ if (mAction == MOVE && !mPath.empty())
{
// Just finish the current action, otherwise we get out of sync
if (Net::getNetworkType() == ServerInfo::MANASERV)
@@ -894,7 +846,7 @@ void LocalPlayer::startWalking(unsigned char dir)
void LocalPlayer::stopWalking(bool sendToServer)
{
- if (mAction == WALK && mWalkingDir)
+ if (mAction == MOVE && mWalkingDir)
{
mWalkingDir = 0;
mLocalWalkTime = 0;
@@ -938,20 +890,6 @@ void LocalPlayer::emote(Uint8 emotion)
Net::getPlayerHandler()->emote(emotion);
}
-void LocalPlayer::useSpecial(int special)
-{
- Net::getSpecialHandler()->use(special);
-}
-
-void LocalPlayer::setSpecialStatus(int id, int current, int max, int recharge)
-{
- logger->log("SpecialUpdate Skill #%d -- (%d/%d) -> %d", id, current, max,
- recharge);
- mSpecials[id].currentMana = current;
- mSpecials[id].neededMana = max;
- mSpecials[id].recharge = recharge;
-}
-
void LocalPlayer::attack(Being *target, bool keep)
{
if (Net::getNetworkType() == ServerInfo::MANASERV)
@@ -966,7 +904,7 @@ void LocalPlayer::attack(Being *target, bool keep)
mKeepAttacking = keep;
- if (!target || target->getType() == Being::NPC)
+ if (!target || target->getType() == ActorSprite::NPC)
return;
if (mTarget != target || !mTarget)
@@ -974,6 +912,7 @@ void LocalPlayer::attack(Being *target, bool keep)
mLastTarget = -1;
setTarget(target);
}
+
if (Net::getNetworkType() == ServerInfo::MANASERV)
{
Vector plaPos = this->getPosition();
@@ -1022,7 +961,7 @@ void LocalPlayer::attack(Being *target, bool keep)
setDirection(LEFT);
}
- mWalkTime = tick_time;
+ mActionTime = tick_time;
mTargetTime = tick_time;
}
@@ -1053,196 +992,13 @@ void LocalPlayer::stopAttack()
mLastTarget = -1;
}
-void LocalPlayer::raiseAttribute(int attr)
-{
- // we assume that the server allows the change.
- // When not we will undo it later.
- mCharacterPoints--;
- IntMap::iterator it = mAttributeBase.find(attr);
- if (it != mAttributeBase.end())
- (*it).second++;
- Net::getPlayerHandler()->increaseAttribute(attr);
-}
-
-void LocalPlayer::lowerAttribute(int attr)
-{
- // we assume that the server allows the change.
- // When not we will undo it later.
- mCorrectionPoints--;
- mCharacterPoints++;
- IntMap::iterator it = mAttributeBase.find(attr);
- if (it != mAttributeBase.end())
- (*it).second--;
- Net::getPlayerHandler()->decreaseAttribute(attr);
-}
-
-void LocalPlayer::setTotalWeight(int value)
-{
- mTotalWeight = value;
-
- inventoryWindow->updateWeight();
-}
-
-void LocalPlayer::setMaxWeight(int value)
-{
- mMaxWeight = value;
-
- inventoryWindow->updateWeight();
-}
-
-void LocalPlayer::setAttributeBase(int num, int value, bool notify)
-{
- int old = mAttributeBase[num];
-
- mAttributeBase[num] = value;
- if (skillDialog)
- {
- if (skillDialog->update(num).empty() || !(value > old))
- return;
-
- if (old != 0 && notify)
- effectManager->trigger(1, this);
- }
-
- if (statusWindow)
- statusWindow->update(num);
-}
-
-void LocalPlayer::setAttributeEffective(int num, int value)
-{
- mAttributeEffective[num] = value;
- if (skillDialog)
- skillDialog->update(num);
-
- if (statusWindow)
- statusWindow->update(num);
-}
-
-void LocalPlayer::setCharacterPoints(int n)
-{
- mCharacterPoints = n;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::CHAR_POINTS);
-}
-
-void LocalPlayer::setCorrectionPoints(int n)
-{
- mCorrectionPoints = n;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::CHAR_POINTS);
-}
-
-void LocalPlayer::setSkillPoints(int points)
-{
- mSkillPoints = points;
- if (skillDialog)
- skillDialog->update();
-}
-
-void LocalPlayer::setExperience(int skill, int current, int next, bool notify)
-{
- std::pair<int, int> cur = getExperience(skill);
- int diff = current - cur.first;
-
- cur = std::pair<int, int>(current, next);
-
- mSkillExp[skill] = cur;
-
- std::string name;
- if (skillDialog)
- name = skillDialog->update(skill);
-
- if (mMap && notify && cur.first != -1 && diff > 0 && !name.empty())
- {
- addMessageToQueue(strprintf("%d %s xp", diff, name.c_str()));
- }
-
- if (statusWindow)
- statusWindow->update(skill);
-}
-
-std::pair<int, int> LocalPlayer::getExperience(int skill)
-{
- return mSkillExp[skill];
-}
-
-void LocalPlayer::setHp(int value)
-{
- mHp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::HP);
-}
-
-void LocalPlayer::setMaxHp(int value)
-{
- mMaxHp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::HP);
-}
-
-void LocalPlayer::setLevel(int value)
-{
- mLevel = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::LEVEL);
-}
-
-void LocalPlayer::setExp(int value, bool notify)
-{
- if (mMap && notify && value > mExp)
- {
- addMessageToQueue(toString(value - mExp) + " xp");
- }
- mExp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::EXP);
-}
-
-void LocalPlayer::setExpNeeded(int value)
-{
- mExpNeeded = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::EXP);
-}
-
-void LocalPlayer::setMP(int value)
-{
- mMp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::MP);
-}
-
-void LocalPlayer::setMaxMP(int value)
-{
- mMaxMp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::MP);
-}
-
-void LocalPlayer::setMoney(int value)
-{
- mMoney = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::MONEY);
-}
-
void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount)
{
if (!amount)
{
if (config.getValue("showpickupchat", 1))
{
- localChatTab->chatLog(_("Unable to pick up item."), BY_SERVER);
+ SERVER_NOTICE(_("Unable to pick up item."))
}
}
else
@@ -1251,10 +1007,9 @@ void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount)
{
// TRANSLATORS: This sentence may be translated differently
// for different grammatical numbers (singular, plural, ...)
- localChatTab->chatLog(strprintf(ngettext("You picked up %d "
+ SERVER_NOTICE(strprintf(ngettext("You picked up %d "
"[@@%d|%s@@].", "You picked up %d [@@%d|%s@@].", amount),
- amount, itemInfo.getId(), itemInfo.getName().c_str()),
- BY_SERVER);
+ amount, itemInfo.getId(), itemInfo.getName().c_str()))
}
if (mMap && config.getValue("showpickupparticle", 0))
@@ -1273,7 +1028,8 @@ int LocalPlayer::getAttackRange()
}
else
{
- Item *weapon = mEquipment->getEquipment(EQUIP_FIGHT1_SLOT);
+ // TODO: Fix this to be more generic
+ Item *weapon = PlayerInfo::getEquipment(EQUIP_FIGHT1_SLOT);
if (weapon)
{
const ItemInfo info = weapon->getInfo();
@@ -1325,91 +1081,6 @@ void LocalPlayer::setGotoTarget(Being *target)
}
}
-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("target-cursor-blue-s.png", 44, 35, false, TC_SMALL);
- loadTargetCursor("target-cursor-red-s.png", 44, 35, true, TC_SMALL);
- loadTargetCursor("target-cursor-blue-m.png", 62, 44, false, TC_MEDIUM);
- loadTargetCursor("target-cursor-red-m.png", 62, 44, true, TC_MEDIUM);
- loadTargetCursor("target-cursor-blue-l.png", 82, 60, false, TC_LARGE);
- loadTargetCursor("target-cursor-red-l.png", 82, 60, true, TC_LARGE);
-}
-
-void LocalPlayer::loadTargetCursor(const std::string &filename,
- int width, int height,
- bool outRange, TargetCursorSize size)
-{
- assert(size > -1);
- assert(size < 3);
-
- ImageSet *currentImageSet = Theme::getImageSetFromTheme(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)));
- }
-
- SimpleAnimation *currentCursor = new SimpleAnimation(anim);
-
- const int index = outRange ? 1 : 0;
-
- mTargetCursorImages[index][size] = currentImageSet;
- mTargetCursor[index][size] = currentCursor;
-}
-
void LocalPlayer::addMessageToQueue(const std::string &message, int color)
{
mMessages.push_back(MessagePair(message, color));
@@ -1423,6 +1094,25 @@ void LocalPlayer::optionChanged(const std::string &value)
}
}
+void LocalPlayer::event(const std::string &channel, const Mana::Event &event)
+{
+ if (channel == "Attributes")
+ {
+ if (event.getName() == "UpdateAttribute")
+ {
+ if (event.getInt("id") == EXP)
+ {
+ int change = event.getInt("newValue")
+ - event.getInt("oldValue");
+
+ addMessageToQueue(toString(change) + " xp");
+ }
+ }
+ }
+ else
+ Being::event(channel, event);
+}
+
void LocalPlayer::changeAwayMode()
{
mAwayMode = !mAwayMode;
diff --git a/src/localplayer.h b/src/localplayer.h
index 2c06dfb5..2fb93e9b 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -22,9 +22,11 @@
#ifndef LOCALPLAYER_H
#define LOCALPLAYER_H
-#include "player.h"
+#include "actorspritelistener.h"
+#include "being.h"
+#include "listener.h"
-#include "gui/userpalette.h"
+#include "resources/userpalette.h"
#include <guichan/actionlistener.hpp>
@@ -32,84 +34,22 @@
#include <vector>
class ChatTab;
-class Equipment;
class FloorItem;
class ImageSet;
-class Inventory;
class Item;
class Map;
class OkDialog;
-
-struct Special
-{
- int currentMana;
- int neededMana;
- int recharge;
-};
-
class AwayListener : public gcn::ActionListener
{
public:
void action(const gcn::ActionEvent &event);
};
-
-/**
- * Attributes used during combat. Available to all the beings.
- */
-enum
-{
-BASE_ATTR_BEGIN = 0,
- BASE_ATTR_PHY_ATK_MIN = BASE_ATTR_BEGIN,
- BASE_ATTR_PHY_ATK_DELTA,
- /**< Physical attack power. */
- BASE_ATTR_MAG_ATK, /**< Magical attack power. */
- BASE_ATTR_PHY_RES, /**< Resistance to physical damage. */
- BASE_ATTR_MAG_RES, /**< Resistance to magical damage. */
- BASE_ATTR_EVADE, /**< Ability to avoid hits. */
- BASE_ATTR_HIT, /**< Ability to hit stuff. */
- BASE_ATTR_HP, /**< Hit Points (Base value: maximum, Modded value: current) */
- BASE_ATTR_HP_REGEN,/**< number of HP regenerated every 10 game ticks */
- BASE_ATTR_END,
- BASE_ATTR_NB = BASE_ATTR_END - BASE_ATTR_BEGIN,
-
- BASE_ELEM_BEGIN = BASE_ATTR_END,
- BASE_ELEM_NEUTRAL = BASE_ELEM_BEGIN,
- BASE_ELEM_FIRE,
- BASE_ELEM_WATER,
- BASE_ELEM_EARTH,
- BASE_ELEM_AIR,
- BASE_ELEM_SACRED,
- BASE_ELEM_DEATH,
- BASE_ELEM_END,
- BASE_ELEM_NB = BASE_ELEM_END - BASE_ELEM_BEGIN,
-
- NB_BEING_ATTRIBUTES = BASE_ELEM_END
-};
-
-/**
- * Attributes of characters. Used to derive being attributes.
- */
-enum
-{
- CHAR_ATTR_BEGIN = NB_BEING_ATTRIBUTES,
- CHAR_ATTR_STRENGTH = CHAR_ATTR_BEGIN,
- CHAR_ATTR_AGILITY,
- CHAR_ATTR_DEXTERITY,
- CHAR_ATTR_VITALITY,
- CHAR_ATTR_INTELLIGENCE,
- CHAR_ATTR_WILLPOWER,
- CHAR_ATTR_END,
- CHAR_ATTR_NB = CHAR_ATTR_END - CHAR_ATTR_BEGIN,
-
- NB_CHARACTER_ATTRIBUTES = CHAR_ATTR_END
-};
-
/**
* The local player character.
*/
-class LocalPlayer : public Player
+class LocalPlayer : public Being, public ActorSpriteListener
{
public:
/**
@@ -144,11 +84,6 @@ class LocalPlayer : public Player
virtual void nextTile(unsigned char dir);
/**
- * Returns the player's inventory.
- */
- Inventory *getInventory() const { return mInventory; }
-
- /**
* Check the player has permission to invite users to specific guild
*/
bool checkInviteRights(const std::string &guildName);
@@ -158,12 +93,15 @@ class LocalPlayer : public Player
*/
void inviteToGuild(Being *being);
- void clearInventory();
- void setInvItem(int index, int id, int amount);
-
void pickUp(FloorItem *item);
/**
+ * Called when an ActorSprite has been destroyed.
+ * @param actorSprite the ActorSprite being destroyed.
+ */
+ void actorSpriteDestroyed(const ActorSprite &actorSprite);
+
+ /**
* Sets the attack range.
*/
void setAttackRange(int range) { mAttackRange = range; }
@@ -172,33 +110,8 @@ class LocalPlayer : public Player
* Gets the attack range.
*/
int getAttackRange();
-
- /**
- * Returns true when the player is ready to accept a trade offer.
- * Returns false otherwise.
- */
- bool tradeRequestOk() const { return !mTrading; }
-
- /**
- * Sets the trading state of the player, i.e. whether or not he is
- * currently involved into some trade.
- */
- void setTrading(bool trading) { mTrading = trading; }
-
- void useSpecial(int id);
-
- void setSpecialStatus(int id, int current, int max, int recharge);
-
- const std::map<int, Special> &getSpecialStatus() const
- { return mSpecials; }
-
void attack(Being *target = NULL, bool keep = false);
- /**
- * Triggers whether or not to show the name as a GM name.
- */
- virtual void setGM(bool gm);
-
void setGMLevel(int level);
void stopAttack();
@@ -257,16 +170,6 @@ class LocalPlayer : public Player
*/
void stopWalking(bool sendToServer = true);
- /**
- * Uses a character point to raise an attribute
- */
- void raiseAttribute(int attr);
-
- /**
- * Uses a correction point to lower an attribute
- */
- void lowerAttribute(int attr);
-
void toggleSit();
void emote(Uint8 emotion);
@@ -275,85 +178,6 @@ class LocalPlayer : public Player
*/
void pickedUp(const ItemInfo &itemInfo, int amount);
- int getHp() const
- { return mHp; }
-
- int getMaxHp() const
- { return mMaxHp; }
-
- void setHp(int value);
-
- void setMaxHp(int value);
-
- int getLevel() const
- { return mLevel; }
-
- void setLevel(int value);
-
- void setExp(int value, bool notify = true);
-
- int getExp() const
- { return mExp; }
-
- void setExpNeeded(int value);
-
- int getExpNeeded() const
- { return mExpNeeded; }
-
- void setMP(int value);
-
- int getMP() const
- { return mMp; }
-
- void setMaxMP(int value);
-
- int getMaxMP() const
- { return mMaxMp; }
-
- int getMoney() const
- { return mMoney; }
-
- void setMoney(int value);
-
- int getTotalWeight() const
- { return mTotalWeight; }
-
- void setTotalWeight(int value);
-
- int getMaxWeight() const
- { return mMaxWeight; }
-
- void setMaxWeight(int value);
-
- int getAttributeBase(int num)
- { return mAttributeBase[num]; }
-
- void setAttributeBase(int num, int value, bool notify = true);
-
- int getAttributeEffective(int num)
- { return mAttributeEffective[num]; }
-
- void setAttributeEffective(int num, int value);
-
- int getCharacterPoints() const
- { return mCharacterPoints; }
-
- void setCharacterPoints(int n);
-
- int getCorrectionPoints() const
- { return mCorrectionPoints; }
-
- void setCorrectionPoints(int n);
-
- int getSkillPoints() const
- { return mSkillPoints; }
-
- void setSkillPoints(int points);
-
- void setExperience(int skill, int current, int next, bool notify = true);
-
- std::pair<int, int> getExperience(int skill);
-
/** Tells that the path has been set by mouse. */
void pathSetByMouse()
{ mPathSetByMouse = true; }
@@ -379,6 +203,8 @@ class LocalPlayer : public Player
*/
void optionChanged(const std::string &value);
+ void event(const std::string &channel, const Mana::Event &event);
+
/**
* set a following player by right clicking.
*/
@@ -403,7 +229,7 @@ class LocalPlayer : public Player
std::string getFollow() const { return mPlayerFollowed; }
/**
- * Tells the engine wether to check
+ * Tells the engine whether to check
* if the Player Name is to be displayed.
*/
void setCheckNameSetting(bool checked) { mUpdateName = checked; }
@@ -414,19 +240,10 @@ class LocalPlayer : public Player
*/
bool getCheckNameSetting() const { return mUpdateName; }
- /** Keeps the Equipment related values */
- const std::auto_ptr<Equipment> mEquipment;
-
protected:
-
/** Whether or not the name settings have changed */
bool mUpdateName;
- virtual void handleStatusEffect(StatusEffect *effect, int effectId);
-
- // Colors don't change for local player
- virtual void updateColors() {}
-
void startWalking(unsigned char dir);
int mAttackRange;
@@ -434,26 +251,6 @@ class LocalPlayer : public Player
int mTargetTime; /** How long the being has been targeted **/
int mLastTarget; /** Time stamp of last targeting action, -1 if none. */
- // Character status:
- typedef std::map<int, int> IntMap;
- IntMap mAttributeBase;
- IntMap mAttributeEffective;
- std::map<int, std::pair<int, int> > mSkillExp;
- int mCharacterPoints;
- int mCorrectionPoints;
- int mLevelProgress;
- std::map<int, Special> mSpecials;
- char mSpecialRechargeUpdateNeeded;
- int mLevel;
- int mExp, mExpNeeded;
- int mMp, mMaxMp;
- int mMoney;
- int mTotalWeight;
- int mMaxWeight;
- int mHp;
- int mMaxHp;
- int mSkillPoints;
-
int mGMLevel;
Being *mTarget;
@@ -465,38 +262,17 @@ class LocalPlayer : public Player
FloorItem *mPickUpTarget;
- bool mTrading;
bool mGoingToTarget;
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. */
bool mPathSetByMouse; /**< Tells if the path was set using mouse */
- std::vector<int> mStatusEffectIcons;
-
- Inventory *mInventory;
-
int mLocalWalkTime; /**< Timestamp used to control keyboard walk
messages flooding */
- /** Load the target cursors into memory */
- void initTargetCursor();
-
- /**
- * Helper function for loading target cursors
- */
- void loadTargetCursor(const 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];
-
typedef std::pair<std::string, int> MessagePair;
- /** Queued exp messages*/
+ /** Queued messages*/
std::list<MessagePair> mMessages;
int mMessageTime;
AwayListener *mAwayListener;
diff --git a/src/main.cpp b/src/main.cpp
index 29713c27..f3962c40 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -40,6 +40,10 @@ static void printHelp()
std::cout
<< _("mana [options] [mana-file]") << endl << endl
+ << _("[mana-file] : The mana file is an XML file (.mana)") << endl
+ << _(" used to set custom parameters") << endl
+ << _(" to the mana client.")
+ << endl << endl
<< _("Options:") << endl
<< _(" -v --version : Display the version") << endl
<< _(" -h --help : Display this help") << endl
@@ -55,6 +59,7 @@ static void printHelp()
<< _(" -u --skip-update : Skip the update downloads") << endl
<< _(" -d --data : Directory to load game data from") << endl
<< _(" -L --localdata-dir : Directory to use as local data directory") << endl
+ << _(" -l --chat-log-dir : Chat log dir to use") << endl
<< _(" --screenshot-dir : Directory to store screenshots") << endl
#ifdef USE_OPENGL
<< _(" --no-opengl : Disable OpenGL for this session") << endl
@@ -85,6 +90,7 @@ static void parseOptions(int argc, char *argv[], Client::Options &options)
{ "skip-update", no_argument, 0, 'u' },
{ "username", required_argument, 0, 'U' },
{ "no-opengl", no_argument, 0, 'O' },
+ { "chat-log-dir", required_argument, 0, 'l' },
{ "version", no_argument, 0, 'v' },
{ "screenshot-dir", required_argument, 0, 'i' },
{ 0 }
@@ -143,6 +149,8 @@ static void parseOptions(int argc, char *argv[], Client::Options &options)
case 'O':
options.noOpenGL = true;
break;
+ case 'l':
+ options.chatLogDir = std::string(optarg);
case 'i':
options.screenshotDir = optarg;
break;
diff --git a/src/map.cpp b/src/map.cpp
index f1f8d091..367083b6 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -21,13 +21,12 @@
#include "map.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
#include "client.h"
#include "configuration.h"
#include "graphics.h"
#include "particle.h"
#include "simpleanimation.h"
-#include "sprite.h"
#include "tileset.h"
#include "resources/ambientlayer.h"
@@ -122,7 +121,7 @@ Image* MapLayer::getTile(int x, int y) const
void MapLayer::draw(Graphics *graphics, int startX, int startY,
int endX, int endY, int scrollX, int scrollY,
- const MapSprites &sprites, int debugFlags) const
+ const Actors &actors, int debugFlags) const
{
startX -= mX;
startY -= mY;
@@ -134,47 +133,86 @@ void MapLayer::draw(Graphics *graphics, int startX, int startY,
if (endX > mWidth) endX = mWidth;
if (endY > mHeight) endY = mHeight;
- MapSprites::const_iterator si = sprites.begin();
+ Actors::const_iterator ai = actors.begin();
+
+ int dx = (mX * 32) - scrollX;
+ int dy = (mY * 32) - scrollY + 32;
for (int y = startY; y < endY; y++)
{
- // If drawing the fringe layer, make sure all sprites above this row of
+ int y32 = y * 32;
+
+ // If drawing the fringe layer, make sure all actors above this row of
// tiles have been drawn
if (mIsFringeLayer)
{
- while (si != sprites.end() && (*si)->getPixelY() <= y * 32)
+ while (ai != actors.end() && (*ai)->getPixelY() <= y * 32)
{
- (*si)->setAlpha(1.0f);
- (*si)->draw(graphics, -scrollX, -scrollY);
- si++;
+ (*ai)->draw(graphics, -scrollX, -scrollY);
+ ai++;
}
}
- for (int x = startX; x < endX; x++)
+ if (debugFlags != Map::MAP_SPECIAL3)
{
- Image *img = getTile(x, y);
- if (img)
+ const int py0 = y32 + dy;
+
+ for (int x = startX; x < endX; x++)
{
- const int px = (x + mX) * 32 - scrollX;
- const int py = (y + mY) * 32 - scrollY + 32 - img->getHeight();
- if (debugFlags != Map::MAP_SPECIAL || img->getHeight() <= 32)
- graphics->drawImage(img, px, py);
+ Image *img = getTile(x, y);
+ if (img)
+ {
+ const int px = (x * 32) + dx;
+ const int py = py0 - img->getHeight();
+ if ((debugFlags != Map::MAP_SPECIAL
+ && debugFlags != Map::MAP_SPECIAL2)
+ || img->getHeight() <= 32)
+ {
+ int width = 0;
+ int c = getTileDrawWidth(x, y, endX, width);
+ if (!c)
+ {
+ graphics->drawImage(img, px, py);
+ }
+ else
+ {
+ graphics->drawImagePattern(img, px, py,
+ width, img->getHeight());
+ }
+ x += c;
+ }
+ }
}
}
}
- // Draw any remaining sprites
+ // Draw any remaining actors
if (mIsFringeLayer)
{
- while (si != sprites.end())
+ while (ai != actors.end())
{
- (*si)->setAlpha(1.0f);
- (*si)->draw(graphics, -scrollX, -scrollY);
- si++;
+ (*ai)->draw(graphics, -scrollX, -scrollY);
+ ai++;
}
}
}
+int MapLayer::getTileDrawWidth(int x1, int y1, int endX, int &width) const
+{
+ Image *img1 = getTile(x1, y1);
+ int c = 0;
+ width = img1->getWidth();
+ for (int x = x1 + 1; x < endX; x++)
+ {
+ Image *img = getTile(x, y1);
+ if (img != img1)
+ break;
+ c ++;
+ width += img->getWidth();
+ }
+ return c;
+}
+
Map::Map(int width, int height, int tileWidth, int tileHeight):
mWidth(width), mHeight(height),
mTileWidth(tileWidth), mTileHeight(tileHeight),
@@ -283,7 +321,7 @@ void Map::addTileset(Tileset *tileset)
mMaxTileHeight = tileset->getHeight();
}
-bool spriteCompare(const Sprite *a, const Sprite *b)
+bool actorCompare(const Actor *a, const Actor *b)
{
return a->getPixelY() < b->getPixelY();
}
@@ -309,46 +347,69 @@ void Map::draw(Graphics *graphics, int scrollX, int scrollY)
int endX = (graphics->getWidth() + scrollX + mTileWidth - 1) / mTileWidth;
int endY = endPixelY / mTileHeight;
- // Make sure sprites are sorted ascending by Y-coordinate
+ // Make sure actors are sorted ascending by Y-coordinate
// so that they overlap correctly
- mSprites.sort(spriteCompare);
+ mActors.sort(actorCompare);
// update scrolling of all ambient layers
updateAmbientLayers(scrollX, scrollY);
// Draw backgrounds
drawAmbientLayers(graphics, BACKGROUND_LAYERS, scrollX, scrollY,
- (int) config.getValue("OverlayDetail", 2));
+ config.getIntValue("OverlayDetail"));
// draw the game world
Layers::const_iterator layeri = mLayers.begin();
- for (; layeri != mLayers.end(); ++layeri)
+
+ bool overFringe = false;
+
+ if (mDebugFlags == MAP_SPECIAL3)
+ {
+ for (; layeri != mLayers.end(); ++layeri)
+ {
+ if ((*layeri)->isFringeLayer())
+ {
+ (*layeri)->draw(graphics,
+ startX, startY, endX, endY,
+ scrollX, scrollY,
+ mActors, mDebugFlags);
+ }
+ }
+ }
+ else
{
- (*layeri)->draw(graphics,
- startX, startY, endX, endY,
- scrollX, scrollY,
- mSprites, mDebugFlags);
+ for (; layeri != mLayers.end() && !overFringe; ++layeri)
+ {
+ if ((*layeri)->isFringeLayer() && mDebugFlags == MAP_SPECIAL2)
+ overFringe = true;
+
+ (*layeri)->draw(graphics,
+ startX, startY, endX, endY,
+ scrollX, scrollY,
+ mActors, mDebugFlags);
+ }
}
// Draws beings with a lower opacity to make them visible
// even when covered by a wall or some other elements...
- MapSprites::const_iterator si = mSprites.begin();
- while (si != mSprites.end())
+ Actors::const_iterator ai = mActors.begin();
+ while (ai != mActors.end())
{
- if (Sprite *sprite = *si)
+ if (Actor *actor = *ai)
{
- // For now, just draw sprites with only one layer.
- if (sprite->getNumberOfLayers() == 1)
+ // For now, just draw actors with only one layer.
+ if (actor->getNumberOfLayers() == 1)
{
- sprite->setAlpha(0.3f);
- sprite->draw(graphics, -scrollX, -scrollY);
+ actor->setAlpha(0.3f);
+ actor->draw(graphics, -scrollX, -scrollY);
+ actor->setAlpha(1.0f);
}
}
- si++;
+ ai++;
}
drawAmbientLayers(graphics, FOREGROUND_LAYERS, scrollX, scrollY,
- (int) config.getValue("OverlayDetail", 2));
+ config.getIntValue("OverlayDetail"));
}
void Map::drawCollision(Graphics *graphics, int scrollX, int scrollY,
@@ -524,12 +585,14 @@ bool Map::getWalk(int x, int y, unsigned char walkmask) const
bool Map::occupied(int x, int y) const
{
- const Beings &beings = beingManager->getAll();
- for (Beings::const_iterator i = beings.begin(); i != beings.end(); i++)
+ const ActorSprites &actors = actorSpriteManager->getAll();
+ ActorSpritesConstIterator it, it_end;
+ for (it = actors.begin(), it_end = actors.end(); it != it_end; it++)
{
- const Being *being = *i;
+ const ActorSprite *actor = *it;
- if (being->getTileX() == x && being->getTileY() == y)
+ if (actor->getTileX() == x && actor->getTileY() == y &&
+ actor->getType() != ActorSprite::FLOOR_ITEM)
return true;
}
@@ -546,15 +609,15 @@ MetaTile *Map::getMetaTile(int x, int y) const
return &mMetaTiles[x + y * mWidth];
}
-MapSprite Map::addSprite(Sprite *sprite)
+Actors::iterator Map::addActor(Actor *actor)
{
- mSprites.push_front(sprite);
- return mSprites.begin();
+ mActors.push_front(actor);
+ return mActors.begin();
}
-void Map::removeSprite(MapSprite iterator)
+void Map::removeActor(Actors::iterator iterator)
{
- mSprites.erase(iterator);
+ mActors.erase(iterator);
}
const std::string Map::getMusicFile() const
@@ -893,7 +956,7 @@ void Map::initializeParticleEffects(Particle *particleEngine)
{
Particle *p;
- if (config.getValue("particleeffects", 1))
+ if (config.getBoolValue("particleeffects"))
{
for (std::list<ParticleEffectData>::iterator i = particleEffects.begin();
i != particleEffects.end();
diff --git a/src/map.h b/src/map.h
index 9fc32232..160cb7f7 100644
--- a/src/map.h
+++ b/src/map.h
@@ -22,6 +22,7 @@
#ifndef MAP_H
#define MAP_H
+#include "actor.h"
#include "position.h"
#include "properties.h"
@@ -31,16 +32,12 @@
class Animation;
class AmbientLayer;
class Graphics;
-class Image;
class MapLayer;
class Particle;
class SimpleAnimation;
-class Sprite;
class Tileset;
typedef std::vector<Tileset*> Tilesets;
-typedef std::list<Sprite*> MapSprites;
-typedef MapSprites::iterator MapSprite;
typedef std::vector<MapLayer*> Layers;
/**
@@ -91,7 +88,7 @@ class MapLayer
public:
/**
* Constructor, taking layer origin, size and whether this layer is the
- * fringe layer. The fringe layer is the layer that draws the sprites.
+ * fringe layer. The fringe layer is the layer that draws the actors.
* There can be only one fringe layer per map.
*/
MapLayer(int x, int y, int width, int height, bool isFringeLayer);
@@ -121,20 +118,25 @@ class MapLayer
* expected to be in map range and will be translated to local layer
* coordinates and clipped to the layer's dimensions.
*
- * The given sprites are only drawn when this layer is the fringe
+ * The given actors are only drawn when this layer is the fringe
* layer.
*/
void draw(Graphics *graphics,
int startX, int startY,
int endX, int endY,
int scrollX, int scrollY,
- const MapSprites &sprites,
+ const Actors &actors,
int mDebugFlags) const;
+ bool isFringeLayer()
+ { return mIsFringeLayer; }
+
+ int getTileDrawWidth(int x1, int y1, int endX, int &width) const;
+
private:
int mX, mY;
int mWidth, mHeight;
- bool mIsFringeLayer; /**< Whether the sprites are drawn. */
+ bool mIsFringeLayer; /**< Whether the actors are drawn. */
Image **mTiles;
};
@@ -164,7 +166,9 @@ class Map : public Properties
{
MAP_NORMAL = 0,
MAP_DEBUG = 1,
- MAP_SPECIAL = 2
+ MAP_SPECIAL = 2,
+ MAP_SPECIAL2 = 3,
+ MAP_SPECIAL3 = 4
};
/**
@@ -190,7 +194,7 @@ class Map : public Properties
/**
* Draws the map to the given graphics output. This method draws all
- * layers, sprites and overlay effects.
+ * layers, actors and overlay effects.
*
* TODO: For efficiency reasons, this method could take into account
* the clipping rectangle set on the Graphics object. However,
@@ -295,16 +299,6 @@ class Map : public Properties
unsigned char walkmask, int maxCost = 20);
/**
- * Adds a sprite to the map.
- */
- MapSprite addSprite(Sprite *sprite);
-
- /**
- * Removes a sprite from the map.
- */
- void removeSprite(MapSprite iterator);
-
- /**
* Adds a particle effect
*/
void addParticleEffect(const std::string &effectFile, int x, int y, int w = 0, int h = 0);
@@ -329,6 +323,19 @@ class Map : public Properties
*/
TileAnimation *getAnimationForGid(int gid) const;
+ protected:
+ friend class Actor;
+
+ /**
+ * Adds an actor to the map.
+ */
+ Actors::iterator addActor(Actor *actor);
+
+ /**
+ * Removes an actor from the map.
+ */
+ void removeActor(Actors::iterator iterator);
+
private:
enum LayerType
@@ -364,7 +371,7 @@ class Map : public Properties
MetaTile *mMetaTiles;
Layers mLayers;
Tilesets mTilesets;
- MapSprites mSprites;
+ Actors mActors;
// debug flags
int mDebugFlags;
diff --git a/src/monster.cpp b/src/monster.cpp
deleted file mode 100644
index ca156821..00000000
--- a/src/monster.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "monster.h"
-
-#include "animatedsprite.h"
-#include "client.h"
-#include "localplayer.h"
-#include "particle.h"
-#include "sound.h"
-#include "text.h"
-
-#include "gui/userpalette.h"
-
-#include "net/net.h"
-
-#include "resources/monsterdb.h"
-#include "resources/monsterinfo.h"
-#include "configuration.h"
-
-Monster::Monster(int id, int subtype, Map *map):
- Being(id, subtype, map),
- mAttackType(1)
-{
- setSubtype(subtype);
-
- mNameColor = &userPalette->getColor(UserPalette::MONSTER);
- mTextColor = &userPalette->getColor(UserPalette::MONSTER);
-
- Being::setName(getInfo().getName());
-}
-
-void Monster::logic()
-{
- if ((Net::getNetworkType() == ServerInfo::TMWATHENA) && (mAction != STAND))
- {
- mFrame = (int) ((get_elapsed_time(mWalkTime) * 4) / getWalkSpeed().x);
-
- if (mFrame >= 4 && mAction != DEAD)
- nextTile();
- }
-
- Being::logic();
-}
-
-
-void Monster::setAction(Action action, int attackType)
-{
- SpriteAction currentAction = ACTION_INVALID;
- int rotation = 0;
- std::string particleEffect;
-
- switch (action)
- {
- case WALK:
- currentAction = ACTION_WALK;
- break;
- case DEAD:
- currentAction = ACTION_DEAD;
- sound.playSfx(getInfo().getSound(MONSTER_EVENT_DIE));
- break;
- case ATTACK:
- mAttackType = attackType;
- currentAction = getInfo().getAttackAction(attackType);
- for (SpriteIterator it = mSprites.begin(); it != mSprites.end(); it++)
- (*it)->reset();
-
- //attack particle effect
- particleEffect = getInfo().getAttackParticleEffect(attackType);
- if (!particleEffect.empty() && Particle::enabled)
- {
- switch (mSpriteDirection)
- {
- case DIRECTION_DOWN: rotation = 0; break;
- case DIRECTION_LEFT: rotation = 90; break;
- case DIRECTION_UP: rotation = 180; break;
- case DIRECTION_RIGHT: rotation = 270; break;
- default: break;
- }
- Particle *p;
- p = particleEngine->addEffect(particleEffect, 0, 0, rotation);
- controlParticle(p);
- }
- break;
- case STAND:
- currentAction = ACTION_STAND;
- break;
- case HURT:
- // Not implemented yet
- break;
- case SIT:
- // Also not implemented yet
- break;
- }
-
- if (currentAction != ACTION_INVALID)
- {
- for (SpriteIterator it = mSprites.begin(); it != mSprites.end(); it++)
- if (*it)
- (*it)->play(currentAction);
- mAction = action;
- }
-}
-
-void Monster::setSubtype(Uint16 subtype)
-{
- Being::setSubtype(subtype);
-
- const MonsterInfo &info = getInfo();
-
- // Setup Monster sprites
- const std::list<std::string> &sprites = info.getSprites();
-
- mSprites.clear();
- for (std::list<std::string>::const_iterator i = sprites.begin();
- i != sprites.end(); i++)
- {
- std::string file = paths.getValue("sprites",
- "graphics/sprites/") + *i;
- mSprites.push_back(AnimatedSprite::load(file));
- }
-
- // Ensure that something is shown
- if (mSprites.size() == 0)
- {
- mSprites.push_back(AnimatedSprite::load(
- paths.getValue("sprites", "graphics/sprites/") +
- paths.getValue("spriteErrorFile", "error.xml") ));
- }
-
- if (Particle::enabled)
- {
- 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));
- }
- }
-}
-
-void Monster::handleAttack(Being *victim, int damage, AttackType type)
-{
- Being::handleAttack(victim, damage, type);
-
- const MonsterInfo &mi = getInfo();
- sound.playSfx(mi.getSound((damage > 0) ?
- MONSTER_EVENT_HIT : MONSTER_EVENT_MISS));
-
- fireMissile(victim, mi.getAttackMissileParticle(mAttackType));
-}
-
-void Monster::takeDamage(Being *attacker, int amount, AttackType type)
-{
- if (amount > 0)
- sound.playSfx(getInfo().getSound(MONSTER_EVENT_HURT));
-
- Being::takeDamage(attacker, amount, type);
-}
-
-Being::TargetCursorSize Monster::getTargetCursorSize() const
-{
- return getInfo().getTargetCursorSize();
-}
-
-const MonsterInfo &Monster::getInfo() const
-{
- return MonsterDB::get(mSubType);
-}
-
-void Monster::updateCoords()
-{
- if (mDispName)
- {
- mDispName->adviseXY(getPixelX(),
- getPixelY() - getHeight() - mDispName->getHeight());
- }
-}
-
-void Monster::showName()
-{
- Being::showName();
-
- updateCoords();
-}
diff --git a/src/monster.h b/src/monster.h
deleted file mode 100644
index 9bb8e3b9..00000000
--- a/src/monster.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef MONSTER_H
-#define MONSTER_H
-
-#include "being.h"
-
-class MonsterInfo;
-class Text;
-
-class Monster : public Being
-{
- public:
- Monster(int id, int subtype, Map *map);
-
- virtual void logic();
-
- virtual void setAction(Action action, int attackType = 0);
-
- virtual Type getType() const { return MONSTER; }
-
- virtual void setSubtype(Uint16 subtype);
-
- virtual TargetCursorSize
- getTargetCursorSize() const;
-
- /**
- * Handles an attack of another being by this monster. Plays a hit or
- * miss sound when appropriate.
- *
- * @param victim the victim being
- * @param damage the amount of damage dealt (0 means miss)
- * @param type the attack type
- */
- virtual void handleAttack(Being *victim, int damage, AttackType type);
-
- /**
- * Puts a damage bubble above this monster and plays the hurt sound
- *
- * @param attacker the attacking being
- * @param damage the amount of damage recieved (0 means miss)
- * @param type the attack type
- */
- virtual void takeDamage(Being *attacker, int amount, AttackType type);
-
- /**
- * Returns the MonsterInfo, with static data about this monster.
- */
- const MonsterInfo& getInfo() const;
-
- /**
- * Gets the way the monster is blocked by other objects
- */
- virtual unsigned char getWalkMask() const
- {
- return Map::BLOCKMASK_WALL
- | Map::BLOCKMASK_CHARACTER
- | Map::BLOCKMASK_MONSTER;
- }
-
- protected:
- /**
- * Gets the way the monster blocks pathfinding for other objects
- */
- virtual Map::BlockType getBlockType() const
- { return Map::BLOCKTYPE_MONSTER; }
-
- /**
- * Update the text when the monster moves
- */
- void updateCoords();
-
- void showName();
-
- private:
- int mAttackType;
-};
-
-#endif
diff --git a/src/net/adminhandler.h b/src/net/adminhandler.h
index 23e9abc0..3ed96dbd 100644
--- a/src/net/adminhandler.h
+++ b/src/net/adminhandler.h
@@ -29,6 +29,8 @@ namespace Net {
class AdminHandler
{
public:
+ virtual ~AdminHandler() {}
+
virtual void announce(const std::string &text) = 0;
virtual void localAnnounce(const std::string &text) = 0;
@@ -49,8 +51,6 @@ class AdminHandler
virtual void mute(int playerId, int type, int limit) = 0;
- virtual ~AdminHandler() {}
-
// TODO
};
diff --git a/src/net/charhandler.h b/src/net/charhandler.h
index 4a813e21..c2be5714 100644
--- a/src/net/charhandler.h
+++ b/src/net/charhandler.h
@@ -24,13 +24,13 @@
#include "localplayer.h"
#include "logindata.h"
+#include "playerinfo.h"
#include <iosfwd>
#include <vector>
class CharCreateDialog;
class CharSelectDialog;
-class LocalPlayer;
namespace Net {
@@ -52,6 +52,7 @@ struct Character
int slot; /**< The index in the list of characters */
LocalPlayer *dummy; /**< A dummy representing this character */
+ PlayerInfoBackend data;
};
typedef std::list<Character*> Characters;
@@ -59,6 +60,8 @@ typedef std::list<Character*> Characters;
class CharHandler
{
public:
+ virtual ~CharHandler() {}
+
virtual void setCharSelectDialog(CharSelectDialog *window) = 0;
virtual void setCharCreateDialog(CharCreateDialog *window) = 0;
@@ -75,13 +78,11 @@ class CharHandler
virtual void switchCharacter() = 0;
- virtual int baseSprite() const = 0;
+ virtual unsigned int baseSprite() const = 0;
- virtual int hairSprite() const = 0;
+ virtual unsigned int hairSprite() const = 0;
- virtual int maxSprite() const = 0;
-
- virtual ~CharHandler() {}
+ virtual unsigned int maxSprite() const = 0;
protected:
CharHandler():
diff --git a/src/net/chathandler.h b/src/net/chathandler.h
index d1449698..fbaa8dba 100644
--- a/src/net/chathandler.h
+++ b/src/net/chathandler.h
@@ -28,6 +28,8 @@ namespace Net {
class ChatHandler
{
public:
+ virtual ~ChatHandler() {}
+
virtual void talk(const std::string &text) = 0;
virtual void me(const std::string &text) = 0;
@@ -53,8 +55,6 @@ class ChatHandler
virtual void kickUser(int channelId, const std::string &name) = 0;
virtual void who() = 0;
-
- virtual ~ChatHandler() {}
};
}
diff --git a/src/net/download.cpp b/src/net/download.cpp
index a2cd4910..83ab180f 100644
--- a/src/net/download.cpp
+++ b/src/net/download.cpp
@@ -221,8 +221,8 @@ int Download::downloadThread(void *ptr)
}
curl_easy_setopt(d->mCurl, CURLOPT_USERAGENT,
- strprintf(PACKAGE_EXTENDED_VERSION, branding
- .getValue("appShort", "mana").c_str()).c_str());
+ strprintf(PACKAGE_EXTENDED_VERSION,
+ branding.getStringValue("appShort").c_str()).c_str());
curl_easy_setopt(d->mCurl, CURLOPT_ERRORBUFFER, d->mError);
curl_easy_setopt(d->mCurl, CURLOPT_URL, d->mUrl.c_str());
curl_easy_setopt(d->mCurl, CURLOPT_NOPROGRESS, 0);
diff --git a/src/net/gamehandler.h b/src/net/gamehandler.h
index 774de16c..9b0c8d95 100644
--- a/src/net/gamehandler.h
+++ b/src/net/gamehandler.h
@@ -31,16 +31,14 @@ namespace Net {
class GameHandler
{
public:
+ virtual ~GameHandler() {}
+
virtual void connect() = 0;
virtual bool isConnected() = 0;
virtual void disconnect() = 0;
- virtual void inGame() = 0;
-
- virtual void mapLoaded(const std::string &mapName) = 0;
-
virtual void who() = 0;
virtual void quit() = 0;
@@ -49,7 +47,10 @@ class GameHandler
virtual bool removeDeadBeings() const = 0;
- virtual ~GameHandler() {}
+ /**
+ * Tells whether the protocol is using the MP status bar
+ */
+ virtual bool canUseMagicBar() const = 0;
};
} // namespace Net
diff --git a/src/net/generalhandler.h b/src/net/generalhandler.h
index 222b430a..1d8c66af 100644
--- a/src/net/generalhandler.h
+++ b/src/net/generalhandler.h
@@ -40,13 +40,7 @@ class GeneralHandler
virtual void flushNetwork() = 0;
- virtual void guiWindowsLoaded() = 0;
-
- virtual void guiWindowsUnloaded() = 0;
-
virtual void clearHandlers() = 0;
-
- virtual void stateChanged(State oldState, State newState) = 0;
};
} // namespace Net
diff --git a/src/net/guildhandler.h b/src/net/guildhandler.h
index 1696b2d5..e4513cbb 100644
--- a/src/net/guildhandler.h
+++ b/src/net/guildhandler.h
@@ -23,10 +23,11 @@
#define GUILDHANDLER_H
#include "guild.h"
-#include "player.h"
#include <iosfwd>
+class Being;
+
namespace Net {
class GuildHandler
@@ -40,7 +41,7 @@ class GuildHandler
virtual void invite(int guildId, const std::string &name) = 0;
- virtual void invite(int guildId, Player *player) = 0;
+ virtual void invite(int guildId, Being *being) = 0;
virtual void inviteResponse(int guildId, bool response) = 0;
diff --git a/src/net/inventoryhandler.h b/src/net/inventoryhandler.h
index e48043a7..91257d3b 100644
--- a/src/net/inventoryhandler.h
+++ b/src/net/inventoryhandler.h
@@ -32,6 +32,8 @@ namespace Net {
class InventoryHandler
{
public:
+ virtual ~InventoryHandler() {}
+
virtual void equipItem(const Item *item) = 0;
virtual void unequipItem(const Item *item) = 0;
@@ -57,8 +59,6 @@ class InventoryHandler
// TODO: fix/remove me
virtual size_t getSize(int type) const = 0;
-
- virtual ~InventoryHandler() {}
};
} // namespace Net
diff --git a/src/net/logindata.h b/src/net/logindata.h
index 9bbeed4f..021a57f3 100644
--- a/src/net/logindata.h
+++ b/src/net/logindata.h
@@ -22,7 +22,7 @@
#ifndef LOGINDATA_H
#define LOGINDATA_H
-#include "player.h"
+#include "being.h"
#include "net/serverinfo.h"
diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp
index 8df9a8ab..63c1e13f 100644
--- a/src/net/manaserv/beinghandler.cpp
+++ b/src/net/manaserv/beinghandler.cpp
@@ -21,13 +21,12 @@
#include "net/manaserv/beinghandler.h"
+#include "actorspritemanager.h"
#include "being.h"
-#include "beingmanager.h"
#include "client.h"
#include "game.h"
#include "localplayer.h"
#include "log.h"
-#include "npc.h"
#include "particle.h"
#include "gui/okdialog.h"
@@ -121,7 +120,7 @@ Vector BeingHandler::giveSpeedInPixelsPerTicks(float speedInTilesPerSeconds)
return speedInTicks;
}
-static void handleLooks(Player *being, Net::MessageIn &msg)
+static void handleLooks(Being *being, Net::MessageIn &msg)
{
// Order of sent slots. Has to be in sync with the server code.
static int const nb_slots = 4;
@@ -145,7 +144,7 @@ static void handleLooks(Player *being, Net::MessageIn &msg)
{
if (!(mask & (1 << i))) continue;
int id = msg.readInt16();
- being->setSprite(slots[i], id);
+ being->setSprite(slots[i], id,"", (slots[i] == SPRITE_WEAPON));
}
}
@@ -170,23 +169,23 @@ void BeingHandler::handleBeingEnterMessage(Net::MessageIn &msg)
}
else
{
- being = beingManager->createBeing(id, Being::PLAYER, 0);
+ being = actorSpriteManager->createBeing(id,
+ ActorSprite::PLAYER, 0);
being->setName(name);
}
- Player *p = static_cast< Player * >(being);
int hs = msg.readInt8(), hc = msg.readInt8();
- p->setSprite(SPRITE_HAIR, hs * -1, ColorDB::get(hc));
- p->setGender(msg.readInt8() == GENDER_MALE ?
- GENDER_MALE : GENDER_FEMALE);
- handleLooks(p, msg);
+ being->setSprite(SPRITE_HAIR, hs * -1, ColorDB::get(hc));
+ being->setGender(msg.readInt8() == GENDER_MALE ?
+ GENDER_MALE : GENDER_FEMALE);
+ handleLooks(being, msg);
} break;
case OBJECT_MONSTER:
case OBJECT_NPC:
{
int subtype = msg.readInt16();
- being = beingManager->createBeing(id, type == OBJECT_MONSTER ?
- Being::MONSTER : Being::NPC, subtype);
+ being = actorSpriteManager->createBeing(id, type == OBJECT_MONSTER
+ ? ActorSprite::MONSTER : ActorSprite::NPC, subtype);
std::string name = msg.readString();
if (name.length() > 0) being->setName(name);
} break;
@@ -202,11 +201,11 @@ void BeingHandler::handleBeingEnterMessage(Net::MessageIn &msg)
void BeingHandler::handleBeingLeaveMessage(Net::MessageIn &msg)
{
- Being *being = beingManager->findBeing(msg.readInt16());
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
if (!being)
return;
- beingManager->destroyBeing(being);
+ actorSpriteManager->destroy(being);
}
void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg)
@@ -215,7 +214,7 @@ void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg)
{
int id = msg.readInt16();
int flags = msg.readInt8();
- Being *being = beingManager->findBeing(id);
+ Being *being = actorSpriteManager->findBeing(id);
int sx = 0;
int sy = 0;
int speed = 0;
@@ -257,7 +256,7 @@ void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg)
void BeingHandler::handleBeingAttackMessage(Net::MessageIn &msg)
{
- Being *being = beingManager->findBeing(msg.readInt16());
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
const int direction = msg.readInt8();
const int attackType = msg.readInt8();
@@ -279,7 +278,7 @@ void BeingHandler::handleBeingsDamageMessage(Net::MessageIn &msg)
{
while (msg.getUnreadLength())
{
- Being *being = beingManager->findBeing(msg.readInt16());
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
int damage = msg.readInt16();
if (being)
{
@@ -290,7 +289,7 @@ void BeingHandler::handleBeingsDamageMessage(Net::MessageIn &msg)
void BeingHandler::handleBeingActionChangeMessage(Net::MessageIn &msg)
{
- Being *being = beingManager->findBeing(msg.readInt16());
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
Being::Action action = (Being::Action) msg.readInt8();
if (!being)
return;
@@ -329,22 +328,21 @@ void BeingHandler::handleBeingActionChangeMessage(Net::MessageIn &msg)
void BeingHandler::handleBeingLooksChangeMessage(Net::MessageIn &msg)
{
- Being *being = beingManager->findBeing(msg.readInt16());
- if (!being || being->getType() != Being::PLAYER)
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ if (!being || being->getType() != ActorSprite::PLAYER)
return;
- Player *player = static_cast<Player *>(being);
- handleLooks(player, msg);
+ handleLooks(being, msg);
if (msg.getUnreadLength())
{
int style = msg.readInt16();
int color = msg.readInt16();
- player->setSprite(SPRITE_HAIR, style * -1, ColorDB::get(color));
+ being->setSprite(SPRITE_HAIR, style * -1, ColorDB::get(color));
}
}
void BeingHandler::handleBeingDirChangeMessage(Net::MessageIn &msg)
{
- Being *being = beingManager->findBeing(msg.readInt16());
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
if (!being)
return;
int data = msg.readInt8();
diff --git a/src/net/manaserv/buysellhandler.cpp b/src/net/manaserv/buysellhandler.cpp
index a4ce6aa0..d4187db7 100644
--- a/src/net/manaserv/buysellhandler.cpp
+++ b/src/net/manaserv/buysellhandler.cpp
@@ -21,13 +21,11 @@
#include "net/manaserv/buysellhandler.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
#include "item.h"
-#include "localplayer.h"
-#include "npc.h"
+#include "playerinfo.h"
#include "gui/buy.h"
-#include "gui/chat.h"
#include "gui/sell.h"
#include "net/messagein.h"
@@ -49,8 +47,8 @@ BuySellHandler::BuySellHandler()
void BuySellHandler::handleMessage(Net::MessageIn &msg)
{
- Being *being = beingManager->findBeing(msg.readInt16());
- if (!being || being->getType() != Being::NPC)
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ if (!being || being->getType() != ActorSprite::NPC)
{
return;
}
@@ -64,7 +62,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
BuyDialog* dialog = new BuyDialog(npcId);
dialog->reset();
- dialog->setMoney(player_node->getMoney());
+ dialog->setMoney(PlayerInfo::getAttribute(MONEY));
while (msg.getUnreadLength())
{
@@ -81,7 +79,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
SellDialog* dialog = new SellDialog(npcId);
dialog->reset();
- dialog->setMoney(player_node->getMoney());
+ dialog->setMoney(PlayerInfo::getAttribute(MONEY));
while (msg.getUnreadLength())
{
diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp
index e6723226..7e401455 100644
--- a/src/net/manaserv/charhandler.cpp
+++ b/src/net/manaserv/charhandler.cpp
@@ -233,6 +233,7 @@ void CharHandler::handleCharacterSelectResponse(Net::MessageIn &msg)
// Prevent the selected local player from being deleted
player_node = mSelectedCharacter->dummy;
+ PlayerInfo::setBackend(mSelectedCharacter->data);
mSelectedCharacter->dummy = 0;
Client::setState(STATE_CONNECT_GAME);
@@ -319,17 +320,17 @@ void CharHandler::switchCharacter()
gameHandler->quit(true);
}
-int CharHandler::baseSprite() const
+unsigned int CharHandler::baseSprite() const
{
return SPRITE_BASE;
}
-int CharHandler::hairSprite() const
+unsigned int CharHandler::hairSprite() const
{
return SPRITE_HAIR;
}
-int CharHandler::maxSprite() const
+unsigned int CharHandler::maxSprite() const
{
return SPRITE_VECTOREND;
}
@@ -355,14 +356,14 @@ void CharHandler::updateCharacters()
player->setGender(info.gender);
player->setSprite(SPRITE_HAIR, info.hairStyle * -1,
ColorDB::get(info.hairColor));
- player->setLevel(info.level);
- player->setCharacterPoints(info.characterPoints);
- player->setCorrectionPoints(info.correctionPoints);
- player->setMoney(info.money);
+ character->data.mAttributes[LEVEL] = info.level;
+ character->data.mAttributes[CHAR_POINTS] = info.characterPoints;
+ character->data.mAttributes[CORR_POINTS] = info.correctionPoints;
+ character->data.mAttributes[MONEY] = info.money;
for (int i = 0; i < 7; i++)
{
- player->setAttributeBase(i, info.attribute[i], false);
+ character->data.mStats[i].base = info.attribute[i];
}
mCharacters.push_back(character);
diff --git a/src/net/manaserv/charhandler.h b/src/net/manaserv/charhandler.h
index 26a7bf4e..dac4a29e 100644
--- a/src/net/manaserv/charhandler.h
+++ b/src/net/manaserv/charhandler.h
@@ -65,11 +65,11 @@ class CharHandler : public MessageHandler, public Net::CharHandler
void switchCharacter();
- int baseSprite() const;
+ unsigned int baseSprite() const;
- int hairSprite() const;
+ unsigned int hairSprite() const;
- int maxSprite() const;
+ unsigned int maxSprite() const;
void clear();
diff --git a/src/net/manaserv/chathandler.cpp b/src/net/manaserv/chathandler.cpp
index a452281f..147bab0a 100644
--- a/src/net/manaserv/chathandler.cpp
+++ b/src/net/manaserv/chathandler.cpp
@@ -21,13 +21,13 @@
#include "net/manaserv/chathandler.h"
+#include "actorspritemanager.h"
#include "being.h"
-#include "beingmanager.h"
#include "client.h"
#include "channel.h"
#include "channelmanager.h"
-
-#include "gui/chat.h"
+#include "event.h"
+#include "playerrelations.h"
#include "gui/widgets/channeltab.h"
@@ -149,22 +149,29 @@ void ChatHandler::handleGameChatMessage(Net::MessageIn &msg)
if (id == 0)
{
- localChatTab->chatLog(chatMsg, BY_SERVER);
+ SERVER_NOTICE(chatMsg)
return;
}
- Being *being = beingManager->findBeing(id);
+ Being *being = actorSpriteManager->findBeing(id);
std::string mes;
if (being)
{
mes = being->getName() + " : " + chatMsg;
- being->setSpeech(chatMsg, SPEECH_TIME);
}
else
mes = "Unknown : " + chatMsg;
- localChatTab->chatLog(mes, being == player_node ? BY_PLAYER : BY_OTHER);
+ Mana::Event event(being == player_node ? "Player" : "Being");
+ event.setString("message", mes);
+ event.setString("text", chatMsg);
+ event.setString("nick", being->getName());
+ event.setInt("beingId", id);
+ event.setInt("permissions", player_relations
+ .checkPermissionSilently(being->getName(),
+ PlayerRelation::SPEECH_LOG | PlayerRelation::SPEECH_FLOAT));
+ event.trigger("Chat");
}
void ChatHandler::handleEnterChannelResponse(Net::MessageIn &msg)
@@ -198,13 +205,13 @@ void ChatHandler::handleEnterChannelResponse(Net::MessageIn &msg)
}
else
{
- localChatTab->chatLog(_("Error joining channel."), BY_SERVER);
+ SERVER_NOTICE(_("Error joining channel."))
}
}
void ChatHandler::handleListChannelsResponse(Net::MessageIn &msg)
{
- localChatTab->chatLog(_("Listing channels."), BY_SERVER);
+ SERVER_NOTICE(_("Listing channels."))
while (msg.getUnreadLength())
{
std::string channelName = msg.readString();
@@ -214,9 +221,9 @@ void ChatHandler::handleListChannelsResponse(Net::MessageIn &msg)
numUsers << msg.readInt16();
channelName += " - ";
channelName += numUsers.str();
- localChatTab->chatLog(channelName, BY_SERVER);
+ SERVER_NOTICE(channelName)
}
- localChatTab->chatLog(_("End of channel list."), BY_SERVER);
+ SERVER_NOTICE(_("End of channel list."))
}
void ChatHandler::handlePrivateMessage(Net::MessageIn &msg)
@@ -224,13 +231,18 @@ void ChatHandler::handlePrivateMessage(Net::MessageIn &msg)
std::string userNick = msg.readString();
std::string chatMsg = msg.readString();
- chatWindow->whisper(userNick, chatMsg);
+ Mana::Event event("Whisper");
+ event.setString("nick", userNick);
+ event.setString("message", chatMsg);
+ event.trigger("Chat");
}
void ChatHandler::handleAnnouncement(Net::MessageIn &msg)
{
std::string chatMsg = msg.readString();
- localChatTab->chatLog(chatMsg, BY_GM);
+ Mana::Event event("Announcement");
+ event.setString("message", chatMsg);
+ event.trigger("Chat");
}
void ChatHandler::handleChatMessage(Net::MessageIn &msg)
@@ -341,7 +353,7 @@ void ChatHandler::handleWhoResponse(Net::MessageIn &msg)
{
break;
}
- localChatTab->chatLog(userNick, BY_SERVER);
+ SERVER_NOTICE(userNick)
}
}
diff --git a/src/net/manaserv/connection.cpp b/src/net/manaserv/connection.cpp
index fbd2ed22..b404191f 100644
--- a/src/net/manaserv/connection.cpp
+++ b/src/net/manaserv/connection.cpp
@@ -60,7 +60,7 @@ bool Connection::connect(const std::string &address, short port)
enetAddress.port = port;
// Initiate the connection, allocating channel 0.
-#ifdef ENET_VERSION_MAJOR
+#if defined(ENET_VERSION) && ENET_VERSION >= ENET_CUTOFF
mConnection = enet_host_connect(mClient, &enetAddress, 1, 0);
#else
mConnection = enet_host_connect(mClient, &enetAddress, 1);
diff --git a/src/net/manaserv/connection.h b/src/net/manaserv/connection.h
index b39f8957..808a6d40 100644
--- a/src/net/manaserv/connection.h
+++ b/src/net/manaserv/connection.h
@@ -26,6 +26,12 @@
#include <iosfwd>
+#ifdef ENET_VERSION_CREATE
+#define ENET_CUTOFF ENET_VERSION_CREATE(1,3,0)
+#else
+#define ENET_CUTOFF 0xFFFFFFFF
+#endif
+
namespace ManaServ
{
class MessageOut;
diff --git a/src/net/manaserv/defines.h b/src/net/manaserv/defines.h
new file mode 100644
index 00000000..e97866df
--- /dev/null
+++ b/src/net/manaserv/defines.h
@@ -0,0 +1,76 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MANASERV_DEFINES_H
+#define MANASERV_DEFINES_H
+
+/**
+ * Attributes used during combat. Available to all the beings.
+ */
+enum
+{
+BASE_ATTR_BEGIN = 0,
+ BASE_ATTR_PHY_ATK_MIN = BASE_ATTR_BEGIN,
+ BASE_ATTR_PHY_ATK_DELTA,
+ /**< Physical attack power. */
+ BASE_ATTR_MAG_ATK, /**< Magical attack power. */
+ BASE_ATTR_PHY_RES, /**< Resistance to physical damage. */
+ BASE_ATTR_MAG_RES, /**< Resistance to magical damage. */
+ BASE_ATTR_EVADE, /**< Ability to avoid hits. */
+ BASE_ATTR_HIT, /**< Ability to hit stuff. */
+ BASE_ATTR_HP, /**< Hit Points (Base value: maximum, Modded value: current) */
+ BASE_ATTR_HP_REGEN,/**< number of HP regenerated every 10 game ticks */
+ BASE_ATTR_END,
+ BASE_ATTR_NB = BASE_ATTR_END - BASE_ATTR_BEGIN,
+
+ BASE_ELEM_BEGIN = BASE_ATTR_END,
+ BASE_ELEM_NEUTRAL = BASE_ELEM_BEGIN,
+ BASE_ELEM_FIRE,
+ BASE_ELEM_WATER,
+ BASE_ELEM_EARTH,
+ BASE_ELEM_AIR,
+ BASE_ELEM_SACRED,
+ BASE_ELEM_DEATH,
+ BASE_ELEM_END,
+ BASE_ELEM_NB = BASE_ELEM_END - BASE_ELEM_BEGIN,
+
+ NB_BEING_ATTRIBUTES = BASE_ELEM_END
+};
+
+/**
+ * Attributes of characters. Used to derive being attributes.
+ */
+enum
+{
+ CHAR_ATTR_BEGIN = NB_BEING_ATTRIBUTES,
+ CHAR_ATTR_STRENGTH = CHAR_ATTR_BEGIN,
+ CHAR_ATTR_AGILITY,
+ CHAR_ATTR_DEXTERITY,
+ CHAR_ATTR_VITALITY,
+ CHAR_ATTR_INTELLIGENCE,
+ CHAR_ATTR_WILLPOWER,
+ CHAR_ATTR_END,
+ CHAR_ATTR_NB = CHAR_ATTR_END - CHAR_ATTR_BEGIN,
+
+ NB_CHARACTER_ATTRIBUTES = CHAR_ATTR_END
+};
+
+#endif // MANASERV_DEFINES_H
diff --git a/src/net/manaserv/effecthandler.cpp b/src/net/manaserv/effecthandler.cpp
index 27db9b59..c803b441 100644
--- a/src/net/manaserv/effecthandler.cpp
+++ b/src/net/manaserv/effecthandler.cpp
@@ -21,7 +21,7 @@
#include "net/manaserv/effecthandler.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
#include "effectmanager.h"
#include "log.h"
@@ -68,7 +68,7 @@ void EffectHandler::handleCreateEffectBeing(Net::MessageIn &msg)
{
int eid = msg.readInt16();
int bid = msg.readInt16();
- Being* b = beingManager->findBeing(bid);
+ Being* b = actorSpriteManager->findBeing(bid);
if (b)
effectManager->trigger(eid, b);
else
diff --git a/src/net/manaserv/gamehandler.cpp b/src/net/manaserv/gamehandler.cpp
index 5e29a896..3cb9f0ea 100644
--- a/src/net/manaserv/gamehandler.cpp
+++ b/src/net/manaserv/gamehandler.cpp
@@ -115,16 +115,6 @@ void GameHandler::disconnect()
chatHandler->disconnect();
}
-void GameHandler::inGame()
-{
- // TODO
-}
-
-void GameHandler::mapLoaded(const std::string &mapName)
-{
- // TODO
-}
-
void GameHandler::who()
{
// TODO
diff --git a/src/net/manaserv/gamehandler.h b/src/net/manaserv/gamehandler.h
index dde1748f..2e9f37fe 100644
--- a/src/net/manaserv/gamehandler.h
+++ b/src/net/manaserv/gamehandler.h
@@ -42,10 +42,6 @@ class GameHandler : public MessageHandler, public Net::GameHandler
void disconnect();
- void inGame();
-
- void mapLoaded(const std::string &mapName);
-
void who();
void quit(bool reconnectAccount);
@@ -53,12 +49,15 @@ class GameHandler : public MessageHandler, public Net::GameHandler
void quit() { quit(false); }
void ping(int tick);
-
+
bool removeDeadBeings() const { return false; }
void clear();
void gameLoading();
+
+ /** The ManaServ protocol doesn't use the MP status bar. */
+ bool canUseMagicBar() const { return false; }
};
} // namespace ManaServ
diff --git a/src/net/manaserv/generalhandler.cpp b/src/net/manaserv/generalhandler.cpp
index 0d3073f1..210e3043 100644
--- a/src/net/manaserv/generalhandler.cpp
+++ b/src/net/manaserv/generalhandler.cpp
@@ -90,6 +90,9 @@ GeneralHandler::GeneralHandler():
chatServerConnection = getConnection();
generalHandler = this;
+
+ listen("Client");
+ listen("Game");
}
void GeneralHandler::load()
@@ -163,38 +166,40 @@ void GeneralHandler::flushNetwork()
}
}
-void GeneralHandler::guiWindowsLoaded()
-{
- inventoryWindow->setSplitAllowed(true);
- skillDialog->loadSkills("mana-skills.xml");
- specialsWindow->loadSpecials("specials.xml");
-
- player_node->setExpNeeded(100);
-
- Stats::informStatusWindow();
-}
-
-void GeneralHandler::guiWindowsUnloaded()
-{
- // TODO
-}
-
void GeneralHandler::clearHandlers()
{
clearNetworkHandlers();
}
-void GeneralHandler::stateChanged(State oldState, State newState)
+void GeneralHandler::event(const std::string &channel,
+ const Mana::Event &event)
{
- if (newState == STATE_GAME)
+ if (channel == "Client")
{
- GameHandler *game = static_cast<GameHandler*>(Net::getGameHandler());
- game->gameLoading();
+ int newState = event.getInt("newState");
+
+ if (newState == STATE_GAME)
+ {
+ GameHandler *game = static_cast<GameHandler*>(Net::getGameHandler());
+ game->gameLoading();
+ }
+ else if (newState == STATE_LOAD_DATA)
+ {
+ Stats::load();
+ Stats::informItemDB();
+ }
}
- else if (newState == STATE_LOAD_DATA)
+ else if (channel == "Game")
{
- Stats::load();
- Stats::informItemDB();
+ if (event.getName() == "GuiWindowsLoaded")
+ {
+ inventoryWindow->setSplitAllowed(true);
+ skillDialog->loadSkills("mana-skills.xml");
+
+ PlayerInfo::setAttribute(EXP_NEEDED, 100);
+
+ Stats::informStatusWindow();
+ }
}
}
diff --git a/src/net/manaserv/generalhandler.h b/src/net/manaserv/generalhandler.h
index 58b95529..2a203e8c 100644
--- a/src/net/manaserv/generalhandler.h
+++ b/src/net/manaserv/generalhandler.h
@@ -22,6 +22,8 @@
#ifndef NET_MANASERV_GENERALHANDLER_H
#define NET_MANASERV_GENERALHANDLER_H
+#include "listener.h"
+
#include "net/generalhandler.h"
#include "net/net.h"
@@ -29,7 +31,7 @@
namespace ManaServ {
-class GeneralHandler : public Net::GeneralHandler
+class GeneralHandler : public Net::GeneralHandler, public Mana::Listener
{
public:
GeneralHandler();
@@ -42,13 +44,9 @@ class GeneralHandler : public Net::GeneralHandler
void flushNetwork();
- void guiWindowsLoaded();
-
- void guiWindowsUnloaded();
-
void clearHandlers();
- void stateChanged(State oldState, State newState);
+ void event(const std::string &channel, const Mana::Event &event);
protected:
MessageHandlerPtr mBeingHandler;
diff --git a/src/net/manaserv/guildhandler.cpp b/src/net/manaserv/guildhandler.cpp
index 253efb01..821d70bd 100644
--- a/src/net/manaserv/guildhandler.cpp
+++ b/src/net/manaserv/guildhandler.cpp
@@ -21,16 +21,17 @@
#include "net/manaserv/guildhandler.h"
+#include "event.h"
#include "guild.h"
#include "log.h"
#include "localplayer.h"
#include "channel.h"
#include "channelmanager.h"
-#include "gui/widgets/channeltab.h"
-#include "gui/chat.h"
#include "gui/socialwindow.h"
+#include "gui/widgets/channeltab.h"
+
#include "net/messagein.h"
#include "net/net.h"
@@ -78,12 +79,12 @@ void GuildHandler::handleMessage(Net::MessageIn &msg)
if (msg.readInt8() == ERRMSG_OK)
{
// TODO - Acknowledge guild was created
- localChatTab->chatLog(_("Guild created."));
+ SERVER_NOTICE(_("Guild created."))
joinedGuild(msg);
}
else
{
- localChatTab->chatLog(_("Error creating guild."));
+ SERVER_NOTICE(_("Error creating guild."))
}
} break;
@@ -93,7 +94,7 @@ void GuildHandler::handleMessage(Net::MessageIn &msg)
if (msg.readInt8() == ERRMSG_OK)
{
// TODO - Acknowledge invite was sent
- localChatTab->chatLog(_("Invite sent."));
+ SERVER_NOTICE(_("Invite sent."))
}
} break;
@@ -200,12 +201,12 @@ void GuildHandler::handleMessage(Net::MessageIn &msg)
if (msg.readInt8() == ERRMSG_OK)
{
// promotion succeeded
- localChatTab->chatLog(_("Member was promoted successfully."));
+ SERVER_NOTICE(_("Member was promoted successfully."))
}
else
{
// promotion failed
- localChatTab->chatLog(_("Failed to promote member."));
+ SERVER_NOTICE(_("Failed to promote member."))
}
}
@@ -275,9 +276,9 @@ void GuildHandler::invite(int guildId, const std::string &name)
chatServerConnection->send(msg);
}
-void GuildHandler::invite(int guildId, Player *player)
+void GuildHandler::invite(int guildId, Being *being)
{
- invite(guildId, player->getName());
+ invite(guildId, being->getName());
}
void GuildHandler::inviteResponse(int guildId, bool response)
diff --git a/src/net/manaserv/guildhandler.h b/src/net/manaserv/guildhandler.h
index 9929d135..bde677fb 100644
--- a/src/net/manaserv/guildhandler.h
+++ b/src/net/manaserv/guildhandler.h
@@ -41,7 +41,7 @@ public:
void invite(int guildId, const std::string &name);
- void invite(int guidId, Player *player);
+ void invite(int guidId, Being *being);
void inviteResponse(int guidId, bool response);
diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp
index 76fca7ae..8622627e 100644
--- a/src/net/manaserv/inventoryhandler.cpp
+++ b/src/net/manaserv/inventoryhandler.cpp
@@ -26,8 +26,7 @@
#include "item.h"
#include "itemshortcut.h"
#include "localplayer.h"
-
-#include "gui/chat.h"
+#include "playerinfo.h"
#include "net/manaserv/connection.h"
#include "net/manaserv/messagein.h"
@@ -36,8 +35,6 @@
#include "resources/iteminfo.h"
-#include "log.h" // <<< REMOVE ME!
-
extern Net::InventoryHandler *inventoryHandler;
namespace ManaServ {
@@ -60,8 +57,8 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
switch (msg.getId())
{
case GPMSG_INVENTORY_FULL:
- player_node->clearInventory();
- player_node->mEquipment->setBackend(&mEquips);
+ PlayerInfo::clearInventory();
+ PlayerInfo::getEquipment()->setBackend(&mEquips);
// no break!
case GPMSG_INVENTORY:
@@ -70,7 +67,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
unsigned int slot = msg.readInt8();
if (slot == 255)
{
- player_node->setMoney(msg.readInt32());
+ PlayerInfo::setAttribute(MONEY, msg.readInt32());
continue;
}
@@ -82,7 +79,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
else if (slot >= 32 && slot < 32 + getSize(Inventory::INVENTORY))
{
int amount = id ? msg.readInt8() : 0;
- player_node->setInvItem(slot - 32, id, amount);
+ PlayerInfo::setInventoryItem(slot - 32, id, amount);
}
};
break;
@@ -104,7 +101,6 @@ void InventoryHandler::unequipItem(const Item *item)
// Tidy equipment directly to avoid weapon still shown bug, for instance
int equipSlot = item->getInvIndex();
- logger->log("Unequipping %d", equipSlot);
mEquips.setEquipment(equipSlot, 0);
}
@@ -130,7 +126,7 @@ bool InventoryHandler::canSplit(const Item *item)
void InventoryHandler::splitItem(const Item *item, int amount)
{
- int newIndex = player_node->getInventory()->getFreeSlot();
+ int newIndex = PlayerInfo::getInventory()->getFreeSlot();
if (newIndex > Inventory::NO_SLOT_INDEX)
{
MessageOut msg(PGMSG_MOVE_ITEM);
@@ -149,7 +145,7 @@ void InventoryHandler::moveItem(int oldIndex, int newIndex)
MessageOut msg(PGMSG_MOVE_ITEM);
msg.writeInt8(oldIndex);
msg.writeInt8(newIndex);
- msg.writeInt8(player_node->getInventory()->getItem(oldIndex)
+ msg.writeInt8(PlayerInfo::getInventory()->getItem(oldIndex)
->getQuantity());
gameServerConnection->send(msg);
}
diff --git a/src/net/manaserv/itemhandler.cpp b/src/net/manaserv/itemhandler.cpp
index dc3b9f14..200e7fac 100644
--- a/src/net/manaserv/itemhandler.cpp
+++ b/src/net/manaserv/itemhandler.cpp
@@ -21,7 +21,7 @@
#include "net/manaserv/itemhandler.h"
-#include "flooritemmanager.h"
+#include "actorspritemanager.h"
#include "net/manaserv/protocol.h"
#include "net/manaserv/messagein.h"
@@ -62,8 +62,7 @@ void ItemHandler::handleMessage(Net::MessageIn &msg)
{
if (Map *map = game->getCurrentMap())
{
- floorItemManager->create(id,
- itemId,
+ actorSpriteManager->createItem(id, itemId,
x / map->getTileWidth(),
y / map->getTileHeight());
}
@@ -75,9 +74,9 @@ void ItemHandler::handleMessage(Net::MessageIn &msg)
}
}
}
- else if (FloorItem *item = floorItemManager->findById(id))
+ else if (FloorItem *item = actorSpriteManager->findItem(id))
{
- floorItemManager->destroy(item);
+ actorSpriteManager->destroy(item);
}
}
} break;
diff --git a/src/net/manaserv/network.cpp b/src/net/manaserv/network.cpp
index 636585c9..a5bf6186 100644
--- a/src/net/manaserv/network.cpp
+++ b/src/net/manaserv/network.cpp
@@ -53,7 +53,7 @@ void initialize()
logger->error("Failed to initialize ENet.");
}
-#ifdef ENET_VERSION_MAJOR
+#if defined(ENET_VERSION) && ENET_VERSION >= ENET_CUTOFF
client = enet_host_create(NULL, 3, 0, 0, 0);
#else
client = enet_host_create(NULL, 3, 0, 0);
diff --git a/src/net/manaserv/npchandler.cpp b/src/net/manaserv/npchandler.cpp
index 392ec4fd..f7e04c1b 100644
--- a/src/net/manaserv/npchandler.cpp
+++ b/src/net/manaserv/npchandler.cpp
@@ -21,17 +21,16 @@
#include "net/manaserv/npchandler.h"
-#include "beingmanager.h"
-#include "npc.h"
-
-#include "gui/npcdialog.h"
-#include "gui/npcpostdialog.h"
+#include "actorspritemanager.h"
+#include "event.h"
#include "net/manaserv/connection.h"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
#include "net/manaserv/protocol.h"
+#include "utils/stringutils.h"
+
extern Net::NpcHandler *npcHandler;
namespace ManaServ {
@@ -52,143 +51,131 @@ NpcHandler::NpcHandler()
};
handledMessages = _messages;
npcHandler = this;
+
+ listen("NPC");
}
void NpcHandler::handleMessage(Net::MessageIn &msg)
{
- Being *being = beingManager->findBeing(msg.readInt16());
- if (!being || being->getType() != Being::NPC)
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ if (!being || being->getType() != ActorSprite::NPC)
{
return;
}
- int npcId = being->getId();
- NpcDialogs::iterator diag = mNpcDialogs.find(npcId);
- NpcDialog *dialog;
-
- if (diag == mNpcDialogs.end())
- {
- if (msg.getId() == GPMSG_NPC_ERROR || msg.getId() == GPMSG_NPC_CLOSE)
- return; // Dialog is pointless in these cases
-
- dialog = new NpcDialog(npcId);
- Wrapper wrap;
- wrap.dialog = dialog;
- mNpcDialogs[npcId] = wrap;
- }
- else
- {
- dialog = diag->second.dialog;
- }
+ int npcId = being->getId(), count = 0;
+ Mana::Event *event = 0;
switch (msg.getId())
{
- case GPMSG_NPC_CHOICE:
- dialog->choiceRequest();
- while (msg.getUnreadLength())
- {
- dialog->addChoice(msg.readString());
- }
- break;
-
- case GPMSG_NPC_NUMBER:
+ case GPMSG_NPC_CHOICE:
+ event = new Mana::Event("Menu");
+ event->setInt("id", npcId);
+ while (msg.getUnreadLength())
{
- int min_num = msg.readInt32();
- int max_num = msg.readInt32();
- dialog->integerRequest(msg.readInt32(), min_num, max_num);
- break;
+ count++;
+ event->setString("choice" + toString(count), msg.readString());
}
-
- case GPMSG_NPC_STRING:
- dialog->textRequest("");
- break;
-
- case GPMSG_NPC_POST:
- {
- new NpcPostDialog(npcId);
- break;
- }
-
- case GPMSG_NPC_ERROR:
- dialog->close();
- if (diag != mNpcDialogs.end())
- {
- mNpcDialogs.erase(diag);
- }
- break;
-
- case GPMSG_NPC_MESSAGE:
- dialog->addText(msg.readString(msg.getUnreadLength()));
- dialog->showNextButton();
- break;
-
- case GPMSG_NPC_CLOSE:
- dialog->showCloseButton();
- break;
+ event->setInt("choiceCount", count);
+ event->trigger("NPC");
+ break;
+
+ case GPMSG_NPC_NUMBER:
+ event = new Mana::Event("IntegerInput");
+ event->setInt("id", npcId);
+ event->setInt("min", msg.readInt32());
+ event->setInt("max", msg.readInt32());
+ event->setInt("default", msg.readInt32());
+ event->trigger("NPC");
+ break;
+
+ case GPMSG_NPC_STRING:
+ event = new Mana::Event("StringInput");
+ event->setInt("id", npcId);
+ event->trigger("NPC");
+ break;
+
+ case GPMSG_NPC_POST:
+ event = new Mana::Event("Post");
+ event->setInt("id", npcId);
+ event->trigger("NPC");
+ break;
+
+ case GPMSG_NPC_ERROR:
+ event = new Mana::Event("End");
+ event->setInt("id", npcId);
+ event->trigger("NPC");
+ break;
+
+ case GPMSG_NPC_MESSAGE:
+ event = new Mana::Event("Message");
+ event->setInt("id", npcId);
+ event->setString("text", msg.readString(msg.getUnreadLength()));
+ event->trigger("NPC");
+ delete event;
+
+ event = new Mana::Event("Next");
+ event->setInt("id", npcId);
+ event->trigger("NPC");
+ break;
+
+ case GPMSG_NPC_CLOSE:
+ event = new Mana::Event("Close");
+ event->setInt("id", npcId);
+ event->trigger("NPC");
+ break;
}
-}
-void NpcHandler::talk(int npcId)
-{
- MessageOut msg(PGMSG_NPC_TALK);
- msg.writeInt16(npcId);
- gameServerConnection->send(msg);
-}
-
-void NpcHandler::nextDialog(int npcId)
-{
- MessageOut msg(PGMSG_NPC_TALK_NEXT);
- msg.writeInt16(npcId);
- gameServerConnection->send(msg);
+ delete event;
}
-void NpcHandler::closeDialog(int npcId)
+void NpcHandler::event(const std::string &channel, const Mana::Event &event)
{
- MessageOut msg(PGMSG_NPC_TALK_NEXT);
- msg.writeInt16(npcId);
- gameServerConnection->send(msg);
-
- NpcDialogs::iterator it = mNpcDialogs.find(npcId);
- if (it != mNpcDialogs.end())
+ if (channel == "NPC")
{
- (*it).second.dialog->close();
- mNpcDialogs.erase(it);
+ if (event.getName() == "doTalk")
+ {
+ MessageOut msg(PGMSG_NPC_TALK);
+ msg.writeInt16(event.getInt("npcId"));
+ gameServerConnection->send(msg);
+ }
+ else if (event.getName() == "doNext" || event.getName() == "doClose")
+ {
+ MessageOut msg(PGMSG_NPC_TALK_NEXT);
+ msg.writeInt16(event.getInt("npcId"));
+ gameServerConnection->send(msg);
+ }
+ else if (event.getName() == "doMenu")
+ {
+ MessageOut msg(PGMSG_NPC_SELECT);
+ msg.writeInt16(event.getInt("npcId"));
+ msg.writeInt8(event.getInt("choice"));
+ gameServerConnection->send(msg);
+ }
+ else if (event.getName() == "doIntegerInput")
+ {
+ MessageOut msg(PGMSG_NPC_NUMBER);
+ msg.writeInt16(event.getInt("npcId"));
+ msg.writeInt32(event.getInt("value"));
+ gameServerConnection->send(msg);
+ }
+ else if (event.getName() == "doStringInput")
+ {
+ MessageOut msg(PGMSG_NPC_STRING);
+ msg.writeInt16(event.getInt("npcId"));
+ msg.writeString(event.getString("value"));
+ gameServerConnection->send(msg);
+ }
+ else if (event.getName() == "doSendLetter")
+ {
+ MessageOut msg(PGMSG_NPC_POST_SEND);
+ msg.writeString(event.getString("recipient"));
+ msg.writeString(event.getString("text"));
+ gameServerConnection->send(msg);
+ }
}
}
-void NpcHandler::listInput(int npcId, int value)
-{
- MessageOut msg(PGMSG_NPC_SELECT);
- msg.writeInt16(npcId);
- msg.writeInt8(value);
- gameServerConnection->send(msg);
-}
-
-void NpcHandler::integerInput(int npcId, int value)
-{
- MessageOut msg(PGMSG_NPC_NUMBER);
- msg.writeInt16(npcId);
- msg.writeInt32(value);
- gameServerConnection->send(msg);
-}
-
-void NpcHandler::stringInput(int npcId, const std::string &value)
-{
- MessageOut msg(PGMSG_NPC_STRING);
- msg.writeInt16(npcId);
- msg.writeString(value);
- gameServerConnection->send(msg);
-}
-
-void NpcHandler::sendLetter(int npcId, const std::string &recipient,
- const std::string &text)
-{
- MessageOut msg(PGMSG_NPC_POST_SEND);
- msg.writeString(recipient);
- msg.writeString(text);
- gameServerConnection->send(msg);
-}
-
void NpcHandler::startShopping(int beingId)
{
// TODO
@@ -225,9 +212,4 @@ void NpcHandler::endShopping(int beingId)
// TODO
}
-void NpcHandler::clearDialogs()
-{
- mNpcDialogs.clear();
-}
-
} // namespace ManaServ
diff --git a/src/net/manaserv/npchandler.h b/src/net/manaserv/npchandler.h
index 689fdc1d..14e8a50a 100644
--- a/src/net/manaserv/npchandler.h
+++ b/src/net/manaserv/npchandler.h
@@ -22,37 +22,25 @@
#ifndef NET_MANASERV_NPCHANDLER_H
#define NET_MANASERV_NPCHANDLER_H
+#include "listener.h"
+
#include "net/npchandler.h"
#include "net/manaserv/messagehandler.h"
#include <map>
-class NpcDialog;
-
namespace ManaServ {
-class NpcHandler : public MessageHandler, public Net::NpcHandler
+class NpcHandler : public MessageHandler, public Net::NpcHandler,
+ public Mana::Listener
{
public:
NpcHandler();
void handleMessage(Net::MessageIn &msg);
- void talk(int npcId);
-
- void nextDialog(int npcId);
-
- void closeDialog(int npcId);
-
- void listInput(int npcId, int value);
-
- void integerInput(int npcId, int value);
-
- void stringInput(int npcId, const std::string &value);
-
- void sendLetter(int npcId, const std::string &recipient,
- const std::string &text);
+ void event(const std::string &channel, const Mana::Event &event);
void startShopping(int beingId);
@@ -65,15 +53,6 @@ class NpcHandler : public MessageHandler, public Net::NpcHandler
void sellItem(int beingId, int itemId, int amount);
void endShopping(int beingId);
-
- void clearDialogs();
-
- private:
- typedef struct {
- NpcDialog* dialog;
- } Wrapper;
- typedef std::map<int, Wrapper> NpcDialogs;
- NpcDialogs mNpcDialogs;
};
} // namespace ManaServ
diff --git a/src/net/manaserv/partyhandler.cpp b/src/net/manaserv/partyhandler.cpp
index ec153fa8..370d6496 100644
--- a/src/net/manaserv/partyhandler.cpp
+++ b/src/net/manaserv/partyhandler.cpp
@@ -21,13 +21,12 @@
#include "net/manaserv/partyhandler.h"
+#include "event.h"
#include "log.h"
#include "localplayer.h"
#include "gui/socialwindow.h"
-#include "gui/widgets/chattab.h"
-
#include "net/manaserv/connection.h"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
@@ -85,7 +84,7 @@ void PartyHandler::handleMessage(Net::MessageIn &msg)
if (msg.readInt8() == ERRMSG_OK)
{
//
- localChatTab->chatLog(_("Joined party."));
+ SERVER_NOTICE(_("Joined party."));
}
}
@@ -103,7 +102,7 @@ void PartyHandler::handleMessage(Net::MessageIn &msg)
int id = msg.readInt16(); // being id
std::string name = msg.readString();
- localChatTab->chatLog(strprintf(_("%s joined the party."),
+ SERVER_NOTICE(strprintf(_("%s joined the party."),
name.c_str()));
if (id == player_node->getId())
@@ -120,8 +119,8 @@ void PartyHandler::handleMessage(Net::MessageIn &msg)
case CPMSG_PARTY_REJECTED:
{
std::string name = msg.readString();
- localChatTab->chatLog(strprintf(_("%s rejected your invite."),
- name.c_str()));
+ SERVER_NOTICE(strprintf(
+ _("%s rejected your invite."), name.c_str()));
} break;
}
}
@@ -136,9 +135,9 @@ void PartyHandler::join(int partyId)
// TODO
}
-void PartyHandler::invite(Player *player)
+void PartyHandler::invite(Being *being)
{
- invite(player->getName());
+ invite(being->getName());
}
void PartyHandler::invite(const std::string &name)
@@ -167,7 +166,7 @@ void PartyHandler::leave()
chatServerConnection->send(msg);
}
-void PartyHandler::kick(Player *player)
+void PartyHandler::kick(Being *being)
{
// TODO
}
diff --git a/src/net/manaserv/partyhandler.h b/src/net/manaserv/partyhandler.h
index 0777b49e..29dc280d 100644
--- a/src/net/manaserv/partyhandler.h
+++ b/src/net/manaserv/partyhandler.h
@@ -43,7 +43,7 @@ public:
void join(int partyId);
- void invite(Player *player);
+ void invite(Being *being);
void invite(const std::string &name);
@@ -51,7 +51,7 @@ public:
void leave();
- void kick(Player *player);
+ void kick(Being *being);
void kick(const std::string &name);
diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp
index 33367927..db2dcf7a 100644
--- a/src/net/manaserv/playerhandler.cpp
+++ b/src/net/manaserv/playerhandler.cpp
@@ -24,14 +24,14 @@
#include "client.h"
#include "effectmanager.h"
+#include "event.h"
#include "game.h"
#include "localplayer.h"
#include "log.h"
#include "particle.h"
-#include "npc.h"
+#include "playerinfo.h"
#include "configuration.h"
-#include "gui/chat.h"
#include "gui/gui.h"
#include "gui/okdialog.h"
#include "gui/viewport.h"
@@ -39,9 +39,9 @@
#include "net/net.h"
#include "net/manaserv/connection.h"
+#include "net/manaserv/defines.h"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
-#include "net/manaserv/npchandler.h"
#include "net/manaserv/protocol.h"
/**
@@ -64,9 +64,7 @@ void RespawnRequestListener::action(const gcn::ActionEvent &event)
{
Net::getPlayerHandler()->respawn();
- ManaServ::NpcHandler *handler =
- static_cast<ManaServ::NpcHandler*>(Net::getNpcHandler());
- handler->clearDialogs();
+ Mana::Event::trigger("NPC", "CloseAll");
}
PlayerHandler::PlayerHandler()
@@ -122,13 +120,13 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
if (stat == BASE_ATTR_HP)
{
- player_node->setMaxHp(base);
- player_node->setHp(value);
+ PlayerInfo::setAttribute(MAX_HP, base);
+ PlayerInfo::setAttribute(HP, value);
}
else
{
- player_node->setAttributeBase(stat, base);
- player_node->setAttributeEffective(stat, value);
+ PlayerInfo::setStatBase(stat, base);
+ PlayerInfo::setStatMod(stat, value - base);
}
}
} break;
@@ -142,26 +140,26 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
int current = msg.readInt32();
int next = msg.readInt32();
- player_node->setExperience(skill, current, next);
+ PlayerInfo::setStatExperience(skill, current, next);
}
} break;
case GPMSG_LEVELUP:
{
- player_node->setLevel(msg.readInt16());
- player_node->setCharacterPoints(msg.readInt16());
- player_node->setCorrectionPoints(msg.readInt16());
+ PlayerInfo::setAttribute(LEVEL, msg.readInt16());
+ PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16());
+ PlayerInfo::setAttribute(CORR_POINTS, msg.readInt16());
Particle* effect = particleEngine->addEffect(
- paths.getValue("particles", "graphics/particles/")
- + paths.getValue("levelUpEffectFile", "levelup.particle.xml"),
- 0, 0);
+ paths.getStringValue("particles")
+ + paths.getStringValue("levelUpEffectFile")
+ ,0, 0);
player_node->controlParticle(effect);
} break;
case GPMSG_LEVEL_PROGRESS:
{
- player_node->setExp(msg.readInt8(), false);
+ PlayerInfo::setAttribute(EXP, msg.readInt8());
} break;
@@ -185,18 +183,19 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
// has to be correct. The server is always right!
// undo attribute change and set points to 0
logger->log("Warning: Server denied increase of attribute %d (no points left) ", attrNum);
- int attrValue = player_node->getAttributeBase(attrNum) - 1;
- player_node->setCharacterPoints(0);
- player_node->setAttributeBase(attrNum, attrValue);
+ int attrValue = PlayerInfo::getStatBase(attrNum) - 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, 0);
+ PlayerInfo::setStatBase(attrNum, attrValue);
} break;
case ATTRIBMOD_DENIED:
{
// undo attribute change
logger->log("Warning: Server denied increase of attribute %d (reason unknown) ", attrNum);
- int points = player_node->getCharacterPoints() - 1;
- player_node->setCharacterPoints(points);
- int attrValue = player_node->getAttributeBase(attrNum) - 1;
- player_node->setAttributeBase(attrNum, attrValue);
+ int points = PlayerInfo::getAttribute(CHAR_POINTS) - 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, points);
+
+ int attrValue = PlayerInfo::getStatBase(attrNum) - 1;
+ PlayerInfo::setStatBase(attrNum, attrValue);
} break;
}
} break;
@@ -221,21 +220,23 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
// has to be correct. The server is always right!
// undo attribute change and set points to 0
logger->log("Warning: Server denied reduction of attribute %d (no points left) ", attrNum);
- int attrValue = player_node->getAttributeBase(attrNum) + 1;
- player_node->setCorrectionPoints(0);
- player_node->setAttributeBase(attrNum, attrValue);
+ int attrValue = PlayerInfo::getStatBase(attrNum) + 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, 0);
+ PlayerInfo::setStatBase(attrNum, attrValue);
break;
} break;
case ATTRIBMOD_DENIED:
{
// undo attribute change
logger->log("Warning: Server denied reduction of attribute %d (reason unknown) ", attrNum);
- int charaPoints = player_node->getCharacterPoints() - 1;
- player_node->setCharacterPoints(charaPoints);
- int correctPoints = player_node->getCorrectionPoints() + 1;
- player_node->setCorrectionPoints(correctPoints);
- int attrValue = player_node->getAttributeBase(attrNum) + 1;
- player_node->setAttributeBase(attrNum, attrValue);
+ int charaPoints = PlayerInfo::getAttribute(CHAR_POINTS) - 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, charaPoints);
+
+ int correctPoints = PlayerInfo::getAttribute(CORR_POINTS) + 1;
+ PlayerInfo::setAttribute(CORR_POINTS, correctPoints);
+
+ int attrValue = PlayerInfo::getStatBase(attrNum) + 1;
+ PlayerInfo::setStatBase(attrNum, attrValue);
} break;
}
@@ -250,7 +251,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
int current = msg.readInt32();
int max = msg.readInt32();
int recharge = msg.readInt32();
- player_node->setSpecialStatus(id, current, max, recharge);
+ PlayerInfo::setSpecialStatus(id, current, max, recharge);
}
} break;
/*
@@ -343,11 +344,14 @@ void PlayerHandler::increaseSkill(int skillId)
void PlayerHandler::pickUp(FloorItem *floorItem)
{
- int id = floorItem->getId();
- MessageOut msg(PGMSG_PICKUP);
- msg.writeInt16(id >> 16);
- msg.writeInt16(id & 0xFFFF);
- gameServerConnection->send(msg);
+ if (floorItem)
+ {
+ int id = floorItem->getId();
+ MessageOut msg(PGMSG_PICKUP);
+ msg.writeInt16(id >> 16);
+ msg.writeInt16(id & 0xFFFF);
+ gameServerConnection->send(msg);
+ }
}
void PlayerHandler::setDirection(char direction)
diff --git a/src/net/manaserv/tradehandler.cpp b/src/net/manaserv/tradehandler.cpp
index 234a18d6..30ff6890 100644
--- a/src/net/manaserv/tradehandler.cpp
+++ b/src/net/manaserv/tradehandler.cpp
@@ -21,15 +21,15 @@
#include "net/manaserv/tradehandler.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
+#include "event.h"
#include "item.h"
#include "localplayer.h"
+#include "playerinfo.h"
#include "gui/confirmdialog.h"
#include "gui/trade.h"
-#include "gui/widgets/chattab.h"
-
#include "net/net.h"
#include "net/manaserv/connection.h"
@@ -86,16 +86,15 @@ TradeHandler::TradeHandler():
};
handledMessages = _messages;
tradeHandler = this;
-
}
void TradeHandler::setAcceptTradeRequests(bool acceptTradeRequests)
{
mAcceptTradeRequests = acceptTradeRequests;
if (mAcceptTradeRequests)
- localChatTab->chatLog(_("Accepting incoming trade requests."), BY_SERVER);
+ SERVER_NOTICE(_("Accepting incoming trade requests."))
else
- localChatTab->chatLog(_("Ignoring incoming trade requests."), BY_SERVER);
+ SERVER_NOTICE(_("Ignoring incoming trade requests."))
}
void TradeHandler::handleMessage(Net::MessageIn &msg)
@@ -104,13 +103,13 @@ void TradeHandler::handleMessage(Net::MessageIn &msg)
{
case GPMSG_TRADE_REQUEST:
{
- Being *being = beingManager->findBeing(msg.readInt16());
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
if (!being || !mAcceptTradeRequests)
{
respond(false);
break;
}
- player_node->setTrading(true);
+ PlayerInfo::setTrading(true);
tradePartnerName = being->getName();
tradePartnerID = being->getId();
ConfirmDialog *dlg = new ConfirmDialog(_("Request for Trade"),
@@ -144,19 +143,19 @@ void TradeHandler::handleMessage(Net::MessageIn &msg)
case GPMSG_TRADE_AGREED:
tradeWindow->receivedOk(false);
break;
-
+
case GPMSG_TRADE_CANCEL:
- localChatTab->chatLog(_("Trade canceled."), BY_SERVER);
+ SERVER_NOTICE(_("Trade canceled."))
tradeWindow->setVisible(false);
tradeWindow->reset();
- player_node->setTrading(false);
+ PlayerInfo::setTrading(false);
break;
case GPMSG_TRADE_COMPLETE:
- localChatTab->chatLog(_("Trade completed."), BY_SERVER);
+ SERVER_NOTICE(_("Trade completed."))
tradeWindow->setVisible(false);
tradeWindow->reset();
- player_node->setTrading(false);
+ PlayerInfo::setTrading(false);
break;
}
}
@@ -177,7 +176,7 @@ void TradeHandler::respond(bool accept)
gameServerConnection->send(msg);
if (!accept)
- player_node->setTrading(false);
+ PlayerInfo::setTrading(false);
}
void TradeHandler::addItem(Item *item, int amount)
diff --git a/src/net/npchandler.h b/src/net/npchandler.h
index bba8dc31..fb8ab7ec 100644
--- a/src/net/npchandler.h
+++ b/src/net/npchandler.h
@@ -29,20 +29,7 @@ namespace Net {
class NpcHandler
{
public:
- virtual void talk(int npcId) = 0;
-
- virtual void nextDialog(int npcId) = 0;
-
- virtual void closeDialog(int npcId) = 0;
-
- virtual void listInput(int npcId, int value) = 0;
-
- virtual void integerInput(int npcId, int value) = 0;
-
- virtual void stringInput(int npcId, const std::string &value) = 0;
-
- virtual void sendLetter(int npcId, const std::string &recipient,
- const std::string &text) = 0;
+ virtual ~NpcHandler() {}
virtual void startShopping(int beingId) = 0;
@@ -55,8 +42,6 @@ class NpcHandler
virtual void sellItem(int beingId, int itemId, int amount) = 0;
virtual void endShopping(int beingId) = 0;
-
- virtual ~NpcHandler() {}
};
} // namespace Net
diff --git a/src/net/partyhandler.h b/src/net/partyhandler.h
index dd1103fc..7ca13546 100644
--- a/src/net/partyhandler.h
+++ b/src/net/partyhandler.h
@@ -24,7 +24,7 @@
#include <string>
-class Player;
+class Being;
enum PartyShare {
PARTY_SHARE_UNKNOWN = -1,
@@ -38,11 +38,13 @@ namespace Net {
class PartyHandler
{
public:
+ virtual ~PartyHandler() {}
+
virtual void create(const std::string &name = "") = 0;
virtual void join(int partyId) = 0;
- virtual void invite(Player *player) = 0;
+ virtual void invite(Being *player) = 0;
virtual void invite(const std::string &name) = 0;
@@ -50,7 +52,7 @@ class PartyHandler
virtual void leave() = 0;
- virtual void kick(Player *player) = 0;
+ virtual void kick(Being *player) = 0;
virtual void kick(const std::string &name) = 0;
@@ -69,8 +71,6 @@ class PartyHandler
// virtual void options() = 0;
// virtual void message() = 0;
-
- virtual ~PartyHandler() {}
};
} // namespace Net
diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h
index 399afb5e..b3534b83 100644
--- a/src/net/playerhandler.h
+++ b/src/net/playerhandler.h
@@ -31,6 +31,8 @@ namespace Net {
class PlayerHandler
{
public:
+ virtual ~PlayerHandler() {}
+
virtual void attack(int id) = 0;
virtual void emote(int emoteId) = 0;
@@ -62,8 +64,6 @@ class PlayerHandler
virtual int getJobLocation() = 0;
virtual Vector getDefaultWalkSpeed() = 0;
-
- virtual ~PlayerHandler() {}
};
} // namespace Net
diff --git a/src/net/specialhandler.h b/src/net/specialhandler.h
index 21e3a4b7..89fcdf7d 100644
--- a/src/net/specialhandler.h
+++ b/src/net/specialhandler.h
@@ -28,6 +28,8 @@ namespace Net {
class SpecialHandler
{
public:
+ virtual ~SpecialHandler () {}
+
virtual void use(int id) = 0;
virtual void use(int id, int level, int beingId) = 0;
@@ -35,8 +37,6 @@ class SpecialHandler
virtual void use(int id, int level, int x, int y) = 0;
virtual void use(int id, const std::string &map) = 0;
-
- virtual ~SpecialHandler () {}
};
}
diff --git a/src/net/tmwa/adminhandler.cpp b/src/net/tmwa/adminhandler.cpp
index e56d5a44..b72c2a13 100644
--- a/src/net/tmwa/adminhandler.cpp
+++ b/src/net/tmwa/adminhandler.cpp
@@ -21,13 +21,12 @@
#include "net/tmwa/adminhandler.h"
+#include "actorspritemanager.h"
#include "being.h"
-#include "beingmanager.h"
+#include "event.h"
#include "game.h"
#include "playerrelations.h"
-#include "gui/widgets/chattab.h"
-
#include "net/chathandler.h"
#include "net/net.h"
@@ -60,9 +59,9 @@ void AdminHandler::handleMessage(Net::MessageIn &msg)
case SMSG_ADMIN_KICK_ACK:
id = msg.readInt32();
if (id == 0)
- localChatTab->chatLog(_("Kick failed!"), BY_SERVER);
+ SERVER_NOTICE(_("Kick failed!"))
else
- localChatTab->chatLog(_("Kick succeeded!"), BY_SERVER);
+ SERVER_NOTICE(_("Kick succeeded!"))
break;
}
}
diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp
index 04690c50..543beec2 100644
--- a/src/net/tmwa/beinghandler.cpp
+++ b/src/net/tmwa/beinghandler.cpp
@@ -21,14 +21,13 @@
#include "net/tmwa/beinghandler.h"
+#include "actorspritemanager.h"
#include "being.h"
-#include "beingmanager.h"
#include "client.h"
#include "effectmanager.h"
#include "guild.h"
#include "localplayer.h"
#include "log.h"
-#include "npc.h"
#include "party.h"
#include "playerrelations.h"
@@ -74,19 +73,19 @@ BeingHandler::BeingHandler(bool enableSync):
Being *createBeing(int id, short job)
{
- Being::Type type = Being::UNKNOWN;
+ ActorSprite::Type type = ActorSprite::UNKNOWN;
if (job <= 25 || (job >= 4001 && job <= 4049))
- type = Being::PLAYER;
+ type = ActorSprite::PLAYER;
else if (job >= 46 && job <= 1000)
- type = Being::NPC;
+ type = ActorSprite::NPC;
else if (job > 1000 && job <= 2000)
- type = Being::MONSTER;
+ type = ActorSprite::MONSTER;
else if (job == 45)
return NULL; // Skip portals
- Being *being = beingManager->createBeing(id, type, job);
+ Being *being = actorSpriteManager->createBeing(id, type, job);
- if (type == Being::PLAYER || type == Being::NPC)
+ if (type == ActorSprite::PLAYER || type == ActorSprite::NPC)
{
MessageOut outMsg(0x0094);
outMsg.writeInt32(id);//readLong(2));
@@ -97,7 +96,7 @@ Being *createBeing(int id, short job)
void BeingHandler::handleMessage(Net::MessageIn &msg)
{
- if (!beingManager)
+ if (!actorSpriteManager)
return;
int id;
@@ -112,7 +111,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
int type, guild;
Uint16 status;
Being *srcBeing, *dstBeing;
- Player *player = 0;
int hairStyle, hairColor, flag;
std::string player_followed;
@@ -128,7 +126,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
statusEffects |= ((Uint32)msg.readInt16()) << 16; // option
job = msg.readInt16(); // class
- dstBeing = beingManager->findBeing(id);
+ dstBeing = actorSpriteManager->findBeing(id);
if (!dstBeing)
{
@@ -145,14 +143,10 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
break;
}
- if (dstBeing->getType() == Being::PLAYER)
- player = static_cast<Player*>(dstBeing);
-
- if (msg.getId() == 0x0078)
+ if (msg.getId() == SMSG_BEING_VISIBLE)
{
dstBeing->clearPath();
- dstBeing->setFrame(0);
- dstBeing->setWalkTime(tick_time);
+ dstBeing->setActionTime(tick_time);
dstBeing->setAction(Being::STAND);
}
@@ -178,16 +172,13 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
shoes = msg.readInt16(); // clothes color - "abused" as shoes
gloves = msg.readInt16(); // head dir - "abused" as gloves
guild = msg.readInt32(); // guild
- if (player)
+ if (guild == 0)
{
- if (guild == 0)
- {
- player->clearGuilds();
- }
- else
- {
- player->addGuild(Guild::getGuild(guild));
- }
+ dstBeing->clearGuilds();
+ }
+ else
+ {
+ dstBeing->addGuild(Guild::getGuild(guild));
}
msg.readInt16(); // guild emblem
msg.readInt16(); // manner
@@ -195,19 +186,19 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
msg.readInt8(); // karma
gender = msg.readInt8();
- if (player)
+ if (dstBeing->getType() == ActorSprite::PLAYER)
{
- player->setGender((gender == 0)
- ? GENDER_FEMALE : GENDER_MALE);
+ dstBeing->setGender((gender == 0)
+ ? GENDER_FEMALE : GENDER_MALE);
// Set these after the gender, as the sprites may be gender-specific
- player->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(hairColor));
- player->setSprite(SPRITE_BOTTOMCLOTHES, headBottom);
- player->setSprite(SPRITE_TOPCLOTHES, headMid);
- player->setSprite(SPRITE_HAT, headTop);
- player->setSprite(SPRITE_SHOE, shoes);
- player->setSprite(SPRITE_GLOVES, gloves);
- player->setSprite(SPRITE_WEAPON, weapon, "", true);
- player->setSprite(SPRITE_SHIELD, shield);
+ dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(hairColor));
+ dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom);
+ dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid);
+ dstBeing->setSprite(SPRITE_HAT, headTop);
+ dstBeing->setSprite(SPRITE_SHOE, shoes);
+ dstBeing->setSprite(SPRITE_GLOVES, gloves);
+ dstBeing->setSprite(SPRITE_WEAPON, weapon, "", true);
+ dstBeing->setSprite(SPRITE_SHIELD, shield);
}
if (msg.getId() == SMSG_BEING_MOVE)
@@ -242,11 +233,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
* 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
+ dstBeing = actorSpriteManager->findBeing(msg.readInt32());
/*
* This packet doesn't have enough info to actually
@@ -254,21 +241,23 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
* we'll just pretend the packet didn't happen
*/
- if (dstBeing)
- {
- dstBeing->setAction(Being::STAND);
- dstBeing->setTileCoords(srcX, srcY);
- dstBeing->setDestination(dstX, dstY);
- }
+ if (!dstBeing)
+ break;
+
+ Uint16 srcX, srcY, dstX, dstY;
+ msg.readCoordinatePair(srcX, srcY, dstX, dstY);
+ msg.readInt32(); // Server tick
+
+ dstBeing->setAction(Being::STAND);
+ dstBeing->setTileCoords(srcX, srcY);
+ dstBeing->setDestination(dstX, dstY);
break;
case SMSG_BEING_REMOVE:
// A being should be removed or has died
id = msg.readInt32();
-
- dstBeing = beingManager->findBeing(id);
-
+ dstBeing = actorSpriteManager->findBeing(id);
if (!dstBeing)
break;
@@ -289,16 +278,14 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
if (msg.readInt8() == 1)
dstBeing->setAction(Being::DEAD);
else
- beingManager->destroyBeing(dstBeing);
+ actorSpriteManager->destroy(dstBeing);
break;
case SMSG_BEING_RESURRECT:
// A being changed mortality status
id = msg.readInt32();
-
- dstBeing = beingManager->findBeing(id);
-
+ dstBeing = actorSpriteManager->findBeing(id);
if (!dstBeing)
break;
@@ -313,8 +300,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
case SMSG_SKILL_DAMAGE:
msg.readInt16(); // Skill Id
- srcBeing = beingManager->findBeing(msg.readInt32());
- dstBeing = beingManager->findBeing(msg.readInt32());
+ srcBeing = actorSpriteManager->findBeing(msg.readInt32());
+ dstBeing = actorSpriteManager->findBeing(msg.readInt32());
msg.readInt32(); // Server tick
msg.readInt32(); // src speed
msg.readInt32(); // dst speed
@@ -329,8 +316,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
break;
case SMSG_BEING_ACTION:
- srcBeing = beingManager->findBeing(msg.readInt32());
- dstBeing = beingManager->findBeing(msg.readInt32());
+ srcBeing = actorSpriteManager->findBeing(msg.readInt32());
+ dstBeing = actorSpriteManager->findBeing(msg.readInt32());
msg.readInt32(); // server tick
msg.readInt32(); // src speed
msg.readInt32(); // dst speed
@@ -357,7 +344,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
case 0x02: // Sit
if (srcBeing)
{
- srcBeing->setFrame(0);
srcBeing->setAction(Being::SIT);
}
break;
@@ -365,7 +351,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
case 0x03: // Stand up
if (srcBeing)
{
- srcBeing->setFrame(0);
srcBeing->setAction(Being::STAND);
}
break;
@@ -374,19 +359,18 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
case SMSG_BEING_SELFEFFECT: {
id = (Uint32)msg.readInt32();
- if (!beingManager->findBeing(id))
+ Being* being = actorSpriteManager->findBeing(id);
+ if (!being)
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())))
+ if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
{
break;
}
@@ -415,14 +399,11 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
* 16 bit value will be 0.
*/
- if (!(dstBeing = beingManager->findBeing(msg.readInt32())))
+ if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
{
break;
}
- if (dstBeing->getType() == Being::PLAYER)
- player = static_cast<Player*>(dstBeing);
-
int type = msg.readInt8();
int id = 0;
int id2 = 0;
@@ -440,41 +421,41 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
switch (type)
{
case 1: // eAthena LOOK_HAIR
- player->setSpriteID(SPRITE_HAIR, id *-1);
+ dstBeing->setSpriteID(SPRITE_HAIR, id *-1);
break;
case 2: // Weapon ID in id, Shield ID in id2
- player->setSprite(SPRITE_WEAPON, id, "", true);
- player->setSprite(SPRITE_SHIELD, id2);
+ dstBeing->setSprite(SPRITE_WEAPON, id, "", true);
+ dstBeing->setSprite(SPRITE_SHIELD, id2);
break;
case 3: // Change lower headgear for eAthena, pants for us
- player->setSprite(SPRITE_BOTTOMCLOTHES, id);
+ dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, id);
break;
case 4: // Change upper headgear for eAthena, hat for us
- player->setSprite(SPRITE_HAT, id);
+ dstBeing->setSprite(SPRITE_HAT, id);
break;
case 5: // Change middle headgear for eathena, armor for us
- player->setSprite(SPRITE_TOPCLOTHES, id);
+ dstBeing->setSprite(SPRITE_TOPCLOTHES, id);
break;
case 6: // eAthena LOOK_HAIR_COLOR
- player->setSpriteColor(SPRITE_HAIR, ColorDB::get(id));
+ dstBeing->setSpriteColor(SPRITE_HAIR, ColorDB::get(id));
break;
case 8: // eAthena LOOK_SHIELD
- player->setSprite(SPRITE_SHIELD, id);
+ dstBeing->setSprite(SPRITE_SHIELD, id);
break;
case 9: // eAthena LOOK_SHOES
- player->setSprite(SPRITE_SHOE, id);
+ dstBeing->setSprite(SPRITE_SHOE, id);
break;
case 10: // LOOK_GLOVES
- player->setSprite(SPRITE_GLOVES, id);
+ dstBeing->setSprite(SPRITE_GLOVES, id);
break;
case 11: // LOOK_CAPE
- player->setSprite(SPRITE_CAPE, id);
+ dstBeing->setSprite(SPRITE_CAPE, id);
break;
case 12:
- player->setSprite(SPRITE_MISC1, id);
+ dstBeing->setSprite(SPRITE_MISC1, id);
break;
case 13:
- player->setSprite(SPRITE_MISC2, id);
+ dstBeing->setSprite(SPRITE_MISC2, id);
break;
default:
logger->log("SMSG_BEING_CHANGE_LOOKS: unsupported type: "
@@ -485,13 +466,13 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
break;
case SMSG_BEING_NAME_RESPONSE:
- if ((dstBeing = beingManager->findBeing(msg.readInt32())))
+ if ((dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
{
dstBeing->setName(msg.readString(24));
}
break;
case SMSG_PLAYER_GUILD_PARTY_INFO:
- if ((dstBeing = beingManager->findBeing(msg.readInt32())))
+ if ((dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
{
dstBeing->setPartyName(msg.readString(24));
dstBeing->setGuildName(msg.readString(24));
@@ -500,7 +481,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
}
break;
case SMSG_BEING_CHANGE_DIRECTION:
- if (!(dstBeing = beingManager->findBeing(msg.readInt32())))
+ if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
{
break;
}
@@ -523,7 +504,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
<< 16; // status.options; Aethyra uses this as misc2
job = msg.readInt16();
- dstBeing = beingManager->findBeing(id);
+ dstBeing = actorSpriteManager->findBeing(id);
if (!dstBeing)
{
@@ -533,13 +514,10 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
break;
}
- if (dstBeing->getType() == Being::PLAYER)
- player = static_cast<Player*>(dstBeing);
-
if (Party *party = player_node->getParty()){
if (party->isMember(id))
{
- player->setParty(party);
+ dstBeing->setParty(party);
}
}
@@ -565,21 +543,21 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
msg.readInt16(); // manner
dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3
msg.readInt8(); // karma
- player->setGender((msg.readInt8() == 0)
+ dstBeing->setGender((msg.readInt8() == 0)
? GENDER_FEMALE : GENDER_MALE);
// Set these after the gender, as the sprites may be gender-specific
- player->setSprite(SPRITE_WEAPON, weapon, "", true);
- player->setSprite(SPRITE_SHIELD, shield);
- //player->setSprite(SPRITE_SHOE, shoes);
- player->setSprite(SPRITE_BOTTOMCLOTHES, headBottom);
- player->setSprite(SPRITE_TOPCLOTHES, headMid);
- player->setSprite(SPRITE_HAT, headTop);
- //player->setSprite(SPRITE_GLOVES, gloves);
- //player->setSprite(SPRITE_CAPE, cape);
- //player->setSprite(SPRITE_MISC1, misc1);
- //player->setSprite(SPRITE_MISC2, misc2);
- player->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(hairColor));
+ dstBeing->setSprite(SPRITE_WEAPON, weapon, "", true);
+ dstBeing->setSprite(SPRITE_SHIELD, shield);
+ //dstBeing->setSprite(SPRITE_SHOE, shoes);
+ dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom);
+ dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid);
+ dstBeing->setSprite(SPRITE_HAT, headTop);
+ //dstBeing->setSprite(SPRITE_GLOVES, gloves);
+ //dstBeing->setSprite(SPRITE_CAPE, cape);
+ //dstBeing->setSprite(SPRITE_MISC1, misc1);
+ //dstBeing->setSprite(SPRITE_MISC2, misc2);
+ dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(hairColor));
if (msg.getId() == SMSG_PLAYER_MOVE)
{
@@ -609,7 +587,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
gmstatus = msg.readInt16();
if (gmstatus & 0x80)
- player->setGM(true);
+ dstBeing->setGM(true);
if (msg.getId() == SMSG_PLAYER_UPDATE_1)
{
@@ -632,8 +610,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
msg.readInt8(); // Lv
msg.readInt8(); // unknown
- dstBeing->setWalkTime(tick_time);
- dstBeing->setFrame(0);
+ dstBeing->setActionTime(tick_time);
+ dstBeing->reset();
dstBeing->setStunMode(stunMode);
dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff);
@@ -656,18 +634,15 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
id = msg.readInt32();
if (mSync || id != player_node->getId())
{
- dstBeing = beingManager->findBeing(id);
+ dstBeing = actorSpriteManager->findBeing(id);
if (dstBeing)
{
Uint16 x, y;
x = msg.readInt16();
y = msg.readInt16();
dstBeing->setTileCoords(x, y);
- if (dstBeing->getCurrentAction() == Being::WALK)
- {
- dstBeing->setFrame(0);
+ if (dstBeing->getCurrentAction() == Being::MOVE)
dstBeing->setAction(Being::STAND);
- }
}
}
break;
@@ -684,18 +659,18 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
case SMSG_PLAYER_STATUS_CHANGE:
// Change in players' flags
id = msg.readInt32();
- dstBeing = beingManager->findBeing(id);
+ dstBeing = actorSpriteManager->findBeing(id);
+ if (!dstBeing)
+ break;
+
stunMode = msg.readInt16();
statusEffects = msg.readInt16();
statusEffects |= ((Uint32) msg.readInt16()) << 16;
- msg.readInt8();
+ msg.readInt8(); // Unused?
- if (dstBeing)
- {
- dstBeing->setStunMode(stunMode);
- dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff);
- dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff);
- }
+ dstBeing->setStunMode(stunMode);
+ dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff);
+ dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff);
break;
case SMSG_BEING_STATUS_CHANGE:
@@ -704,7 +679,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
id = msg.readInt32();
flag = msg.readInt8(); // 0: stop, 1: start
- dstBeing = beingManager->findBeing(id);
+ dstBeing = actorSpriteManager->findBeing(id);
if (dstBeing)
dstBeing->setStatusEffect(status, flag);
break;
diff --git a/src/net/tmwa/buysellhandler.cpp b/src/net/tmwa/buysellhandler.cpp
index 209f034d..5368ba9d 100644
--- a/src/net/tmwa/buysellhandler.cpp
+++ b/src/net/tmwa/buysellhandler.cpp
@@ -21,18 +21,17 @@
#include "net/tmwa/buysellhandler.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
+#include "event.h"
#include "inventory.h"
#include "item.h"
#include "localplayer.h"
-#include "npc.h"
+#include "playerinfo.h"
#include "gui/buy.h"
#include "gui/buysell.h"
#include "gui/sell.h"
-#include "gui/widgets/chattab.h"
-
#include "net/messagein.h"
#include "net/tmwa/protocol.h"
@@ -62,7 +61,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
switch (msg.getId())
{
case SMSG_NPC_BUY_SELL_CHOICE:
- if (!BuySellDialog::isActive())
+ if (PlayerInfo::getBuySellState() != BUYSELL_CHOOSING)
{
mNpcId = msg.readInt32();
new BuySellDialog(mNpcId);
@@ -73,7 +72,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
msg.readInt16(); // length
n_items = (msg.getLength() - 4) / 11;
mBuyDialog = new BuyDialog(mNpcId);
- mBuyDialog->setMoney(player_node->getMoney());
+ mBuyDialog->setMoney(PlayerInfo::getAttribute(MONEY));
for (int k = 0; k < n_items; k++)
{
@@ -91,7 +90,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
if (n_items > 0)
{
SellDialog *dialog = new SellDialog(mNpcId);
- dialog->setMoney(player_node->getMoney());
+ dialog->setMoney(PlayerInfo::getAttribute(MONEY));
for (int k = 0; k < n_items; k++)
{
@@ -99,7 +98,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
int value = msg.readInt32();
msg.readInt32(); // OCvalue
- Item *item = player_node->getInventory()->getItem(index);
+ Item *item = PlayerInfo::getInventory()->getItem(index);
if (item && !(item->isEquipped()))
dialog->addItem(item, value);
@@ -107,29 +106,29 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
}
else
{
- localChatTab->chatLog(_("Nothing to sell."), BY_SERVER);
+ SERVER_NOTICE(_("Nothing to sell."))
}
break;
case SMSG_NPC_BUY_RESPONSE:
if (msg.readInt8() == 0)
{
- localChatTab->chatLog(_("Thanks for buying."), BY_SERVER);
+ SERVER_NOTICE(_("Thanks for buying."))
}
else
{
// Reset player money since buy dialog already assumed purchase
// would go fine
- mBuyDialog->setMoney(player_node->getMoney());
- localChatTab->chatLog(_("Unable to buy."), BY_SERVER);
+ mBuyDialog->setMoney(PlayerInfo::getAttribute(MONEY));
+ SERVER_NOTICE(_("Unable to buy."))
}
break;
case SMSG_NPC_SELL_RESPONSE:
if (msg.readInt8() == 0)
- localChatTab->chatLog(_("Thanks for selling."), BY_SERVER);
+ SERVER_NOTICE(_("Thanks for selling."))
else
- localChatTab->chatLog(_("Unable to sell."), BY_SERVER);
+ SERVER_NOTICE(_("Unable to sell."))
break;
}
diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp
index 8711f031..820864ce 100644
--- a/src/net/tmwa/charserverhandler.cpp
+++ b/src/net/tmwa/charserverhandler.cpp
@@ -83,12 +83,10 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
for (int i = 0; i < count; ++i)
{
Net::Character *character = new Net::Character;
- int slot;
- character->dummy = readPlayerData(msg, &slot);
- character->slot = slot;
+ readPlayerData(msg, character);
mCharacters.push_back(character);
logger->log("CharServer: Player: %s (%d)",
- character->dummy->getName().c_str(), slot);
+ character->dummy->getName().c_str(), character->slot);
}
Client::setState(STATE_CHAR_SELECT);
@@ -115,9 +113,7 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
case SMSG_CHAR_CREATE_SUCCEEDED:
{
Net::Character *character = new Net::Character;
- int slot;
- character->dummy = readPlayerData(msg, &slot);
- character->slot = slot;
+ readPlayerData(msg, character);
mCharacters.push_back(character);
updateCharSelectDialog();
@@ -162,6 +158,8 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
// Prevent the selected local player from being deleted
player_node = mSelectedCharacter->dummy;
+ PlayerInfo::setBackend(mSelectedCharacter->data);
+
mSelectedCharacter->dummy = 0;
delete_all(mCharacters);
@@ -191,7 +189,7 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
}
}
-LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot)
+void CharServerHandler::readPlayerData(Net::MessageIn &msg, Net::Character *character)
{
const Token &token =
static_cast<LoginHandler*>(Net::getLoginHandler())->getToken();
@@ -199,30 +197,37 @@ LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot)
LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0);
tempPlayer->setGender(token.sex);
- tempPlayer->setExp(msg.readInt32());
- tempPlayer->setMoney(msg.readInt32());
- tempPlayer->setExperience(JOB, msg.readInt32(), 1);
+ character->data.mAttributes[EXP] = msg.readInt32();
+ character->data.mAttributes[MONEY] = msg.readInt32();
+ character->data.mStats[JOB].exp = msg.readInt32();
+
int temp = msg.readInt32();
- tempPlayer->setAttributeBase(JOB, temp, false);
- tempPlayer->setAttributeEffective(JOB, temp);
+ character->data.mStats[JOB].base = temp;
+ character->data.mStats[JOB].mod = temp;
+
tempPlayer->setSprite(SPRITE_SHOE, msg.readInt16());
tempPlayer->setSprite(SPRITE_GLOVES, msg.readInt16());
tempPlayer->setSprite(SPRITE_CAPE, msg.readInt16());
tempPlayer->setSprite(SPRITE_MISC1, msg.readInt16());
+
msg.readInt32(); // option
msg.readInt32(); // karma
msg.readInt32(); // manner
msg.skip(2); // unknown
- tempPlayer->setHp(msg.readInt16());
- tempPlayer->setMaxHp(msg.readInt16());
- tempPlayer->setMP(msg.readInt16());
- tempPlayer->setMaxMP(msg.readInt16());
+
+ character->data.mAttributes[HP] = msg.readInt16();
+ character->data.mAttributes[MAX_HP] = msg.readInt16();
+ character->data.mAttributes[MP] = msg.readInt16();
+ character->data.mAttributes[MAX_MP] = msg.readInt16();
+
msg.readInt16(); // speed
tempPlayer->setSubtype(msg.readInt16()); // class (used for race)
int hairStyle = msg.readInt16();
Uint16 weapon = msg.readInt16();
tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true);
- tempPlayer->setLevel(msg.readInt16());
+
+ character->data.mAttributes[LEVEL] = msg.readInt16();
+
msg.readInt16(); // skill point
tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, msg.readInt16()); // head bottom
tempPlayer->setSprite(SPRITE_SHIELD, msg.readInt16());
@@ -231,12 +236,14 @@ LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot)
tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(msg.readInt16()));
tempPlayer->setSprite(SPRITE_MISC2, msg.readInt16());
tempPlayer->setName(msg.readString(24));
+
+ character->dummy = tempPlayer;
+
for (int i = 0; i < 6; i++)
- tempPlayer->setAttributeBase(i + STR, msg.readInt8(), false);
- *slot = msg.readInt8(); // character slot
- msg.readInt8(); // unknown
+ character->data.mStats[i + STR].base = msg.readInt8();
- return tempPlayer;
+ character->slot = msg.readInt8(); // character slot
+ msg.readInt8(); // unknown
}
void CharServerHandler::setCharSelectDialog(CharSelectDialog *window)
@@ -312,17 +319,17 @@ void CharServerHandler::switchCharacter()
outMsg.writeInt8(1);
}
-int CharServerHandler::baseSprite() const
+unsigned int CharServerHandler::baseSprite() const
{
return SPRITE_BASE;
}
-int CharServerHandler::hairSprite() const
+unsigned int CharServerHandler::hairSprite() const
{
return SPRITE_HAIR;
}
-int CharServerHandler::maxSprite() const
+unsigned int CharServerHandler::maxSprite() const
{
return SPRITE_VECTOREND;
}
diff --git a/src/net/tmwa/charserverhandler.h b/src/net/tmwa/charserverhandler.h
index e80d22c4..2076cbae 100644
--- a/src/net/tmwa/charserverhandler.h
+++ b/src/net/tmwa/charserverhandler.h
@@ -63,16 +63,16 @@ class CharServerHandler : public MessageHandler, public Net::CharHandler
void switchCharacter();
- int baseSprite() const;
+ unsigned int baseSprite() const;
- int hairSprite() const;
+ unsigned int hairSprite() const;
- int maxSprite() const;
+ unsigned int maxSprite() const;
void connect();
private:
- LocalPlayer *readPlayerData(Net::MessageIn &msg, int *slot);
+ void readPlayerData(Net::MessageIn &msg, Net::Character *character);
};
} // namespace TmwAthena
diff --git a/src/net/tmwa/chathandler.cpp b/src/net/tmwa/chathandler.cpp
index 00d29662..2b647f68 100644
--- a/src/net/tmwa/chathandler.cpp
+++ b/src/net/tmwa/chathandler.cpp
@@ -21,14 +21,13 @@
#include "net/tmwa/chathandler.h"
+#include "actorspritemanager.h"
#include "being.h"
-#include "beingmanager.h"
+#include "event.h"
#include "game.h"
#include "localplayer.h"
#include "playerrelations.h"
-#include "gui/widgets/chattab.h"
-
#include "net/messagein.h"
#include "net/messageout.h"
@@ -60,8 +59,6 @@ ChatHandler::ChatHandler()
void ChatHandler::handleMessage(Net::MessageIn &msg)
{
- if (!localChatTab) return;
-
Being *being;
std::string chatMsg;
std::string nick;
@@ -70,19 +67,36 @@ void ChatHandler::handleMessage(Net::MessageIn &msg)
switch (msg.getId())
{
case SMSG_WHISPER_RESPONSE:
+ if (mSentWhispers.empty())
+ nick = "user";
+ else
+ {
+ nick = mSentWhispers.front();
+ mSentWhispers.pop();
+ }
+
switch (msg.readInt8())
{
case 0x00:
- // comment out since we'll local echo in chat.cpp instead, then only report failures
- //localChatTab->chatLog("Whisper sent", BY_SERVER);
+ // Success (don't need to report)
break;
case 0x01:
- localChatTab->chatLog(_("Whisper could not be sent, user "
- "is offline."), BY_SERVER);
+ {
+ Mana::Event event("WhisperError");
+ event.setString("nick", nick);
+ event.setString("error", strprintf(_("Whisper could "
+ "not be sent, %s is offline."), nick.c_str()));
+ event.trigger("Chat");
+ }
break;
case 0x02:
- localChatTab->chatLog(_("Whisper could not be sent, "
- "ignored by user."), BY_SERVER);
+ {
+ Mana::Event event("WhisperError");
+ event.setString("nick", nick);
+ event.setString("error", strprintf(_("Whisper could "
+ "not be sent, ignored by %s."), nick.c_str()));
+ event.Event::trigger("Chat");
+ }
break;
}
break;
@@ -100,11 +114,16 @@ void ChatHandler::handleMessage(Net::MessageIn &msg)
if (nick != "Server")
{
if (player_relations.hasPermission(nick, PlayerRelation::WHISPER))
- chatWindow->whisper(nick, chatMsg);
+ {
+ Mana::Event event("Whisper");
+ event.setString("nick", nick);
+ event.setString("message", chatMsg);
+ event.trigger("Chat");
+ }
}
else
{
- localChatTab->chatLog(chatMsg, BY_SERVER);
+ SERVER_NOTICE(chatMsg)
}
break;
@@ -113,7 +132,8 @@ void ChatHandler::handleMessage(Net::MessageIn &msg)
case SMSG_BEING_CHAT:
{
chatMsgLength = msg.readInt16() - 8;
- being = beingManager->findBeing(msg.readInt32());
+ int beingId = msg.readInt32();
+ being = actorSpriteManager->findBeing(beingId);
if (!being || chatMsgLength <= 0)
break;
@@ -135,23 +155,33 @@ void ChatHandler::handleMessage(Net::MessageIn &msg)
chatMsg.erase(0, pos + 3);
}
- trim(chatMsg);
+ int perms;
- // 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)
+ if (being->getType() == Being::PLAYER)
{
- localChatTab->chatLog(removeColors(sender_name) + " : "
- + chatMsg, BY_OTHER);
+ perms = player_relations.checkPermissionSilently(sender_name,
+ PlayerRelation::SPEECH_LOG | PlayerRelation::SPEECH_FLOAT);
}
-
- if (player_relations.hasPermission(sender_name,
- PlayerRelation::SPEECH_FLOAT))
+ else
{
- being->setSpeech(chatMsg, SPEECH_TIME);
+ perms = player_relations.getDefault()
+ & (PlayerRelation::SPEECH_LOG
+ | PlayerRelation::SPEECH_FLOAT);
}
+
+ trim(chatMsg);
+
+ std::string reducedMessage = chatMsg;
+ chatMsg = removeColors(sender_name) + " : " + reducedMessage;
+
+ Mana::Event event("Being");
+ event.setString("message", chatMsg);
+ event.setString("text", reducedMessage);
+ event.setString("nick", sender_name);
+ event.setInt("beingId", beingId);
+ event.setInt("permissions", perms);
+ event.trigger("Chat");
+
break;
}
@@ -164,22 +194,32 @@ void ChatHandler::handleMessage(Net::MessageIn &msg)
break;
chatMsg = msg.readString(chatMsgLength);
- std::string::size_type pos = chatMsg.find(" : ", 0);
if (msg.getId() == SMSG_PLAYER_CHAT)
{
- localChatTab->chatLog(chatMsg, BY_PLAYER);
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+ std::string mes = chatMsg;
if (pos != std::string::npos)
chatMsg.erase(0, pos + 3);
trim(chatMsg);
- player_node->setSpeech(chatMsg, SPEECH_TIME);
+ Mana::Event event("Player");
+ event.setString("message", mes);
+ event.setString("text", chatMsg);
+ event.setString("nick", player_node->getName());
+ event.setInt("beingId", player_node->getId());
+ event.setInt("permissions", player_relations.getDefault()
+ & (PlayerRelation::SPEECH_LOG
+ | PlayerRelation::SPEECH_FLOAT));
+ event.trigger("Chat");
}
else
{
- localChatTab->chatLog(chatMsg, BY_GM);
+ Mana::Event event("Announcement");
+ event.setString("message", chatMsg);
+ event.trigger("Chat");
}
break;
}
@@ -187,7 +227,7 @@ void ChatHandler::handleMessage(Net::MessageIn &msg)
case SMSG_MVP:
// Display MVP player
msg.readInt32(); // id
- localChatTab->chatLog(_("MVP player."), BY_SERVER);
+ SERVER_NOTICE(_("MVP player."))
break;
}
}
@@ -216,47 +256,49 @@ void ChatHandler::privateMessage(const std::string &recipient,
outMsg.writeInt16(text.length() + 28);
outMsg.writeString(recipient, 24);
outMsg.writeString(text, text.length());
+
+ mSentWhispers.push(recipient);
}
void ChatHandler::channelList()
{
- localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER);
+ SERVER_NOTICE(_("Channels are not supported!"))
}
void ChatHandler::enterChannel(const std::string &channel,
const std::string &password)
{
- localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER);
+ SERVER_NOTICE(_("Channels are not supported!"))
}
void ChatHandler::quitChannel(int channelId)
{
- localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER);
+ SERVER_NOTICE(_("Channels are not supported!"))
}
void ChatHandler::sendToChannel(int channelId, const std::string &text)
{
- localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER);
+ SERVER_NOTICE(_("Channels are not supported!"))
}
void ChatHandler::userList(const std::string &channel)
{
- localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER);
+ SERVER_NOTICE(_("Channels are not supported!"))
}
void ChatHandler::setChannelTopic(int channelId, const std::string &text)
{
- localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER);
+ SERVER_NOTICE(_("Channels are not supported!"))
}
void ChatHandler::setUserMode(int channelId, const std::string &name, int mode)
{
- localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER);
+ SERVER_NOTICE(_("Channels are not supported!"))
}
void ChatHandler::kickUser(int channelId, const std::string &name)
{
- localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER);
+ SERVER_NOTICE(_("Channels are not supported!"))
}
void ChatHandler::who()
diff --git a/src/net/tmwa/chathandler.h b/src/net/tmwa/chathandler.h
index 3e035f7e..6426a71e 100644
--- a/src/net/tmwa/chathandler.h
+++ b/src/net/tmwa/chathandler.h
@@ -27,6 +27,8 @@
#include "net/tmwa/messagehandler.h"
+#include <queue>
+
namespace TmwAthena {
class ChatHandler : public MessageHandler, public Net::ChatHandler
@@ -61,6 +63,10 @@ class ChatHandler : public MessageHandler, public Net::ChatHandler
void kickUser(int channelId, const std::string &name);
void who();
+
+ private:
+ typedef std::queue<std::string> WhisperQueue;
+ WhisperQueue mSentWhispers;
};
} // namespace TmwAthena
diff --git a/src/net/tmwa/gamehandler.cpp b/src/net/tmwa/gamehandler.cpp
index 435d5d30..334a2e37 100644
--- a/src/net/tmwa/gamehandler.cpp
+++ b/src/net/tmwa/gamehandler.cpp
@@ -22,12 +22,11 @@
#include "net/tmwa/gamehandler.h"
#include "client.h"
+#include "event.h"
#include "game.h"
#include "localplayer.h"
#include "log.h"
-#include "gui/widgets/chattab.h"
-
#include "gui/okdialog.h"
#include "net/messagein.h"
@@ -58,6 +57,8 @@ GameHandler::GameHandler()
};
handledMessages = _messages;
gameHandler = this;
+
+ listen("Game");
}
void GameHandler::handleMessage(Net::MessageIn &msg)
@@ -84,8 +85,7 @@ void GameHandler::handleMessage(Net::MessageIn &msg)
break;
case SMSG_WHO_ANSWER:
- localChatTab->chatLog(strprintf(_("Online users: %d"),
- msg.readInt32()), BY_SERVER);
+ SERVER_NOTICE(strprintf(_("Online users: %d"), msg.readInt32()))
break;
case SMSG_CHAR_SWITCH_RESPONSE:
@@ -105,6 +105,21 @@ void GameHandler::handleMessage(Net::MessageIn &msg)
}
}
+void GameHandler::event(const std::string &channel, const Mana::Event &event)
+{
+ if (channel == "Game")
+ {
+ if (event.getName() == "EnginesInitalized")
+ {
+ Game::instance()->changeMap(mMap);
+ }
+ else if (event.getName() == "MapLoaded")
+ {
+ MessageOut outMsg(CMSG_MAP_LOADED);
+ }
+ }
+}
+
void GameHandler::connect()
{
mNetwork->connect(mapServer);
@@ -142,16 +157,6 @@ void GameHandler::disconnect()
mNetwork->disconnect();
}
-void GameHandler::inGame()
-{
- Game::instance()->changeMap(mMap);
-}
-
-void GameHandler::mapLoaded(const std::string &mapName)
-{
- MessageOut outMsg(CMSG_MAP_LOADED);
-}
-
void GameHandler::who()
{
}
diff --git a/src/net/tmwa/gamehandler.h b/src/net/tmwa/gamehandler.h
index ca8d27e6..6bdcbaef 100644
--- a/src/net/tmwa/gamehandler.h
+++ b/src/net/tmwa/gamehandler.h
@@ -22,6 +22,8 @@
#ifndef NET_TA_MAPHANDLER_H
#define NET_TA_MAPHANDLER_H
+#include "listener.h"
+
#include "net/gamehandler.h"
#include "net/net.h"
#include "net/serverinfo.h"
@@ -31,23 +33,22 @@
namespace TmwAthena {
-class GameHandler : public MessageHandler, public Net::GameHandler
+class GameHandler : public MessageHandler, public Net::GameHandler,
+ public Mana::Listener
{
public:
GameHandler();
void handleMessage(Net::MessageIn &msg);
+ void event(const std::string &channel, const Mana::Event &event);
+
void connect();
bool isConnected();
void disconnect();
- void inGame();
-
- void mapLoaded(const std::string &mapName);
-
void who();
void quit();
@@ -60,6 +61,9 @@ class GameHandler : public MessageHandler, public Net::GameHandler
void setMap(const std::string map);
+ /** The tmwAthena protocol is making use of the MP status bar. */
+ bool canUseMagicBar() const { return true; }
+
private:
std::string mMap;
int mCharID; /// < Saved for map-server switching
diff --git a/src/net/tmwa/generalhandler.cpp b/src/net/tmwa/generalhandler.cpp
index 14f48055..8d69767f 100644
--- a/src/net/tmwa/generalhandler.cpp
+++ b/src/net/tmwa/generalhandler.cpp
@@ -32,6 +32,10 @@
#include "gui/socialwindow.h"
#include "gui/statuswindow.h"
+#include "net/messagein.h"
+#include "net/messageout.h"
+#include "net/serverinfo.h"
+
#include "net/tmwa/adminhandler.h"
#include "net/tmwa/beinghandler.h"
#include "net/tmwa/buysellhandler.h"
@@ -53,9 +57,6 @@
#include "net/tmwa/gui/guildtab.h"
#include "net/tmwa/gui/partytab.h"
-#include "net/messagein.h"
-#include "net/messageout.h"
-
#include "resources/itemdb.h"
#include "utils/gettext.h"
@@ -75,7 +76,7 @@ extern Party *taParty;
GeneralHandler::GeneralHandler():
mAdminHandler(new AdminHandler),
- mBeingHandler(new BeingHandler(config.getValue("EnableSync", 0) == 1)),
+ mBeingHandler(new BeingHandler(config.getBoolValue("EnableSync"))),
mBuySellHandler(new BuySellHandler),
mCharHandler(new CharServerHandler),
mChatHandler(new ChatHandler),
@@ -106,6 +107,8 @@ GeneralHandler::GeneralHandler():
stats.push_back(ItemDB::Stat("luck", _("Luck %+d")));
ItemDB::setStatsList(stats);
+
+ listen("Game");
}
GeneralHandler::~GeneralHandler()
@@ -209,47 +212,48 @@ void GeneralHandler::flushNetwork()
}
}
-void GeneralHandler::guiWindowsLoaded()
-{
- inventoryWindow->setSplitAllowed(false);
- skillDialog->loadSkills("ea-skills.xml");
-
- statusWindow->addAttribute(STR, _("Strength"), true, "");
- statusWindow->addAttribute(AGI, _("Agility"), true, "");
- statusWindow->addAttribute(VIT, _("Vitality"), true, "");
- statusWindow->addAttribute(INT, _("Intelligence"), true, "");
- statusWindow->addAttribute(DEX, _("Dexterity"), true, "");
- statusWindow->addAttribute(LUK, _("Luck"), true, "");
-
- statusWindow->addAttribute(ATK, _("Attack"), false, "");
- statusWindow->addAttribute(DEF, _("Defense"), false, "");
- statusWindow->addAttribute(MATK, _("M.Attack"), false, "");
- statusWindow->addAttribute(MDEF, _("M.Defense"), false, "");
- statusWindow->addAttribute(HIT, _("% Accuracy"), false, "");
- statusWindow->addAttribute(FLEE, _("% Evade"), false, "");
- statusWindow->addAttribute(CRIT, _("% Critical"), false, "");
-}
-
-void GeneralHandler::guiWindowsUnloaded()
-{
- socialWindow->removeTab(taGuild);
- socialWindow->removeTab(taParty);
-
- delete guildTab;
- guildTab = 0;
-
- delete partyTab;
- partyTab = 0;
-}
-
void GeneralHandler::clearHandlers()
{
mNetwork->clearHandlers();
}
-void GeneralHandler::stateChanged(State oldState, State newState)
+void GeneralHandler::event(const std::string &channel,
+ const Mana::Event &event)
{
- //
+ if (channel == "Game")
+ {
+ if (event.getName() == "GuiWindowsLoaded")
+ {
+ inventoryWindow->setSplitAllowed(false);
+ skillDialog->loadSkills("ea-skills.xml");
+
+ statusWindow->addAttribute(STR, _("Strength"), true, "");
+ statusWindow->addAttribute(AGI, _("Agility"), true, "");
+ statusWindow->addAttribute(VIT, _("Vitality"), true, "");
+ statusWindow->addAttribute(INT, _("Intelligence"), true, "");
+ statusWindow->addAttribute(DEX, _("Dexterity"), true, "");
+ statusWindow->addAttribute(LUK, _("Luck"), true, "");
+
+ statusWindow->addAttribute(ATK, _("Attack"), false, "");
+ statusWindow->addAttribute(DEF, _("Defense"), false, "");
+ statusWindow->addAttribute(MATK, _("M.Attack"), false, "");
+ statusWindow->addAttribute(MDEF, _("M.Defense"), false, "");
+ statusWindow->addAttribute(HIT, _("% Accuracy"), false, "");
+ statusWindow->addAttribute(FLEE, _("% Evade"), false, "");
+ statusWindow->addAttribute(CRIT, _("% Critical"), false, "");
+ }
+ else if (event.getName() == "GuiWindowsUnloading")
+ {
+ socialWindow->removeTab(taGuild);
+ socialWindow->removeTab(taParty);
+
+ delete guildTab;
+ guildTab = 0;
+
+ delete partyTab;
+ partyTab = 0;
+ }
+ }
}
} // namespace TmwAthena
diff --git a/src/net/tmwa/generalhandler.h b/src/net/tmwa/generalhandler.h
index d680f215..f7f78759 100644
--- a/src/net/tmwa/generalhandler.h
+++ b/src/net/tmwa/generalhandler.h
@@ -22,15 +22,17 @@
#ifndef NET_TMWA_GENERALHANDLER_H
#define NET_TMWA_GENERALHANDLER_H
+#include "listener.h"
+
#include "net/generalhandler.h"
#include "net/net.h"
-#include "net/serverinfo.h"
#include "net/tmwa/messagehandler.h"
namespace TmwAthena {
-class GeneralHandler : public MessageHandler, public Net::GeneralHandler
+class GeneralHandler : public MessageHandler, public Net::GeneralHandler,
+ public Mana::Listener
{
public:
GeneralHandler();
@@ -47,13 +49,9 @@ class GeneralHandler : public MessageHandler, public Net::GeneralHandler
void flushNetwork();
- void guiWindowsLoaded();
-
- void guiWindowsUnloaded();
-
void clearHandlers();
- void stateChanged(State oldState, State newState);
+ void event(const std::string &channel, const Mana::Event &event);
protected:
MessageHandlerPtr mAdminHandler;
diff --git a/src/net/tmwa/gui/guildtab.cpp b/src/net/tmwa/gui/guildtab.cpp
index 794ad5cc..ca922e55 100644
--- a/src/net/tmwa/gui/guildtab.cpp
+++ b/src/net/tmwa/gui/guildtab.cpp
@@ -21,17 +21,17 @@
#include "net/tmwa/gui/guildtab.h"
+#include "chatlog.h"
#include "commandhandler.h"
#include "guild.h"
#include "localplayer.h"
-#include "gui/theme.h"
-
#include "net/net.h"
#include "net/guildhandler.h"
#include "resources/iteminfo.h"
#include "resources/itemdb.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
#include "utils/gettext.h"
@@ -114,4 +114,10 @@ void GuildTab::getAutoCompleteList(std::vector<std::string> &names) const
taGuild->getNames(names);
}
+void GuildTab::saveToLogFile(std::string &msg)
+{
+ if (chatLogger)
+ chatLogger->log("#Guild", msg);
+}
+
} // namespace TmwAthena
diff --git a/src/net/tmwa/gui/guildtab.h b/src/net/tmwa/gui/guildtab.h
index 031c81bf..12e15e16 100644
--- a/src/net/tmwa/gui/guildtab.h
+++ b/src/net/tmwa/gui/guildtab.h
@@ -39,6 +39,8 @@ class GuildTab : public ChatTab
bool handleCommand(const std::string &type, const std::string &args);
+ void saveToLogFile(std::string &msg);
+
protected:
void handleInput(const std::string &msg);
diff --git a/src/net/tmwa/gui/partytab.cpp b/src/net/tmwa/gui/partytab.cpp
index 03dadb04..d5781971 100644
--- a/src/net/tmwa/gui/partytab.cpp
+++ b/src/net/tmwa/gui/partytab.cpp
@@ -21,17 +21,17 @@
#include "net/tmwa/gui/partytab.h"
+#include "chatlog.h"
#include "commandhandler.h"
#include "localplayer.h"
#include "party.h"
-#include "gui/theme.h"
-
#include "net/net.h"
#include "net/partyhandler.h"
#include "resources/iteminfo.h"
#include "resources/itemdb.h"
+#include "resources/theme.h"
#include "utils/dtor.h"
#include "utils/gettext.h"
@@ -206,4 +206,10 @@ void PartyTab::getAutoCompleteList(std::vector<std::string> &names) const
p->getNames(names);
}
+void PartyTab::saveToLogFile(std::string &msg)
+{
+ if (chatLogger)
+ chatLogger->log("#Party", msg);
+}
+
} // namespace TmwAthena
diff --git a/src/net/tmwa/gui/partytab.h b/src/net/tmwa/gui/partytab.h
index 62027726..4c16ab46 100644
--- a/src/net/tmwa/gui/partytab.h
+++ b/src/net/tmwa/gui/partytab.h
@@ -39,6 +39,8 @@ class PartyTab : public ChatTab
bool handleCommand(const std::string &type, const std::string &args);
+ void saveToLogFile(std::string &msg);
+
protected:
void handleInput(const std::string &msg);
diff --git a/src/net/tmwa/guildhandler.cpp b/src/net/tmwa/guildhandler.cpp
index 8a106841..67fe5d98 100644
--- a/src/net/tmwa/guildhandler.cpp
+++ b/src/net/tmwa/guildhandler.cpp
@@ -21,6 +21,7 @@
#include "net/tmwa/guildhandler.h"
#include "guild.h"
+#include "event.h"
#include "localplayer.h"
#include "log.h"
@@ -387,8 +388,7 @@ void GuildHandler::handleMessage(Net::MessageIn &msg)
void GuildHandler::create(const std::string &name)
{
- localChatTab->chatLog(_("Guild creation isn't supported yet."),
- BY_SERVER);
+ SERVER_NOTICE(_("Guild creation isn't supported yet."))
return;
MessageOut msg(CMSG_GUILD_CREATE);
@@ -401,10 +401,10 @@ void GuildHandler::invite(int guildId, const std::string &name)
// TODO?
}
-void GuildHandler::invite(int guildId, Player *player)
+void GuildHandler::invite(int guildId, Being *being)
{
MessageOut msg(CMSG_GUILD_INVITE);
- msg.writeInt32(player->getId());
+ msg.writeInt32(being->getId());
msg.writeInt32(0); // Unused
msg.writeInt32(0); // Unused
}
diff --git a/src/net/tmwa/guildhandler.h b/src/net/tmwa/guildhandler.h
index 39dbe486..8bde222f 100644
--- a/src/net/tmwa/guildhandler.h
+++ b/src/net/tmwa/guildhandler.h
@@ -40,7 +40,7 @@ class GuildHandler : public Net::GuildHandler, public MessageHandler
void invite(int guildId, const std::string &name);
- void invite(int guildId, Player *player);
+ void invite(int guildId, Being *being);
void inviteResponse(int guildId, bool response);
diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp
index fd979dc6..c1a96788 100644
--- a/src/net/tmwa/inventoryhandler.cpp
+++ b/src/net/tmwa/inventoryhandler.cpp
@@ -23,6 +23,7 @@
#include "configuration.h"
#include "equipment.h"
+#include "event.h"
#include "inventory.h"
#include "item.h"
#include "itemshortcut.h"
@@ -126,7 +127,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
int number, flag;
int index, amount, itemId, equipType, arrow;
int identified, cards[4], itemType;
- Inventory *inventory = player_node->getInventory();
+ Inventory *inventory = PlayerInfo::getInventory();
switch (msg.getId())
{
@@ -136,7 +137,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
{
// Clear inventory - this will be a complete refresh
mEquips.clear();
- player_node->mEquipment->setBackend(&mEquips);
+ PlayerInfo::getEquipment()->setBackend(&mEquips);
inventory->clear();
}
@@ -276,7 +277,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
if (msg.readInt8() == 0)
{
- localChatTab->chatLog(_("Failed to use item."), BY_SERVER);
+ SERVER_NOTICE(_("Failed to use item."))
}
else
{
@@ -386,7 +387,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
flag = msg.readInt8();
if (!flag)
- localChatTab->chatLog(_("Unable to equip."), BY_SERVER);
+ SERVER_NOTICE(_("Unable to equip."))
else
mEquips.setEquipment(getSlot(equipType), index);
break;
@@ -397,7 +398,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
flag = msg.readInt8();
if (!flag)
- localChatTab->chatLog(_("Unable to unequip."), BY_SERVER);
+ SERVER_NOTICE(_("Unable to unequip."))
else
mEquips.setEquipment(getSlot(equipType), -1);
break;
diff --git a/src/net/tmwa/inventoryhandler.h b/src/net/tmwa/inventoryhandler.h
index 82738afe..8e6e12ca 100644
--- a/src/net/tmwa/inventoryhandler.h
+++ b/src/net/tmwa/inventoryhandler.h
@@ -24,7 +24,7 @@
#include "equipment.h"
#include "inventory.h"
-#include "localplayer.h"
+#include "playerinfo.h"
#include "gui/inventorywindow.h"
@@ -51,7 +51,7 @@ class EquipBackend : public Equipment::Backend {
{
return NULL;
}
- return player_node->getInventory()->getItem(invyIndex);
+ return PlayerInfo::getInventory()->getItem(invyIndex);
}
void clear()
@@ -60,7 +60,7 @@ class EquipBackend : public Equipment::Backend {
{
if (mEquipment[i] != -1)
{
- Item* item = player_node->getInventory()->getItem(i);
+ Item* item = PlayerInfo::getInventory()->getItem(i);
if (item)
{
item->setEquipped(false);
@@ -74,7 +74,7 @@ class EquipBackend : public Equipment::Backend {
void setEquipment(int index, int inventoryIndex)
{
// Unequip existing item
- Item* item = player_node->getInventory()->getItem(mEquipment[index]);
+ Item* item = PlayerInfo::getInventory()->getItem(mEquipment[index]);
if (item)
{
item->setEquipped(false);
@@ -82,7 +82,7 @@ class EquipBackend : public Equipment::Backend {
mEquipment[index] = inventoryIndex;
- item = player_node->getInventory()->getItem(inventoryIndex);
+ item = PlayerInfo::getInventory()->getItem(inventoryIndex);
if (item)
{
item->setEquipped(true);
diff --git a/src/net/tmwa/itemhandler.cpp b/src/net/tmwa/itemhandler.cpp
index abc8103b..a8e98860 100644
--- a/src/net/tmwa/itemhandler.cpp
+++ b/src/net/tmwa/itemhandler.cpp
@@ -21,7 +21,7 @@
#include "net/tmwa/itemhandler.h"
-#include "flooritemmanager.h"
+#include "actorspritemanager.h"
#include "net/messagein.h"
@@ -54,13 +54,13 @@ void ItemHandler::handleMessage(Net::MessageIn &msg)
int y = msg.readInt16();
msg.skip(4); // amount,subX,subY / subX,subY,amount
- floorItemManager->create(id, itemId, x, y);
+ actorSpriteManager->createItem(id, itemId, x, y);
}
break;
case SMSG_ITEM_REMOVE:
- if (FloorItem *item = floorItemManager->findById(msg.readInt32()))
- floorItemManager->destroy(item);
+ if (FloorItem *item = actorSpriteManager->findItem(msg.readInt32()))
+ actorSpriteManager->destroy(item);
break;
}
}
diff --git a/src/net/tmwa/npchandler.cpp b/src/net/tmwa/npchandler.cpp
index 5888c679..e1615fec 100644
--- a/src/net/tmwa/npchandler.cpp
+++ b/src/net/tmwa/npchandler.cpp
@@ -21,11 +21,9 @@
#include "net/tmwa/npchandler.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
+#include "event.h"
#include "localplayer.h"
-#include "npc.h"
-
-#include "gui/npcdialog.h"
#include "net/messagein.h"
#include "net/messageout.h"
@@ -34,10 +32,27 @@
#include "net/tmwa/protocol.h"
+#include "utils/stringutils.h"
+
#include <SDL_types.h>
extern Net::NpcHandler *npcHandler;
+static void parseMenu(Mana::Event *event, const std::string &options)
+{
+ std::istringstream iss(options);
+
+ int count = 0;
+ std::string tmp;
+ while (getline(iss, tmp, ':'))
+ {
+ count++;
+ event->setString("choice" + toString(count), tmp);
+ }
+
+ event->setInt("choiceCount", count);
+}
+
namespace TmwAthena {
NpcHandler::NpcHandler()
@@ -53,6 +68,8 @@ NpcHandler::NpcHandler()
};
handledMessages = _messages;
npcHandler = this;
+
+ listen("NPC");
}
void NpcHandler::handleMessage(Net::MessageIn &msg)
@@ -63,126 +80,103 @@ void NpcHandler::handleMessage(Net::MessageIn &msg)
}
int npcId = msg.readInt32();
- NpcDialogs::iterator diag = mNpcDialogs.find(npcId);
- NpcDialog *dialog = 0;
-
- if (diag == mNpcDialogs.end())
- {
- // Empty dialogs don't help
- if (msg.getId() == SMSG_NPC_CLOSE)
- {
- closeDialog(npcId);
- return;
- }
- else if (msg.getId() == SMSG_NPC_NEXT)
- {
- nextDialog(npcId);
- return;
- }
- else
- {
- dialog = new NpcDialog(npcId);
- Wrapper wrap;
- wrap.dialog = dialog;
- mNpcDialogs[npcId] = wrap;
- }
- }
- else
- {
- dialog = diag->second.dialog;
- }
+ Mana::Event *event = 0;
switch (msg.getId())
{
- case SMSG_NPC_CHOICE:
- dialog->choiceRequest();
- dialog->parseListItems(msg.readString(msg.getLength() - 8));
- break;
-
- case SMSG_NPC_MESSAGE:
- dialog->addText(msg.readString(msg.getLength() - 8));
- break;
-
- case SMSG_NPC_CLOSE:
- // Show the close button
- dialog->showCloseButton();
- break;
-
- case SMSG_NPC_NEXT:
- // Show the next button
- dialog->showNextButton();
- break;
-
- case SMSG_NPC_INT_INPUT:
- // Request for an integer
- dialog->integerRequest(0);
- break;
-
- case SMSG_NPC_STR_INPUT:
- // Request for a string
- dialog->textRequest("");
- break;
+ case SMSG_NPC_CHOICE:
+ event = new Mana::Event("Menu");
+ event->setInt("id", npcId);
+ parseMenu(event, msg.readString(msg.getLength() - 8));
+ event->trigger("NPC");
+ break;
+
+ case SMSG_NPC_MESSAGE:
+ event = new Mana::Event("Message");
+ event->setInt("id", npcId);
+ event->setString("text", msg.readString(msg.getLength() - 8));
+ event->trigger("NPC");
+ break;
+
+ case SMSG_NPC_CLOSE:
+ // Show the close button
+ event = new Mana::Event("Close");
+ event->setInt("id", npcId);
+ event->trigger("NPC");
+ break;
+
+ case SMSG_NPC_NEXT:
+ // Show the next button
+ event = new Mana::Event("Next");
+ event->setInt("id", npcId);
+ event->trigger("NPC");
+ break;
+
+ case SMSG_NPC_INT_INPUT:
+ // Request for an integer
+ event = new Mana::Event("IntegerInput");
+ event->setInt("id", npcId);
+ event->trigger("NPC");
+ break;
+
+ case SMSG_NPC_STR_INPUT:
+ // Request for a string
+ event = new Mana::Event("StringInput");
+ event->setInt("id", npcId);
+ event->trigger("NPC");
+ break;
}
+ delete event;
+
if (player_node->getCurrentAction() != Being::SIT)
player_node->setAction(Being::STAND);
}
-void NpcHandler::talk(int npcId)
+void NpcHandler::event(const std::string &channel, const Mana::Event &event)
{
- MessageOut outMsg(CMSG_NPC_TALK);
- outMsg.writeInt32(npcId);
- outMsg.writeInt8(0); // Unused
-}
-
-void NpcHandler::nextDialog(int npcId)
-{
- MessageOut outMsg(CMSG_NPC_NEXT_REQUEST);
- outMsg.writeInt32(npcId);
-}
-
-void NpcHandler::closeDialog(int npcId)
-{
- MessageOut outMsg(CMSG_NPC_CLOSE);
- outMsg.writeInt32(npcId);
-
- NpcDialogs::iterator it = mNpcDialogs.find(npcId);
- if (it != mNpcDialogs.end())
+ if (channel == "NPC")
{
- (*it).second.dialog->close();
- mNpcDialogs.erase(it);
+ if (event.getName() == "doTalk")
+ {
+ MessageOut outMsg(CMSG_NPC_TALK);
+ outMsg.writeInt32(event.getInt("npcId"));
+ outMsg.writeInt8(0); // Unused
+ }
+ else if (event.getName() == "doNext")
+ {
+ MessageOut outMsg(CMSG_NPC_NEXT_REQUEST);
+ outMsg.writeInt32(event.getInt("npcId"));
+ }
+ else if (event.getName() == "doClose")
+ {
+ MessageOut outMsg(CMSG_NPC_CLOSE);
+ outMsg.writeInt32(event.getInt("npcId"));
+ }
+ else if (event.getName() == "doMenu")
+ {
+ MessageOut outMsg(CMSG_NPC_LIST_CHOICE);
+ outMsg.writeInt32(event.getInt("npcId"));
+ outMsg.writeInt8(event.getInt("choice"));
+ }
+ else if (event.getName() == "doIntegerInput")
+ {
+ MessageOut outMsg(CMSG_NPC_INT_RESPONSE);
+ outMsg.writeInt32(event.getInt("npcId"));
+ outMsg.writeInt32(event.getInt("value"));
+ }
+ else if (event.getName() == "doStringInput")
+ {
+ const std::string &value = event.getString("value");
+ MessageOut outMsg(CMSG_NPC_STR_RESPONSE);
+ outMsg.writeInt16(value.length() + 9);
+ outMsg.writeInt32(event.getInt("npcId"));
+ outMsg.writeString(value, value.length());
+ outMsg.writeInt8(0); // Prevent problems with string reading
+ }
}
}
-void NpcHandler::listInput(int npcId, int value)
-{
- MessageOut outMsg(CMSG_NPC_LIST_CHOICE);
- outMsg.writeInt32(npcId);
- outMsg.writeInt8(value);
-}
-
-void NpcHandler::integerInput(int npcId, int value)
-{
- MessageOut outMsg(CMSG_NPC_INT_RESPONSE);
- outMsg.writeInt32(npcId);
- outMsg.writeInt32(value);
-}
-
-void NpcHandler::stringInput(int npcId, const std::string &value)
-{
- MessageOut outMsg(CMSG_NPC_STR_RESPONSE);
- outMsg.writeInt16(value.length() + 9);
- outMsg.writeInt32(npcId);
- outMsg.writeString(value, value.length());
- outMsg.writeInt8(0); // Prevent problems with string reading
-}
-
-void NpcHandler::sendLetter(int npcId, const std::string &recipient,
- const std::string &text)
-{
- // TODO
-}
-
void NpcHandler::startShopping(int beingId)
{
// TODO
@@ -223,9 +217,4 @@ void NpcHandler::endShopping(int beingId)
// TODO
}
-void NpcHandler::clearDialogs()
-{
- mNpcDialogs.clear();
-}
-
} // namespace TmwAthena
diff --git a/src/net/tmwa/npchandler.h b/src/net/tmwa/npchandler.h
index bd696bdd..93c9f6ec 100644
--- a/src/net/tmwa/npchandler.h
+++ b/src/net/tmwa/npchandler.h
@@ -22,38 +22,25 @@
#ifndef NET_TA_NPCHANDLER_H
#define NET_TA_NPCHANDLER_H
-#include "net/net.h"
+#include "listener.h"
+
#include "net/npchandler.h"
#include "net/tmwa/messagehandler.h"
#include <map>
-class NpcDialog;
-
namespace TmwAthena {
-class NpcHandler : public MessageHandler, public Net::NpcHandler
+class NpcHandler : public MessageHandler, public Net::NpcHandler,
+ public Mana::Listener
{
public:
NpcHandler();
void handleMessage(Net::MessageIn &msg);
- void talk(int npcId);
-
- void nextDialog(int npcId);
-
- void closeDialog(int npcId);
-
- void listInput(int npcId, int value);
-
- void integerInput(int npcId, int value);
-
- void stringInput(int npcId, const std::string &value);
-
- void sendLetter(int npcId, const std::string &recipient,
- const std::string &text);
+ void event(const std::string &channel, const Mana::Event &event);
void startShopping(int beingId);
@@ -66,15 +53,6 @@ class NpcHandler : public MessageHandler, public Net::NpcHandler
void sellItem(int beingId, int itemId, int amount);
void endShopping(int beingId);
-
- void clearDialogs();
-
- private:
- typedef struct {
- NpcDialog* dialog;
- } Wrapper;
- typedef std::map<int, Wrapper> NpcDialogs;
- NpcDialogs mNpcDialogs;
};
} // namespace TmwAthena
diff --git a/src/net/tmwa/partyhandler.cpp b/src/net/tmwa/partyhandler.cpp
index e86d41fa..3d7aa263 100644
--- a/src/net/tmwa/partyhandler.cpp
+++ b/src/net/tmwa/partyhandler.cpp
@@ -20,7 +20,8 @@
#include "net/tmwa/partyhandler.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
+#include "event.h"
#include "localplayer.h"
#include "log.h"
@@ -78,12 +79,9 @@ void PartyHandler::handleMessage(Net::MessageIn &msg)
{
case SMSG_PARTY_CREATE:
if (msg.readInt8())
- localChatTab->chatLog(_("Could not create party."), BY_SERVER);
+ SERVER_NOTICE(_("Could not create party."))
else
- {
- localChatTab->chatLog(_("Party successfully created."),
- BY_SERVER);
- }
+ SERVER_NOTICE(_("Party successfully created."))
break;
case SMSG_PARTY_INFO:
{
@@ -143,12 +141,9 @@ void PartyHandler::handleMessage(Net::MessageIn &msg)
std::string nick = "";
Being *being;
- if ((being = beingManager->findBeing(id)))
+ if ((being = actorSpriteManager->findBeing(id)))
{
- if (being->getType() == Being::PLAYER)
- {
- nick = being->getName();
- }
+ nick = being->getName();
}
socialWindow->showPartyInvite(partyName, nick);
@@ -238,8 +233,7 @@ void PartyHandler::handleMessage(Net::MessageIn &msg)
{
taParty->removeFromMembers();
taParty->clearMembers();
- localChatTab->chatLog(_("You have left the party."),
- BY_SERVER);
+ SERVER_NOTICE(_("You have left the party."))
if (partyTab)
{
delete partyTab;
@@ -252,9 +246,10 @@ void PartyHandler::handleMessage(Net::MessageIn &msg)
partyTab->chatLog(strprintf(_("%s has left your party."),
nick.c_str()), BY_SERVER);
- Being *b = beingManager->findBeing(id);
- if (b->getType() == Being::PLAYER)
- static_cast<Player*>(b)->setParty(NULL);
+ if (Being *b = actorSpriteManager->findBeing(id))
+ {
+ b->setParty(NULL);
+ }
taParty->removeMember(id);
}
@@ -274,9 +269,9 @@ void PartyHandler::handleMessage(Net::MessageIn &msg)
// The server only sends this when the member is in range, so
// lets make sure they get the party hilight.
- if (Being *b = beingManager->findBeing(id))
+ if (Being *b = actorSpriteManager->findBeing(id))
{
- static_cast<Player*>(b)->setParty(taParty);
+ b->setParty(taParty);
}
}
break;
@@ -319,10 +314,10 @@ void PartyHandler::join(int partyId)
// TODO?
}
-void PartyHandler::invite(Player *player)
+void PartyHandler::invite(Being *being)
{
MessageOut outMsg(CMSG_PARTY_INVITE);
- outMsg.writeInt32(player->getId());
+ outMsg.writeInt32(being->getId());
}
void PartyHandler::invite(const std::string &name)
@@ -334,8 +329,7 @@ void PartyHandler::invite(const std::string &name)
}
else
{
- localChatTab->chatLog(_("You can only inivte when you are in a party!"),
- BY_SERVER);
+ SERVER_NOTICE(_("You can only inivte when you are in a party!"))
}
// TODO?
@@ -353,10 +347,10 @@ void PartyHandler::leave()
MessageOut outMsg(CMSG_PARTY_LEAVE);
}
-void PartyHandler::kick(Player *player)
+void PartyHandler::kick(Being *being)
{
MessageOut outMsg(CMSG_PARTY_KICK);
- outMsg.writeInt32(player->getId());
+ outMsg.writeInt32(being->getId());
outMsg.writeString("", 24); //Unused
}
diff --git a/src/net/tmwa/partyhandler.h b/src/net/tmwa/partyhandler.h
index fc8d741f..5afc8e53 100644
--- a/src/net/tmwa/partyhandler.h
+++ b/src/net/tmwa/partyhandler.h
@@ -43,7 +43,7 @@ class PartyHandler : public MessageHandler, public Net::PartyHandler
void join(int partyId);
- void invite(Player *player);
+ void invite(Being *being);
void invite(const std::string &name);
@@ -51,7 +51,7 @@ class PartyHandler : public MessageHandler, public Net::PartyHandler
void leave();
- void kick(Player *player);
+ void kick(Being *being);
void kick(const std::string &name);
diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp
index 5aab94b8..6a1e8918 100644
--- a/src/net/tmwa/playerhandler.cpp
+++ b/src/net/tmwa/playerhandler.cpp
@@ -21,28 +21,25 @@
#include "net/tmwa/playerhandler.h"
+#include "event.h"
#include "game.h"
#include "localplayer.h"
#include "log.h"
-#include "npc.h"
+#include "playerinfo.h"
#include "units.h"
#include "gui/buy.h"
#include "gui/buysell.h"
#include "gui/gui.h"
-#include "gui/npcdialog.h"
#include "gui/okdialog.h"
#include "gui/sell.h"
#include "gui/statuswindow.h"
#include "gui/viewport.h"
-#include "gui/widgets/chattab.h"
-
#include "net/messagein.h"
#include "net/messageout.h"
#include "net/tmwa/protocol.h"
-#include "net/tmwa/npchandler.h"
#include "utils/stringutils.h"
#include "utils/gettext.h"
@@ -54,9 +51,6 @@ extern OkDialog *deathNotice;
// everything beyond will reset the port hard.
static const int MAP_TELEPORT_SCROLL_DISTANCE = 8;
-#define ATTR_BONUS(atr) \
-(player_node->getAttributeEffective(atr) - player_node->getAttributeBase(atr))
-
// TODO Move somewhere else
namespace {
@@ -83,14 +77,11 @@ namespace {
BuyDialog::closeAll();
BuySellDialog::closeAll();
- NpcDialog::closeAll();
SellDialog::closeAll();
viewport->closePopupMenu();
- TmwAthena::NpcHandler *handler =
- static_cast<TmwAthena::NpcHandler*>(Net::getNpcHandler());
- handler->clearDialogs();
+ Mana::Event::trigger("NPC", "CloseAll");
}
} deathListener;
@@ -217,7 +208,6 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
player_node->setAction(Being::STAND);
- player_node->setFrame(0);
player_node->setTileCoords(x, y);
logger->log("Adjust scrolling by %d:%d", (int) scrollOffsetX,
@@ -238,17 +228,17 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
player_node->setWalkSpeed(Vector(value, value, 0));
break;
case 0x0004: break; // manner
- case 0x0005: player_node->setHp(value); break;
- case 0x0006: player_node->setMaxHp(value); break;
- case 0x0007: player_node->setMP(value); break;
- case 0x0008: player_node->setMaxMP(value); break;
- case 0x0009: player_node->setCharacterPoints(value); break;
- case 0x000b: player_node->setLevel(value); break;
- case 0x000c: player_node->setSkillPoints(value); break;
+ case 0x0005: PlayerInfo::setAttribute(HP, value); break;
+ case 0x0006: PlayerInfo::setAttribute(MAX_HP, value); break;
+ case 0x0007: PlayerInfo::setAttribute(MP, value); break;
+ case 0x0008: PlayerInfo::setAttribute(MAX_MP, value); break;
+ case 0x0009: PlayerInfo::setAttribute(CHAR_POINTS, value); break;
+ case 0x000b: PlayerInfo::setAttribute(LEVEL, value); break;
+ case 0x000c: PlayerInfo::setAttribute(SKILL_POINTS, value); break;
case 0x0018:
- if (value >= player_node->getMaxWeight() / 2 &&
- player_node->getTotalWeight() <
- player_node->getMaxWeight() / 2)
+ if (value >= PlayerInfo::getAttribute(MAX_WEIGHT) / 2 &&
+ PlayerInfo::getAttribute(TOTAL_WEIGHT) <
+ PlayerInfo::getAttribute(MAX_WEIGHT) / 2)
{
weightNotice = new OkDialog(_("Message"),
_("You are carrying more than "
@@ -257,59 +247,37 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
weightNotice->addActionListener(
&weightListener);
}
- player_node->setTotalWeight(value);
+ PlayerInfo::setAttribute(TOTAL_WEIGHT, value);
break;
- case 0x0019: player_node->setMaxWeight(value); break;
+ case 0x0019: PlayerInfo::setAttribute(MAX_WEIGHT, value); break;
- case 0x0029: player_node->setAttributeEffective(ATK, value
- + ATTR_BONUS(ATK));
- player_node->setAttributeBase(ATK, value);
- break;
- case 0x002a: value += player_node->getAttributeBase(ATK);
- player_node->setAttributeEffective(ATK, value); break;
-
- case 0x002b: player_node->setAttributeEffective(MATK, value
- + ATTR_BONUS(MATK));
- player_node->setAttributeBase(MATK, value);
- if (statusWindow)
- statusWindow->update(StatusWindow::MP);
- break;
- case 0x002c: value += player_node->getAttributeBase(MATK);
- player_node->setAttributeEffective(MATK, value);
- if (statusWindow)
- statusWindow->update(StatusWindow::MP);
- break;
- case 0x002d: player_node->setAttributeEffective(DEF, value
- + ATTR_BONUS(DEF));
- player_node->setAttributeBase(DEF, value); break;
- case 0x002e: value += player_node->getAttributeBase(DEF);
- player_node->setAttributeEffective(DEF, value); break;
-
- case 0x002f: player_node->setAttributeEffective(MDEF, value
- + ATTR_BONUS(MDEF));
- player_node->setAttributeBase(MDEF, value); break;
- case 0x0030: value += player_node->getAttributeBase(MDEF);
- player_node->setAttributeEffective(MDEF, value); break;
-
- case 0x0031: player_node->setAttributeBase(HIT, value);
- player_node->setAttributeEffective(HIT, value); break;
-
- case 0x0032: player_node->setAttributeEffective(FLEE, value
- + ATTR_BONUS(FLEE));
- player_node->setAttributeBase(FLEE, value); break;
- case 0x0033: value += player_node->getAttributeBase(FLEE);
- player_node->setAttributeEffective(FLEE, value); break;
-
- case 0x0034: player_node->setAttributeBase(CRIT, value);
- player_node->setAttributeEffective(CRIT, value); break;
+ case 0x0029: PlayerInfo::setStatBase(ATK, value); break;
+ case 0x002a: PlayerInfo::setStatMod(ATK, value); break;
+
+ case 0x002b: PlayerInfo::setStatBase(MATK, value); break;
+ case 0x002c: PlayerInfo::setStatMod(MATK, value); break;
+
+ case 0x002d: PlayerInfo::setStatBase(DEF, value); break;
+ case 0x002e: PlayerInfo::setStatMod(DEF, value); break;
+
+ case 0x002f: PlayerInfo::setStatBase(MDEF, value); break;
+ case 0x0030: PlayerInfo::setStatMod(MDEF, value); break;
+
+ case 0x0031: PlayerInfo::setStatBase(HIT, value); break;
+
+ case 0x0032: PlayerInfo::setStatBase(FLEE, value); break;
+ case 0x0033: PlayerInfo::setStatMod(FLEE, value); break;
+
+ case 0x0034: PlayerInfo::setStatBase(CRIT, value); break;
case 0x0035: player_node->setAttackSpeed(value); break;
- case 0x0037: player_node->setAttributeBase(JOB, value);
- player_node->setAttributeEffective(JOB, value); break;
+
+ case 0x0037: PlayerInfo::setStatBase(JOB, value); break;
+
case 500: player_node->setGMLevel(value); break;
}
- if (player_node->getHp() == 0 && !deathNotice)
+ if (PlayerInfo::getAttribute(HP) == 0 && !deathNotice)
{
deathNotice = new OkDialog(_("Message"),
randomDeathMessage(),
@@ -324,29 +292,29 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
switch (msg.readInt16())
{
case 0x0001:
- player_node->setExp(msg.readInt32());
+ PlayerInfo::setAttribute(EXP, msg.readInt32());
break;
case 0x0002:
- player_node->setExperience(JOB, msg.readInt32(),
- player_node->getExperience(JOB).second);
+ PlayerInfo::setStatExperience(JOB, msg.readInt32(),
+ PlayerInfo::getStatExperience(JOB).second);
break;
case 0x0014: {
- int curGp = player_node->getMoney();
- player_node->setMoney(msg.readInt32());
- if (player_node->getMoney() > curGp)
- localChatTab->chatLog(strprintf(_("You picked up "
- "%s."),
- Units::formatCurrency(player_node->getMoney()
- - curGp).c_str()), BY_SERVER);
+ int oldMoney = PlayerInfo::getAttribute(MONEY);
+ int newMoney = msg.readInt32();
+ PlayerInfo::setAttribute(MONEY, newMoney);
+ if (newMoney > oldMoney)
+ SERVER_NOTICE(strprintf(_("You picked up %s."),
+ Units::formatCurrency(newMoney -
+ oldMoney).c_str()))
}
break;
case 0x0016:
- player_node->setExpNeeded(msg.readInt32());
+ PlayerInfo::setAttribute(EXP_NEEDED, msg.readInt32());
break;
case 0x0017:
- player_node->setExperience(JOB,
- player_node->getExperience(JOB).first,
- msg.readInt32());
+ PlayerInfo::setStatExperience(JOB,
+ PlayerInfo::getStatExperience(JOB).first,
+ msg.readInt32());
break;
}
break;
@@ -357,8 +325,8 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
int base = msg.readInt32();
int bonus = msg.readInt32();
- player_node->setAttributeBase(type, base);
- player_node->setAttributeEffective(type, base + bonus);
+ PlayerInfo::setStatBase(type, base, false);
+ PlayerInfo::setStatMod(type, bonus);
}
break;
@@ -370,25 +338,20 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
if (ok != 1)
{
- localChatTab->chatLog(_("Cannot raise skill!"),
- BY_SERVER);
+ SERVER_NOTICE(_("Cannot raise skill!"))
}
- int bonus = ATTR_BONUS(type);
-
- player_node->setAttributeBase(type, value);
- player_node->setAttributeEffective(type, value + bonus);
+ PlayerInfo::setStatBase(type, value);
}
break;
// Updates stats and status points
case SMSG_PLAYER_STAT_UPDATE_5:
- player_node->setCharacterPoints(msg.readInt16());
+ PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16());
{
int val = msg.readInt8();
- player_node->setAttributeEffective(STR, val + ATTR_BONUS(STR));
- player_node->setAttributeBase(STR, val);
+ PlayerInfo::setStatBase(STR, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(STR, 0);
@@ -400,8 +363,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
val = msg.readInt8();
- player_node->setAttributeEffective(AGI, val + ATTR_BONUS(AGI));
- player_node->setAttributeBase(AGI, val);
+ PlayerInfo::setStatBase(AGI, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(AGI, 0);
@@ -413,8 +375,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
val = msg.readInt8();
- player_node->setAttributeEffective(VIT, val + ATTR_BONUS(VIT));
- player_node->setAttributeBase(VIT, val);
+ PlayerInfo::setStatBase(VIT, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(VIT, 0);
@@ -426,8 +387,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
val = msg.readInt8();
- player_node->setAttributeEffective(INT, val + ATTR_BONUS(INT));
- player_node->setAttributeBase(INT, val);
+ PlayerInfo::setStatBase(INT, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(INT, 0);
@@ -439,8 +399,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
val = msg.readInt8();
- player_node->setAttributeEffective(DEX, val + ATTR_BONUS(DEX));
- player_node->setAttributeBase(DEX, val);
+ PlayerInfo::setStatBase(DEX, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(DEX, 0);
@@ -452,8 +411,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
val = msg.readInt8();
- player_node->setAttributeEffective(LUK, val + ATTR_BONUS(LUK));
- player_node->setAttributeBase(LUK, val);
+ PlayerInfo::setStatBase(LUK, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(LUK, 0);
@@ -464,39 +422,25 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
statusWindow->setPointsNeeded(LUK, msg.readInt8());
}
- val = msg.readInt16(); // ATK
- player_node->setAttributeBase(ATK, val);
- val += msg.readInt16(); // ATK bonus
- player_node->setAttributeEffective(ATK, val);
-
- val = msg.readInt16(); // MATK
- player_node->setAttributeBase(MATK, val);
- val += msg.readInt16(); // MATK bonus
- player_node->setAttributeEffective(MATK, val);
- statusWindow->update(StatusWindow::MP);
-
- val = msg.readInt16(); // DEF
- player_node->setAttributeBase(DEF, val);
- val += msg.readInt16(); // DEF bonus
- player_node->setAttributeEffective(DEF, val);
-
- val = msg.readInt16(); // MDEF
- player_node->setAttributeBase(MDEF, val);
- val += msg.readInt16(); // MDEF bonus
- player_node->setAttributeEffective(MDEF, val);
-
- val = msg.readInt16(); // HIT
- player_node->setAttributeBase(HIT, val);
- player_node->setAttributeEffective(HIT, val);
-
- val = msg.readInt16(); // FLEE
- player_node->setAttributeBase(FLEE, val);
- val += msg.readInt16(); // FLEE bonus
- player_node->setAttributeEffective(FLEE, val);
-
- val = msg.readInt16();
- player_node->setAttributeBase(CRIT, val);
- player_node->setAttributeEffective(CRIT, val);
+ PlayerInfo::setStatBase(ATK, msg.readInt16(), false);
+ PlayerInfo::setStatMod(ATK, msg.readInt16());
+
+ PlayerInfo::setStatBase(MATK, msg.readInt16(), false);
+ PlayerInfo::setStatMod(MATK, msg.readInt16());
+
+
+ PlayerInfo::setStatBase(DEF, msg.readInt16(), false);
+ PlayerInfo::setStatMod(DEF, msg.readInt16());
+
+ PlayerInfo::setStatBase(MDEF, msg.readInt16(), false);
+ PlayerInfo::setStatMod(MDEF, msg.readInt16());
+
+ PlayerInfo::setStatBase(HIT, msg.readInt16());
+
+ PlayerInfo::setStatBase(FLEE, msg.readInt16(), false);
+ PlayerInfo::setStatMod(FLEE, msg.readInt16());
+
+ PlayerInfo::setStatBase(CRIT, msg.readInt16());
}
msg.readInt16(); // manner
@@ -533,8 +477,9 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
switch (type)
{
case 0:
- localChatTab->chatLog(_("Equip arrows first."),
- BY_SERVER);
+ {
+ SERVER_NOTICE(_("Equip arrows first."))
+ }
break;
default:
logger->log("0x013b: Unhandled message %i", type);
@@ -575,7 +520,7 @@ void PlayerHandler::decreaseAttribute(int attr)
void PlayerHandler::increaseSkill(int skillId)
{
- if (player_node->getSkillPoints() <= 0)
+ if (PlayerInfo::getAttribute(SKILL_POINTS) <= 0)
return;
MessageOut outMsg(CMSG_SKILL_LEVELUP_REQUEST);
@@ -584,8 +529,11 @@ void PlayerHandler::increaseSkill(int skillId)
void PlayerHandler::pickUp(FloorItem *floorItem)
{
- MessageOut outMsg(CMSG_ITEM_PICKUP);
- outMsg.writeInt32(floorItem->getId());
+ if (floorItem)
+ {
+ MessageOut outMsg(CMSG_ITEM_PICKUP);
+ outMsg.writeInt32(floorItem->getId());
+ }
}
void PlayerHandler::setDirection(char direction)
@@ -634,7 +582,7 @@ void PlayerHandler::ignoreAll(bool ignore)
bool PlayerHandler::canUseMagic()
{
- return player_node->getAttributeEffective(MATK) > 0;
+ return PlayerInfo::getStatEffective(MATK) > 0;
}
bool PlayerHandler::canCorrectAttributes()
diff --git a/src/net/tmwa/specialhandler.cpp b/src/net/tmwa/specialhandler.cpp
index c5f5d540..577bda7e 100644
--- a/src/net/tmwa/specialhandler.cpp
+++ b/src/net/tmwa/specialhandler.cpp
@@ -21,13 +21,12 @@
#include "net/tmwa/specialhandler.h"
-#include "localplayer.h"
+#include "event.h"
#include "log.h"
+#include "playerinfo.h"
#include "gui/skilldialog.h"
-#include "gui/widgets/chattab.h"
-
#include "net/messagein.h"
#include "net/messageout.h"
@@ -105,8 +104,7 @@ void SpecialHandler::handleMessage(Net::MessageIn &msg)
msg.skip(24); // unused
int up = msg.readInt8();
- player_node->setAttributeBase(skillId, level);
- player_node->setAttributeEffective(skillId, level);
+ PlayerInfo::setStatBase(skillId, level);
skillDialog->setModifiable(skillId, up);
}
break;
@@ -119,8 +117,7 @@ void SpecialHandler::handleMessage(Net::MessageIn &msg)
msg.readInt16(); // range
int up = msg.readInt8();
- player_node->setAttributeBase(skillId, level);
- player_node->setAttributeEffective(skillId, level);
+ PlayerInfo::setStatBase(skillId, level);
skillDialog->setModifiable(skillId, up);
}
break;
@@ -218,7 +215,7 @@ void SpecialHandler::handleMessage(Net::MessageIn &msg)
}
}
- localChatTab->chatLog(msg);
+ SERVER_NOTICE(msg)
break;
}
}
diff --git a/src/net/tmwa/token.h b/src/net/tmwa/token.h
index d2a21012..3e781cd8 100644
--- a/src/net/tmwa/token.h
+++ b/src/net/tmwa/token.h
@@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "player.h"
+#include "being.h"
#ifndef NET_TA_TOKEN_H
#define NET_TA_TOKEN_H
diff --git a/src/net/tmwa/tradehandler.cpp b/src/net/tmwa/tradehandler.cpp
index 9089f8e6..ee7931bd 100644
--- a/src/net/tmwa/tradehandler.cpp
+++ b/src/net/tmwa/tradehandler.cpp
@@ -21,16 +21,16 @@
#include "net/tmwa/tradehandler.h"
+#include "event.h"
#include "inventory.h"
#include "item.h"
#include "localplayer.h"
+#include "playerinfo.h"
#include "playerrelations.h"
#include "gui/confirmdialog.h"
#include "gui/trade.h"
-#include "gui/widgets/chattab.h"
-
#include "net/inventoryhandler.h"
#include "net/messagein.h"
#include "net/messageout.h"
@@ -96,14 +96,14 @@ void TradeHandler::handleMessage(Net::MessageIn &msg)
if (player_relations.hasPermission(tradePartnerName,
PlayerRelation::TRADE))
{
- if (!player_node->tradeRequestOk() || confirmDlg)
+ if (PlayerInfo::isTrading() || confirmDlg)
{
Net::getTradeHandler()->respond(false);
break;
}
tradePartnerName = tradePartnerNameTemp;
- player_node->setTrading(true);
+ PlayerInfo::setTrading(true);
confirmDlg = new ConfirmDialog(_("Request for Trade"),
strprintf(_("%s wants to trade with you, do you "
"accept?"), tradePartnerName.c_str()));
@@ -121,16 +121,16 @@ void TradeHandler::handleMessage(Net::MessageIn &msg)
switch (msg.readInt8())
{
case 0: // Too far away
- localChatTab->chatLog(_("Trading isn't possible. Trade "
- "partner is too far away."), BY_SERVER);
+ SERVER_NOTICE(_("Trading isn't possible. Trade "
+ "partner is too far away."))
break;
case 1: // Character doesn't exist
- localChatTab->chatLog(_("Trading isn't possible. Character "
- "doesn't exist."), BY_SERVER);
+ SERVER_NOTICE(_("Trading isn't possible. Character "
+ "doesn't exist."))
break;
case 2: // Invite request check failed...
- localChatTab->chatLog(_("Trade cancelled due to an unknown "
- "reason."), BY_SERVER);
+ SERVER_NOTICE(_("Trade cancelled due to an unknown "
+ "reason."))
break;
case 3: // Trade accepted
tradeWindow->reset();
@@ -141,17 +141,15 @@ void TradeHandler::handleMessage(Net::MessageIn &msg)
case 4: // Trade cancelled
if (player_relations.hasPermission(tradePartnerName,
PlayerRelation::SPEECH_LOG))
- localChatTab->chatLog(strprintf(_("Trade with %s "
- "cancelled."), tradePartnerName.c_str()),
- BY_SERVER);
+ SERVER_NOTICE(strprintf(_("Trade with %s cancelled."),
+ tradePartnerName.c_str()))
// otherwise ignore silently
tradeWindow->setVisible(false);
- player_node->setTrading(false);
+ PlayerInfo::setTrading(false);
break;
default: // Shouldn't happen as well, but to be sure
- localChatTab->chatLog(_("Unhandled trade cancel packet."),
- BY_SERVER);
+ SERVER_NOTICE(_("Unhandled trade cancel packet."))
break;
}
break;
@@ -177,7 +175,7 @@ void TradeHandler::handleMessage(Net::MessageIn &msg)
// Trade: New Item add response (was 0x00ea, now 01b1)
{
const int index = msg.readInt16() - INVENTORY_OFFSET;
- Item *item = player_node->getInventory()->getItem(index);
+ Item *item = PlayerInfo::getInventory()->getItem(index);
if (!item)
{
tradeWindow->receivedOk(true);
@@ -199,17 +197,17 @@ void TradeHandler::handleMessage(Net::MessageIn &msg)
break;
case 1:
// Add item failed - player overweighted
- localChatTab->chatLog(_("Failed adding item. Trade "
- "partner is over weighted."), BY_SERVER);
+ SERVER_NOTICE(_("Failed adding item. Trade "
+ "partner is over weighted."))
break;
case 2:
// Add item failed - player has no free slot
- localChatTab->chatLog(_("Failed adding item. Trade "
- "partner has no free slot."), BY_SERVER);
+ SERVER_NOTICE(_("Failed adding item. Trade "
+ "partner has no free slot."))
break;
default:
- localChatTab->chatLog(_("Failed adding item for "
- "unknown reason."), BY_SERVER);
+ SERVER_NOTICE(_("Failed adding item for "
+ "unknown reason."))
break;
}
}
@@ -221,17 +219,17 @@ void TradeHandler::handleMessage(Net::MessageIn &msg)
break;
case SMSG_TRADE_CANCEL:
- localChatTab->chatLog(_("Trade canceled."), BY_SERVER);
+ SERVER_NOTICE(_("Trade canceled."))
tradeWindow->setVisible(false);
tradeWindow->reset();
- player_node->setTrading(false);
+ PlayerInfo::setTrading(false);
break;
case SMSG_TRADE_COMPLETE:
- localChatTab->chatLog(_("Trade completed."), BY_SERVER);
+ SERVER_NOTICE(_("Trade completed."))
tradeWindow->setVisible(false);
tradeWindow->reset();
- player_node->setTrading(false);
+ PlayerInfo::setTrading(false);
break;
}
}
@@ -245,7 +243,7 @@ void TradeHandler::request(Being *being)
void TradeHandler::respond(bool accept)
{
if (!accept)
- player_node->setTrading(false);
+ PlayerInfo::setTrading(false);
MessageOut outMsg(CMSG_TRADE_RESPONSE);
outMsg.writeInt8(accept ? 3 : 4);
diff --git a/src/net/tradehandler.h b/src/net/tradehandler.h
index 30798c41..ea3c4550 100644
--- a/src/net/tradehandler.h
+++ b/src/net/tradehandler.h
@@ -30,6 +30,8 @@ namespace Net {
class TradeHandler
{
public:
+ virtual ~TradeHandler() {}
+
virtual void request(Being *being) {}
virtual void respond(bool accept) {}
@@ -45,8 +47,6 @@ class TradeHandler
virtual void finish() {}
virtual void cancel() {}
-
- virtual ~TradeHandler() {}
};
}
diff --git a/src/npc.cpp b/src/npc.cpp
deleted file mode 100644
index a3c26618..00000000
--- a/src/npc.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "animatedsprite.h"
-#include "beingmanager.h"
-#include "npc.h"
-#include "particle.h"
-#include "text.h"
-
-#include "gui/buy.h"
-#include "gui/buysell.h"
-#include "gui/npcdialog.h"
-#include "gui/npcpostdialog.h"
-#include "gui/userpalette.h"
-#include "gui/sell.h"
-
-#include "net/net.h"
-#include "net/npchandler.h"
-
-#include "resources/npcdb.h"
-#include "configuration.h"
-
-NPC::NPC(int id, int subtype, Map *map):
- Player(id, subtype, map, true)
-{
- setSubtype(subtype);
-
- setShowName(true);
-}
-
-void NPC::setName(const std::string &name)
-{
- const std::string displayName = name.substr(0, name.find('#', 0));
-
- Being::setName(displayName);
-
- mNameColor = &userPalette->getColor(UserPalette::NPC);
-
- mDispName->setColor(mNameColor);
-}
-
-void NPC::setSubtype(Uint16 subtype)
-{
- Being::setSubtype(subtype);
-
- NPCInfo info = NPCDB::get(subtype);
-
- mSprites.clear();
- // Setup NPC sprites
- for (std::list<NPCsprite*>::const_iterator i = info.sprites.begin();
- i != info.sprites.end();
- i++)
- {
- std::string file = paths.getValue("sprites",
- "graphics/sprites/") + (*i)->sprite;
- int variant = (*i)->variant;
- mSprites.push_back(AnimatedSprite::load(file, variant));
- mSpriteIDs.push_back(0);
- mSpriteColors.push_back("");
- }
-
- if (Particle::enabled)
- {
- //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);
- }
- }
-}
-
-void NPC::talk()
-{
- Net::getNpcHandler()->talk(mId);
-}
-
-void NPC::setSprite(unsigned int slot, int id, const std::string &color)
-{
- // Do nothing
-}
-
-bool NPC::isTalking()
-{
- return NpcDialog::isActive() || BuyDialog::isActive() ||
- SellDialog::isActive() || BuySellDialog::isActive() ||
- NpcPostDialog::isActive();
-}
diff --git a/src/npc.h b/src/npc.h
deleted file mode 100644
index 0abd2395..00000000
--- a/src/npc.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef NPC_H
-#define NPC_H
-
-#include "player.h"
-
-class Graphics;
-class Text;
-
-class NPC : public Player
-{
- public:
- NPC(int id, int subtype, Map *map);
-
- void setName(const std::string &name);
-
- virtual Type getType() const { return Being::NPC; }
-
- virtual void setSubtype(Uint16 subtype);
-
- void talk();
-
- void setSprite(unsigned int slot, int id,
- const std::string &color = "");
-
- /**
- * Gets the way an NPC is blocked by other things on the map
- */
- virtual unsigned char getWalkMask() const
- {
- return Map::BLOCKMASK_WALL
- | Map::BLOCKMASK_CHARACTER
- | Map::BLOCKMASK_MONSTER;
- }
-
- /** We consider NPCs (at least for now) to be one layer-sprites */
- virtual int getNumberOfLayers() const
- { return 1; }
-
- static bool isTalking();
-
- protected:
- /**
- * Gets the way a monster blocks pathfinding for other objects
- */
- virtual Map::BlockType getBlockType() const
- { return Map::BLOCKTYPE_CHARACTER; } //blocks like a player character
-
- // Colors don't change for NPCs
- virtual void updateColors() {}
-};
-
-#endif
diff --git a/src/particle.cpp b/src/particle.cpp
index 84161c9f..e3c45a9f 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -63,7 +63,6 @@ Particle::Particle(Map *map):
mFadeIn(0),
mAlpha(1.0f),
mAutoDelete(true),
- mMap(map),
mAllowSizeAdjust(false),
mGravity(0.0f),
mRandomness(0),
@@ -74,16 +73,12 @@ Particle::Particle(Map *map):
mInvDieDistance(-1.0f),
mMomentum(1.0f)
{
+ setMap(map);
Particle::particleCount++;
- if (mMap)
- setSpriteIterator(mMap->addSprite(this));
}
Particle::~Particle()
{
- // Remove from map sprite list
- if (mMap)
- mMap->removeSprite(mSpriteIterator);
// Delete child emitters and child particles
clear();
Particle::particleCount--;
@@ -91,16 +86,17 @@ Particle::~Particle()
void Particle::setupEngine()
{
- Particle::maxCount = (int)config.getValue("particleMaxCount", 3000);
- Particle::fastPhysics = (int)config.getValue("particleFastPhysics", 0);
- Particle::emitterSkip = (int)config.getValue("particleEmitterSkip", 1) + 1;
- Particle::enabled = (bool)config.getValue("particleeffects", true);
+ Particle::maxCount = config.getIntValue("particleMaxCount");
+ Particle::fastPhysics = config.getIntValue("particleFastPhysics");
+ Particle::emitterSkip = config.getIntValue("particleEmitterSkip") + 1;
+ Particle::enabled = config.getBoolValue("particleeffects");
disableAutoDelete();
logger->log("Particle engine set up");
}
-void Particle::draw(Graphics *, int, int) const
+bool Particle::draw(Graphics *, int, int) const
{
+ return false;
}
bool Particle::update()
@@ -393,13 +389,6 @@ void Particle::adjustEmitterSize(int w, int h)
}
}
-void Particle::setMap(Map *map)
-{
- mMap = map;
- if (mMap)
- setSpriteIterator(mMap->addSprite(this));
-}
-
void Particle::clear()
{
delete_all(mChildEmitters);
diff --git a/src/particle.h b/src/particle.h
index 0690e8c4..2be169c1 100644
--- a/src/particle.h
+++ b/src/particle.h
@@ -22,8 +22,8 @@
#ifndef PARTICLE_H
#define PARTICLE_H
+#include "actor.h"
#include "guichanfwd.h"
-#include "sprite.h"
#include "vector.h"
#include <list>
@@ -41,7 +41,7 @@ typedef Emitters::iterator EmitterIterator;
/**
* A particle spawned by a ParticleEmitter.
*/
-class Particle : public Sprite
+class Particle : public Actor
{
public:
static const float PARTICLE_SKY; /**< Maximum Z position of particles */
@@ -83,7 +83,7 @@ class Particle : public Sprite
/**
* Draws the particle image.
*/
- virtual void draw(Graphics *graphics, int offsetX, int offsetY) const;
+ virtual bool draw(Graphics *graphics, int offsetX, int offsetY) const;
/**
* Necessary for sorting with the other sprites.
@@ -92,12 +92,6 @@ class Particle : public Sprite
{ return (int) (mPos.y + mPos.z) - 64; }
/**
- * Sets the map the particle is on.
- */
- void setMap(Map *map);
-
-
- /**
* Creates a blank particle as a child of the current particle
* Useful for creating target particles
*/
@@ -142,12 +136,6 @@ class Particle : public Sprite
void moveTo(float x, float y);
/**
- * Returns the particle position.
- */
- const Vector& getPosition() const
- { return mPos; }
-
- /**
* Changes the particle position relative
*/
void moveBy (const Vector &change);
@@ -173,32 +161,6 @@ class Particle : public Sprite
{ mFadeIn = fadeIn; }
/**
- * Sets the alpha value of the particle
- */
- void setAlpha(float alpha)
- { mAlpha = alpha; }
-
- /**
- * Returns the current alpha opacity of the particle.
- */
- virtual float getAlpha() const
- { return mAlpha; }
-
- /**
- * Sets the sprite iterator of the particle on the current map to make
- * it easier to remove the particle from the map when it is destroyed.
- */
- void setSpriteIterator(std::list<Sprite*>::iterator spriteIterator)
- { mSpriteIterator = spriteIterator; }
-
- /**
- * Gets the sprite iterator of the particle on the current map.
- */
- std::list<Sprite*>::iterator
- getSpriteIterator() const
- { return mSpriteIterator; }
-
- /**
* Sets the current velocity in 3 dimensional space.
*/
void setVelocity(float x, float y, float z)
@@ -285,9 +247,13 @@ class Particle : public Sprite
virtual int getNumberOfLayers() const
{ return 1; }
+ virtual float getAlpha() const
+ { return 1.0f; }
+
+ virtual void setAlpha(float alpha) {}
+
protected:
bool mAlive; /**< Is the particle supposed to be drawn and updated?*/
- Vector mPos; /**< Position in pixels relative to map. */
int mLifetimeLeft; /**< Lifetime left in game ticks*/
int mLifetimePast; /**< Age of the particle in game ticks*/
int mFadeOut; /**< Lifetime in game ticks left where fading out begins*/
@@ -296,8 +262,6 @@ class Particle : public Sprite
// generic properties
bool mAutoDelete; /**< May the particle request its deletion by the parent particle? */
- Map *mMap; /**< Map the particle is on. */
- std::list<Sprite*>::iterator mSpriteIterator; /**< iterator of the particle on the current map */
Emitters mChildEmitters; /**< List of child emitters. */
Particles mChildParticles; /**< List of particles controlled by this particle */
bool mAllowSizeAdjust; /**< Can the effect size be adjusted by the object props in the map file? */
diff --git a/src/party.cpp b/src/party.cpp
index 75283916..99295792 100644
--- a/src/party.cpp
+++ b/src/party.cpp
@@ -20,8 +20,7 @@
#include "party.h"
-#include "beingmanager.h"
-#include "player.h"
+#include "actorspritemanager.h"
PartyMember::PartyMember(Party *party, int id, const std::string &name):
Avatar(name), mId(id), mParty(party), mLeader(false)
@@ -144,9 +143,9 @@ void Party::removeFromMembers()
itr_end = mMembers.end();
while(itr != itr_end)
{
- Being *b = beingManager->findBeing((*itr)->getID());
- if (b->getType() == Being::PLAYER)
- static_cast<Player*>(b)->setParty(NULL);
+ Being *b = actorSpriteManager->findBeing((*itr)->getID());
+ if (b)
+ b->setParty(NULL);
++itr;
}
}
diff --git a/src/player.cpp b/src/player.cpp
deleted file mode 100644
index e6102b6a..00000000
--- a/src/player.cpp
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "player.h"
-
-#include "animatedsprite.h"
-#include "client.h"
-#include "configuration.h"
-#include "guild.h"
-#include "localplayer.h"
-#include "particle.h"
-#include "party.h"
-#include "text.h"
-
-#include "gui/socialwindow.h"
-#include "gui/theme.h"
-#include "gui/userpalette.h"
-
-#include "net/charhandler.h"
-#include "net/net.h"
-
-#include "resources/colordb.h"
-#include "resources/itemdb.h"
-#include "resources/iteminfo.h"
-
-#include "utils/stringutils.h"
-
-Player::Player(int id, int subtype, Map *map, bool isNPC):
- Being(id, subtype, map),
- mGender(GENDER_UNSPECIFIED),
- mParty(NULL),
- mIsGM(false)
-{
- if (!isNPC)
- {
- for (int i = 0; i < Net::getCharHandler()->maxSprite(); i++)
- {
- mSprites.push_back(NULL);
- mSpriteIDs.push_back(0);
- mSpriteColors.push_back("");
- }
-
- setSubtype(subtype);
- }
- mShowName = config.getValue("visiblenames", 1);
- config.addListener("visiblenames", this);
-
- updateColors();
-}
-
-Player::~Player()
-{
- config.removeListener("visiblenames", this);
-}
-
-void Player::logic()
-{
- if (Net::getNetworkType() == ServerInfo::TMWATHENA)
- {
- switch (mAction)
- {
- case STAND:
- case SIT:
- case DEAD:
- case HURT:
- break;
-
- case WALK:
- mFrame = (int) ((get_elapsed_time(mWalkTime) * 6)
- / getWalkSpeed().x);
- if (mFrame >= 6)
- nextTile();
- break;
-
- case ATTACK:
- int rotation = 0;
- std::string particleEffect = "";
- int frames = 4;
-
- if (mEquippedWeapon &&
- mEquippedWeapon->getAttackType() == ACTION_ATTACK_BOW)
- {
- frames = 5;
- }
-
- mFrame = (get_elapsed_time(mWalkTime) * frames) / mAttackSpeed;
-
- //attack particle effect
- if (mEquippedWeapon)
- particleEffect = mEquippedWeapon->getParticleEffect();
-
- if (!particleEffect.empty() && Particle::enabled && mFrame == 1)
- {
- switch (mDirection)
- {
- case DOWN: rotation = 0; break;
- case LEFT: rotation = 90; break;
- case UP: rotation = 180; break;
- case RIGHT: rotation = 270; break;
- default: break;
- }
- Particle *p;
- p = particleEngine->addEffect(
- paths.getValue("particles",
- "graphics/particles/")
- + particleEffect, 0, 0, rotation);
- controlParticle(p);
- }
-
- if (mFrame >= frames)
- nextTile();
-
- break;
- }
- }
-
- Being::logic();
-}
-
-void Player::setSubtype(Uint16 subtype)
-{
- Being::setSubtype(subtype);
-
- int id = -100 - subtype;
- if (ItemDB::exists(id)) // Prevent showing errors when sprite doesn't exist
- setSprite(Net::getCharHandler()->baseSprite(), id);
- else
- setSprite(Net::getCharHandler()->baseSprite(), -100);
-}
-
-void Player::setGender(Gender gender)
-{
- if (gender != mGender)
- {
- mGender = gender;
-
- // Reload all subsprites
- for (unsigned int i = 0; i < mSprites.size(); i++)
- {
- if (mSpriteIDs.at(i) != 0)
- setSprite(i, mSpriteIDs.at(i), mSpriteColors.at(i));
- }
- }
-}
-
-void Player::setGM(bool gm)
-{
- mIsGM = gm;
-
- updateColors();
-}
-
-void Player::setSprite(int slot, int id, const std::string &color,
- bool isWeapon)
-{
- if (getType() == NPC)
- return;
-
- assert(slot < Net::getCharHandler()->maxSprite());
-
- // id = 0 means unequip
- if (id == 0)
- {
- delete mSprites[slot];
- mSprites[slot] = NULL;
-
- if (isWeapon)
- mEquippedWeapon = NULL;
- }
- else
- {
- std::string filename = ItemDB::get(id).getSprite(mGender);
- AnimatedSprite *equipmentSprite = NULL;
-
- if (!filename.empty())
- {
- if (!color.empty())
- filename += "|" + color;
-
- equipmentSprite = AnimatedSprite::load(
- paths.getValue("sprites", "graphics/sprites/") + filename);
- }
-
- if (equipmentSprite)
- equipmentSprite->setDirection(getSpriteDirection());
-
- if (mSprites[slot])
- delete mSprites[slot];
-
- mSprites[slot] = equipmentSprite;
-
- if (isWeapon)
- mEquippedWeapon = &ItemDB::get(id);
-
- setAction(mAction);
- }
-
- mSpriteIDs[slot] = id;
- mSpriteColors[slot] = color;
-}
-
-void Player::setSpriteID(unsigned int slot, int id)
-{
- setSprite(slot, id, mSpriteColors[slot]);
-}
-
-void Player::setSpriteColor(unsigned int slot, const std::string &color)
-{
- setSprite(slot, mSpriteIDs[slot], color);
-}
-
-void Player::addGuild(Guild *guild)
-{
- mGuilds[guild->getId()] = guild;
- guild->addMember(mId, mName);
-
- if (this == player_node && socialWindow)
- {
- socialWindow->addTab(guild);
- }
-}
-
-void Player::removeGuild(int id)
-{
- if (this == player_node && socialWindow)
- {
- socialWindow->removeTab(mGuilds[id]);
- }
-
- mGuilds[id]->removeMember(mId);
- mGuilds.erase(id);
-}
-
-Guild *Player::getGuild(const std::string &guildName) const
-{
- std::map<int, Guild*>::const_iterator itr, itr_end = mGuilds.end();
- for (itr = mGuilds.begin(); itr != itr_end; ++itr)
- {
- Guild *guild = itr->second;
- if (guild->getName() == guildName)
- {
- return guild;
- }
- }
-
- return NULL;
-}
-
-Guild *Player::getGuild(int id) const
-{
- std::map<int, Guild*>::const_iterator itr;
- itr = mGuilds.find(id);
- if (itr != mGuilds.end())
- {
- return itr->second;
- }
-
- return NULL;
-}
-
-const std::map<int, Guild*> &Player::getGuilds() const
-{
- return mGuilds;
-}
-
-void Player::clearGuilds()
-{
- std::map<int, Guild*>::const_iterator itr, itr_end = mGuilds.end();
- for (itr = mGuilds.begin(); itr != itr_end; ++itr)
- {
- Guild *guild = itr->second;
-
- if (this == player_node && socialWindow)
- socialWindow->removeTab(guild);
-
- guild->removeMember(mId);
- }
-
- mGuilds.clear();
-}
-
-void Player::setParty(Party *party)
-{
- if (party == mParty)
- return;
-
- Party *old = mParty;
- mParty = party;
-
- if (old)
- {
- old->removeMember(mId);
- }
-
- if (party)
- {
- party->addMember(mId, mName);
- }
-
- updateColors();
-
- if (this == player_node && socialWindow)
- {
- if (old)
- socialWindow->removeTab(old);
-
- if (party)
- socialWindow->addTab(party);
- }
-}
-
-void Player::optionChanged(const std::string &value)
-{
- if (value == "visiblenames")
- {
- setShowName(config.getValue("visiblenames", 1));
- }
-}
-
-void Player::updateColors()
-{
- mTextColor = &userPalette->getColor(Theme::PLAYER);
-
- if (mIsGM)
- {
- mTextColor = &userPalette->getColor(Theme::GM);
- mNameColor = &userPalette->getColor(UserPalette::GM);
- }
- else if (mParty && mParty == player_node->getParty())
- {
- mNameColor = &userPalette->getColor(UserPalette::PARTY);
- }
- else
- {
- mNameColor = &userPalette->getColor(UserPalette::PC);
- }
-
- if (mDispName)
- {
- mDispName->setColor(mNameColor);
- }
-}
diff --git a/src/player.h b/src/player.h
deleted file mode 100644
index e75870a0..00000000
--- a/src/player.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef PLAYER_H
-#define PLAYER_H
-
-#include "being.h"
-
-class Graphics;
-class Guild;
-class Map;
-class Party;
-
-enum Gender
-{
- GENDER_MALE = 0,
- GENDER_FEMALE = 1,
- GENDER_UNSPECIFIED = 2
-};
-
-/**
- * A player being. Players have their name drawn beneath them. This class also
- * implements player-specific loading of base sprite, hair sprite and equipment
- * sprites.
- */
-class Player : public Being
-{
- public:
- /**
- * Constructor.
- */
- Player(int id, int subtype, Map *map, bool isNPC = false);
-
- ~Player();
-
- virtual void logic();
-
- virtual Type getType() const { return PLAYER; }
-
- virtual void setSubtype(Uint16 subtype);
-
- /**
- * Sets the gender of this being.
- */
- virtual void setGender(Gender gender);
-
- Gender getGender() const { return mGender; }
-
- /**
- * Whether or not this player is a GM.
- */
- bool isGM() const { return mIsGM; }
-
- /**
- * Triggers whether or not to show the name as a GM name.
- */
- virtual void setGM(bool gm);
-
- /**
- * Sets visible equipments for this player.
- */
- virtual void setSprite(int slot, int id,
- const std::string &color = "",
- bool isWeapon = false);
-
- virtual void setSpriteID(unsigned int slot, int id);
-
- virtual void setSpriteColor(unsigned int slot,
- const std::string &color = "");
-
- /**
- * Adds a guild to the player.
- */
- void addGuild(Guild *guild);
-
- /**
- * Removers a guild from the player.
- */
- void removeGuild(int id);
-
- /**
- * Returns a pointer to the specified guild.
- */
- Guild *getGuild(const std::string &guildName) const;
-
- /**
- * Returns a pointer to the guild with matching id.
- */
- Guild *getGuild(int id) const;
-
- /**
- * Returns all guilds the player is in.
- */
- const std::map<int, Guild*> &getGuilds() const;
-
- /**
- * Removes all guilds the player is in.
- */
- void clearGuilds();
-
- /**
- * Get number of guilds the player belongs to.
- */
- short getNumberOfGuilds() const { return mGuilds.size(); }
-
- bool isInParty() const { return mParty != NULL; }
-
- void setParty(Party *party);
-
- Party *getParty() const { return mParty; }
-
- /**
- * Gets the way the character is blocked by other objects.
- */
- virtual unsigned char getWalkMask() const
- { return Map::BLOCKMASK_WALL | Map::BLOCKMASK_MONSTER; }
-
- /**
- * Called when a option (set with config.addListener()) is changed
- */
- virtual void optionChanged(const std::string &value);
-
- protected:
- /**
- * Gets the way the monster blocks pathfinding for other objects.
- */
- virtual Map::BlockType getBlockType() const
- { return Map::BLOCKTYPE_CHARACTER; }
-
- virtual void updateColors();
-
- Gender mGender;
- std::vector<int> mSpriteIDs;
- std::vector<std::string> mSpriteColors;
-
- // Character guild information
- std::map<int, Guild*> mGuilds;
- Party *mParty;
-
- bool mIsGM;
-};
-
-#endif
diff --git a/src/playerinfo.cpp b/src/playerinfo.cpp
new file mode 100644
index 00000000..cebd15dc
--- /dev/null
+++ b/src/playerinfo.cpp
@@ -0,0 +1,405 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "playerinfo.h"
+
+#include "client.h"
+#include "equipment.h"
+#include "event.h"
+#include "inventory.h"
+#include "listener.h"
+#include "log.h"
+
+#include "resources/itemdb.h"
+#include "resources/iteminfo.h"
+
+namespace PlayerInfo {
+
+class PlayerLogic;
+
+PlayerLogic *mListener = 0;
+
+PlayerInfoBackend mData;
+
+Inventory *mInventory = 0;
+Equipment *mEquipment = 0;
+
+bool mStorageCount = 0;
+
+bool mNPCCount = 0;
+bool mNPCPostCount = 0;
+
+BuySellState mBuySellState = BUYSELL_NONE;
+bool mTrading = false;
+
+std::map<int, Special> mSpecials;
+char mSpecialRechargeUpdateNeeded = 0;
+
+int mLevelProgress = 0;
+
+// --- Triggers ---------------------------------------------------------------
+
+void triggerAttr(int id, int old)
+{
+ Mana::Event event("UpdateAttribute");
+ event.setInt("id", id);
+ event.setInt("oldValue", old);
+ event.setInt("newValue", mData.mAttributes.find(id)->second);
+ event.trigger("Attributes");
+}
+
+void triggerStat(int id, const std::string &changed, int old1, int old2 = 0)
+{
+ StatMap::iterator it = mData.mStats.find(id);
+ Mana::Event event("UpdateStat");
+ event.setInt("id", id);
+ event.setInt("base", it->second.base);
+ event.setInt("mod", it->second.mod);
+ event.setInt("exp", it->second.exp);
+ event.setInt("expNeeded", it->second.expNeed);
+ event.setString("changed", changed);
+ event.setInt("oldValue1", old1);
+ event.setInt("oldValue2", old2);
+ event.trigger("Attributes");
+}
+
+// --- Attributes -------------------------------------------------------------
+
+int getAttribute(int id)
+{
+ IntMap::const_iterator it = mData.mAttributes.find(id);
+ if (it != mData.mAttributes.end())
+ return it->second;
+ else
+ return 0;
+}
+
+void setAttribute(int id, int value, bool notify)
+{
+ int old = mData.mAttributes[id];
+ mData.mAttributes[id] = value;
+ if (notify)
+ triggerAttr(id, old);
+}
+
+// --- Stats ------------------------------------------------------------------
+
+int getStatBase(int id)
+{
+ StatMap::const_iterator it = mData.mStats.find(id);
+ if (it != mData.mStats.end())
+ return it->second.base;
+ else
+ return 0;
+}
+
+void setStatBase(int id, int value, bool notify)
+{
+ int old = mData.mStats[id].base;
+ mData.mStats[id].base = value;
+ if (notify)
+ triggerStat(id, "base", old);
+}
+
+int getStatMod(int id)
+{
+ StatMap::const_iterator it = mData.mStats.find(id);
+ if (it != mData.mStats.end())
+ return it->second.mod;
+ else
+ return 0;
+}
+
+void setStatMod(int id, int value, bool notify)
+{
+ int old = mData.mStats[id].mod;
+ mData.mStats[id].mod = value;
+ if (notify)
+ triggerStat(id, "mod", old);
+}
+
+int getStatEffective(int id)
+{
+ StatMap::const_iterator it = mData.mStats.find(id);
+ if (it != mData.mStats.end())
+ return it->second.base + it->second.mod;
+ else
+ return 0;
+}
+
+std::pair<int, int> getStatExperience(int id)
+{
+ StatMap::const_iterator it = mData.mStats.find(id);
+ int a, b;
+ if (it != mData.mStats.end())
+ {
+ a = it->second.exp;
+ b = it->second.expNeed;
+ }
+ else
+ {
+ a = 0;
+ b = 0;
+ }
+ return std::pair<int, int>(a, b);
+}
+
+void setStatExperience(int id, int have, int need, bool notify)
+{
+ int oldExp = mData.mStats[id].exp;
+ int oldExpNeed = mData.mStats[id].expNeed;
+ mData.mStats[id].exp = have;
+ mData.mStats[id].expNeed = need;
+ if (notify)
+ triggerStat(id, "exp", oldExp, oldExpNeed);
+}
+
+// --- Inventory / Equipment --------------------------------------------------
+
+Inventory *getInventory()
+{
+ return mInventory;
+}
+
+void clearInventory()
+{
+ mEquipment->clear();
+ mInventory->clear();
+}
+
+void setInventoryItem(int index, int id, int amount)
+{
+ bool equipment = false;
+ int itemType = ItemDB::get(id).getType();
+ if (itemType != ITEM_UNUSABLE && itemType != ITEM_USABLE)
+ equipment = true;
+ mInventory->setItem(index, id, amount, equipment);
+}
+
+Equipment *getEquipment()
+{
+ return mEquipment;
+}
+
+Item *getEquipment(unsigned int slot)
+{
+ return mEquipment->getEquipment(slot);
+}
+
+void setEquipmentBackend(Equipment::Backend *backend)
+{
+ mEquipment->setBackend(backend);
+}
+
+int getStorageCount()
+{
+ return mStorageCount;
+}
+
+void setStorageCount(int count)
+{
+ int old = mStorageCount;
+ mStorageCount = count;
+
+ if (count != old)
+ {
+ Mana::Event event("StorageCount");
+ event.setInt("oldCount", old);
+ event.setInt("newCount", count);
+ event.trigger("Storage");
+ }
+}
+
+// -- NPC ---------------------------------------------------------------------
+
+int getNPCInteractionCount()
+{
+ return mNPCCount;
+}
+
+void setNPCInteractionCount(int count)
+{
+ int old = mNPCCount;
+ mNPCCount = count;
+
+ if (count != old)
+ {
+ Mana::Event event("NPCCount");
+ event.setInt("oldCount", old);
+ event.setInt("newCount", count);
+ event.trigger("NPC");
+ }
+}
+
+int getNPCPostCount()
+{
+ return mNPCPostCount;
+}
+
+void setNPCPostCount(int count)
+{
+ int old = mNPCPostCount;
+ mNPCPostCount = count;
+
+ if (count != old)
+ {
+ Mana::Event event("PostCount");
+ event.setInt("oldCount", old);
+ event.setInt("newCount", count);
+ event.trigger("NPC");
+ }
+}
+
+// -- Buy/Sell/Trade ----------------------------------------------------------
+
+BuySellState getBuySellState()
+{
+ return mBuySellState;
+}
+
+void setBuySellState(BuySellState buySellState)
+{
+ BuySellState old = mBuySellState;
+ mBuySellState = buySellState;
+
+ if (buySellState != old)
+ {
+ Mana::Event event("StateChange");
+ event.setInt("oldState", old);
+ event.setInt("newState", buySellState);
+ event.trigger("BuySell");
+ }
+}
+
+bool isTrading()
+{
+ return mTrading;
+}
+
+void setTrading(bool trading)
+{
+ bool notify = mTrading != trading;
+ mTrading = trading;
+
+ if (notify)
+ {
+ Mana::Event event("Trading");
+ event.setBool("trading", trading);
+ event.trigger("Status");
+ }
+}
+
+// --- Specials ---------------------------------------------------------------
+
+void setSpecialStatus(int id, int current, int max, int recharge)
+{
+ logger->log("SpecialUpdate Skill #%d -- (%d/%d) -> %d", id, current, max,
+ recharge);
+ mSpecials[id].currentMana = current;
+ mSpecials[id].neededMana = max;
+ mSpecials[id].recharge = recharge;
+}
+
+const SpecialsMap &getSpecialStatus()
+{
+ return mSpecials;
+}
+
+// --- Misc -------------------------------------------------------------------
+
+void setBackend(const PlayerInfoBackend &backend)
+{
+ mData = backend;
+}
+
+bool isTalking()
+{
+ return getNPCInteractionCount() || getNPCPostCount()
+ || getBuySellState() != BUYSELL_NONE;
+}
+
+void logic()
+{
+ if ((mSpecialRechargeUpdateNeeded%11) == 0)
+ {
+ mSpecialRechargeUpdateNeeded = 0;
+ for (SpecialsMap::iterator it = mSpecials.begin(),
+ it_end = mSpecials.end(); it != it_end; it++)
+ {
+ it->second.currentMana += it->second.recharge;
+ if (it->second.currentMana > it->second.neededMana)
+ {
+ it->second.currentMana = it->second.neededMana;
+ }
+ }
+ }
+ mSpecialRechargeUpdateNeeded++;
+}
+
+class PlayerLogic : Mana::Listener
+{
+public:
+ PlayerLogic()
+ {
+ listen("Client");
+ listen("Game");
+ }
+
+ void event(const std::string &channel, const Mana::Event &event)
+ {
+ if (channel == "Client")
+ {
+ if (event.getName() == "StateChange")
+ {
+ int newState = event.getInt("newState");
+
+ if (newState == STATE_GAME)
+ {
+ if (mInventory == 0)
+ {
+ mInventory = new Inventory(Inventory::INVENTORY);
+ mEquipment = new Equipment();
+ }
+ }
+ }
+ }
+ else if (channel == "Game")
+ {
+ if (event.getName() == "Destructed")
+ {
+ delete mInventory;
+ delete mEquipment;
+
+ mInventory = 0;
+ mEquipment = 0;
+ }
+ }
+ }
+};
+
+void init()
+{
+ if (mListener)
+ return;
+
+ mListener = new PlayerLogic();
+}
+
+} // namespace PlayerInfo
diff --git a/src/playerinfo.h b/src/playerinfo.h
new file mode 100644
index 00000000..43e7da6e
--- /dev/null
+++ b/src/playerinfo.h
@@ -0,0 +1,273 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PLAYERINFO_H
+#define PLAYERINFO_H
+
+#include <map>
+#include <string>
+
+/**
+ * Standard attributes for players.
+ */
+enum Attribute
+{
+ LEVEL,
+ HP, MAX_HP,
+ MP, MAX_MP,
+ EXP, EXP_NEEDED,
+ MONEY,
+ TOTAL_WEIGHT, MAX_WEIGHT,
+ SKILL_POINTS,
+ CHAR_POINTS, CORR_POINTS
+};
+
+/**
+ * Stat information storage structure.
+ */
+struct Stat
+{
+ int base;
+ int mod;
+ int exp;
+ int expNeed;
+};
+
+typedef std::map<int, int> IntMap;
+typedef std::map<int, Stat> StatMap;
+
+/**
+ * Backend for core player information.
+ */
+struct PlayerInfoBackend
+{
+ IntMap mAttributes;
+ StatMap mStats;
+};
+
+class Equipment;
+class Inventory;
+class Item;
+
+enum BuySellState
+{
+ BUYSELL_NONE,
+ BUYSELL_CHOOSING,
+ BUYSELL_BUYING,
+ BUYSELL_SELLING
+};
+
+/**
+ * Special information storage structure.
+ */
+struct Special
+{
+ int currentMana;
+ int neededMana;
+ int recharge;
+};
+
+typedef std::map<int, Special> SpecialsMap;
+
+/**
+ * A database like namespace which holds global info about the localplayer
+ *
+ * NOTE: 'bool notify' is used to determine if a event is to be triggered.
+ */
+namespace PlayerInfo
+{
+
+// --- Attributes -------------------------------------------------------------
+
+ /**
+ * Returns the value of the given attribute.
+ */
+ int getAttribute(int id);
+
+ /**
+ * Changes the value of the given attribute.
+ */
+ void setAttribute(int id, int value, bool notify = true);
+
+// --- Stats ------------------------------------------------------------------
+
+ /**
+ * Returns the base value of the given stat.
+ */
+ int getStatBase(int id);
+
+ /**
+ * Changes the base value of the given stat.
+ */
+ void setStatBase(int id, int value, bool notify = true);
+
+ /**
+ * Returns the modifier for the given stat.
+ */
+ int getStatMod(int id);
+
+ /**
+ * Changes the modifier for the given stat.
+ */
+ void setStatMod(int id, int value, bool notify = true);
+
+ /**
+ * Returns the current effective value of the given stat. Effective is base
+ * + mod
+ */
+ int getStatEffective(int id);
+
+ /**
+ * Changes the level of the given stat.
+ */
+ void setStatLevel(int id, int value, bool notify = true);
+
+ /**
+ * Returns the experience of the given stat.
+ */
+ std::pair<int, int> getStatExperience(int id);
+
+ /**
+ * Changes the experience of the given stat.
+ */
+ void setStatExperience(int id, int have, int need, bool notify = true);
+
+// --- Inventory / Equipment / Storage ----------------------------------------
+
+ /**
+ * Returns the player's inventory.
+ */
+ Inventory *getInventory();
+
+ /**
+ * Clears the player's inventory and equipment.
+ */
+ void clearInventory();
+
+ /**
+ * Changes the inventory item at the given slot.
+ */
+ void setInventoryItem(int index, int id, int amount);
+
+ /**
+ * Returns the player's equipment.
+ */
+ Equipment *getEquipment();
+
+ /**
+ * Returns the player's equipment at the given slot.
+ */
+ Item *getEquipment(unsigned int slot);
+
+ /**
+ * Returns the number of currently open storage windows.
+ */
+ int getStorageCount();
+
+ /**
+ * Sets the number of currently open storage windows.
+ */
+ void setStorageCount(int count);
+
+// -- NPC ---------------------------------------------------------------------
+
+ /**
+ * Returns the number of currently open NPC interaction windows.
+ */
+ int getNPCInteractionCount();
+
+ /**
+ * Sets the number of currently open NPC interaction windows.
+ */
+ void setNPCInteractionCount(int count);
+
+ /**
+ * Returns the number of currently open NPC post windows.
+ */
+ int getNPCPostCount();
+
+ /**
+ * Sets the number of currently open NPC post windows.
+ */
+ void setNPCPostCount(int count);
+
+// -- Buy/Sell/Trade ----------------------------------------------------------
+
+ /**
+ * Returns the current buy, sell, or related interaction the player is
+ * involved in.
+ */
+ BuySellState getBuySellState();
+
+ /**
+ * Sets which buy, sell, or related interaction the player is currently
+ * involved in.
+ */
+ void setBuySellState(BuySellState buySellState);
+
+ /**
+ * Returns true if the player is involved in a trade at the moment, false
+ * otherwise.
+ */
+ bool isTrading();
+
+ /**
+ * Sets whether the player is currently involved in trade or not.
+ */
+ void setTrading(bool trading);
+
+// --- Specials ---------------------------------------------------------------
+
+ /**
+ * Changes the status of the given special.
+ */
+ void setSpecialStatus(int id, int current, int max, int recharge);
+
+ /**
+ * Returns the status of the given special.
+ */
+ const SpecialsMap &getSpecialStatus();
+
+// --- Misc -------------------------------------------------------------------
+
+ /**
+ * Changes the internal PlayerInfoBackend reference;
+ */
+ void setBackend(const PlayerInfoBackend &backend);
+
+ /**
+ * Returns true if the player is involved in a NPC interaction, false
+ * otherwise.
+ */
+ bool isTalking();
+
+ /**
+ * Does necessary updates every tick.
+ */
+ void logic();
+
+ /**
+ * Initializes some internals.
+ */
+ void init();
+
+} // namespace PlayerInfo
+
+#endif
diff --git a/src/playerrelations.cpp b/src/playerrelations.cpp
index 14d9eb6b..f5d3d01b 100644
--- a/src/playerrelations.cpp
+++ b/src/playerrelations.cpp
@@ -21,11 +21,10 @@
#include <algorithm>
+#include "actorspritemanager.h"
#include "being.h"
-#include "beingmanager.h"
#include "configuration.h"
#include "graphics.h"
-#include "player.h"
#include "playerrelations.h"
#include "utils/dtor.h"
@@ -214,7 +213,7 @@ unsigned int PlayerRelationsManager::checkPermissionSilently(const std::string &
bool PlayerRelationsManager::hasPermission(Being *being, unsigned int flags)
{
- if (being->getType() == Being::PLAYER)
+ if (being->getType() == ActorSprite::PLAYER)
return hasPermission(being->getName(), flags) == flags;
return true;
}
@@ -230,9 +229,10 @@ bool PlayerRelationsManager::hasPermission(const std::string &name,
// execute `ignore' strategy, if possible
if (mIgnoreStrategy)
{
- Being *b = beingManager->findBeingByName(name, Being::PLAYER);
- if (b && b->getType() == Being::PLAYER)
- mIgnoreStrategy->ignore(static_cast<Player *>(b), rejections);
+ Being *b = actorSpriteManager->findBeingByName(name,
+ ActorSprite::PLAYER);
+ if (b && b->getType() == ActorSprite::PLAYER)
+ mIgnoreStrategy->ignore(b, rejections);
}
}
@@ -313,7 +313,7 @@ public:
mShortName = PLAYER_IGNORE_STRATEGY_NOP;
}
- virtual void ignore(Player *player, unsigned int flags)
+ virtual void ignore(Being *being, unsigned int flags)
{
}
};
@@ -327,9 +327,9 @@ public:
mShortName = "dotdotdot";
}
- virtual void ignore(Player *player, unsigned int flags)
+ virtual void ignore(Being *being, unsigned int flags)
{
- player->setSpeech("...", 500);
+ being->setSpeech("...", 500);
}
};
@@ -343,9 +343,9 @@ public:
mShortName = "blinkname";
}
- virtual void ignore(Player *player, unsigned int flags)
+ virtual void ignore(Being *being, unsigned int flags)
{
- player->flashName(200);
+ being->flashName(200);
}
};
@@ -359,9 +359,9 @@ public:
mShortName = shortname;
}
- virtual void ignore(Player *player, unsigned int flags)
+ virtual void ignore(Being *being, unsigned int flags)
{
- player->setEmote(mEmotion, IGNORE_EMOTE_TIME);
+ being->setEmote(mEmotion, IGNORE_EMOTE_TIME);
}
private:
int mEmotion;
diff --git a/src/playerrelations.h b/src/playerrelations.h
index 3ff1e5fd..d6ca31ad 100644
--- a/src/playerrelations.h
+++ b/src/playerrelations.h
@@ -28,7 +28,6 @@
#include <vector>
class Being;
-class Player;
struct PlayerRelation
{
@@ -73,7 +72,7 @@ public:
/**
* Handle the ignoring of the indicated action by the indicated player.
*/
- virtual void ignore(Player *player, unsigned int flags) = 0;
+ virtual void ignore(Being *being, unsigned int flags) = 0;
};
class PlayerRelationsListener
diff --git a/src/resources/beinginfo.cpp b/src/resources/beinginfo.cpp
new file mode 100644
index 00000000..e8824391
--- /dev/null
+++ b/src/resources/beinginfo.cpp
@@ -0,0 +1,107 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "resources/beinginfo.h"
+
+#include "log.h"
+
+#include "utils/dtor.h"
+#include "utils/gettext.h"
+
+BeingInfo *BeingInfo::Unknown = new BeingInfo;
+
+BeingInfo::BeingInfo():
+ mName(_("unnamed")),
+ mTargetCursorSize(ActorSprite::TC_MEDIUM),
+ mWalkMask(Map::BLOCKMASK_WALL | Map::BLOCKMASK_CHARACTER
+ | Map::BLOCKMASK_MONSTER),
+ mBlockType(Map::BLOCKTYPE_CHARACTER)
+{
+ SpriteDisplay display;
+ display.sprites.push_back(SpriteReference::Empty);
+
+ setDisplay(display);
+}
+
+BeingInfo::~BeingInfo()
+{
+ delete_all(mSounds);
+ delete_all(mAttacks);
+ mSounds.clear();
+}
+
+void BeingInfo::setDisplay(SpriteDisplay display)
+{
+ mDisplay = display;
+}
+
+void BeingInfo::setTargetCursorSize(const std::string &size)
+{
+ if (size == "small")
+ setTargetCursorSize(ActorSprite::TC_SMALL);
+ else if (size == "medium")
+ setTargetCursorSize(ActorSprite::TC_MEDIUM);
+ else if (size == "large")
+ setTargetCursorSize(ActorSprite::TC_LARGE);
+ else
+ {
+ logger->log("Unknown target cursor type \"%s\" for %s - using medium "
+ "sized one", size.c_str(), getName().c_str());
+ setTargetCursorSize(ActorSprite::TC_MEDIUM);
+ }
+}
+
+void BeingInfo::addSound(SoundEvent event, const std::string &filename)
+{
+ if (mSounds.find(event) == mSounds.end())
+ {
+ mSounds[event] = new std::vector<std::string>;
+ }
+
+ mSounds[event]->push_back("sfx/" + filename);
+}
+
+const std::string &BeingInfo::getSound(SoundEvent event) const
+{
+ static std::string empty("");
+
+ SoundEvents::const_iterator i = mSounds.find(event);
+ return (i == mSounds.end()) ? empty :
+ i->second->at(rand() % i->second->size());
+}
+
+const Attack *BeingInfo::getAttack(int type) const
+{
+ static Attack *empty = new Attack(SpriteAction::ATTACK, "", "");
+
+ Attacks::const_iterator i = mAttacks.find(type);
+ return (i == mAttacks.end()) ? empty : (*i).second;
+}
+
+void BeingInfo::addAttack(int id, std::string action,
+ const std::string &particleEffect,
+ const std::string &missileParticle)
+{
+ if (mAttacks[id])
+ delete mAttacks[id];
+
+ mAttacks[id] = new Attack(action, particleEffect, missileParticle);
+}
diff --git a/src/resources/beinginfo.h b/src/resources/beinginfo.h
new file mode 100644
index 00000000..52390976
--- /dev/null
+++ b/src/resources/beinginfo.h
@@ -0,0 +1,132 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BEINGINFO_H
+#define BEINGINFO_H
+
+#include "actorsprite.h"
+
+#include "resources/spritedef.h"
+
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+struct Attack {
+ std::string action;
+ std::string particleEffect;
+ std::string missileParticle;
+
+ Attack(std::string action, std::string particleEffect,
+ std::string missileParticle)
+ {
+ this->action = action;
+ this->particleEffect = particleEffect;
+ this->missileParticle = missileParticle;
+ }
+};
+
+typedef std::map<int, Attack*> Attacks;
+
+enum SoundEvent
+{
+ SOUND_EVENT_HIT,
+ SOUND_EVENT_MISS,
+ SOUND_EVENT_HURT,
+ SOUND_EVENT_DIE
+};
+
+typedef std::map<SoundEvent, std::vector<std::string>* > SoundEvents;
+
+/**
+ * Holds information about a certain type of monster. This includes the name
+ * of the monster, the sprite to display and the sounds the monster makes.
+ *
+ * @see MonsterDB
+ * @see NPCDB
+ */
+class BeingInfo
+{
+ public:
+ static BeingInfo *Unknown;
+
+ BeingInfo();
+
+ ~BeingInfo();
+
+ void setName(const std::string &name) { mName = name; }
+
+ const std::string &getName() const
+ { return mName; }
+
+ void setDisplay(SpriteDisplay display);
+
+ const SpriteDisplay &getDisplay() const
+ { return mDisplay; }
+
+ void setTargetCursorSize(const std::string &size);
+
+ void setTargetCursorSize(ActorSprite::TargetCursorSize targetSize)
+ { mTargetCursorSize = targetSize; }
+
+ ActorSprite::TargetCursorSize getTargetCursorSize() const
+ { return mTargetCursorSize; }
+
+ void addSound(SoundEvent event, const std::string &filename);
+
+ const std::string &getSound(SoundEvent event) const;
+
+ void addAttack(int id, std::string action,
+ const std::string &particleEffect,
+ const std::string &missileParticle);
+
+ const Attack *getAttack(int type) const;
+
+ void setWalkMask(unsigned char mask)
+ { mWalkMask = mask; }
+
+ /**
+ * Gets the way the being is blocked by other objects
+ */
+ unsigned char getWalkMask() const
+ { return mWalkMask; }
+
+ void setBlockType(Map::BlockType blockType)
+ { mBlockType = blockType; }
+
+ Map::BlockType getBlockType() const
+ { return mBlockType; }
+
+ private:
+ SpriteDisplay mDisplay;
+ std::string mName;
+ ActorSprite::TargetCursorSize mTargetCursorSize;
+ SoundEvents mSounds;
+ Attacks mAttacks;
+ unsigned char mWalkMask;
+ Map::BlockType mBlockType;
+};
+
+typedef std::map<int, BeingInfo*> BeingInfos;
+typedef BeingInfos::iterator BeingInfoIterator;
+
+#endif // BEINGINFO_H
diff --git a/src/resources/emotedb.cpp b/src/resources/emotedb.cpp
index c24e760b..bd8a8e38 100644
--- a/src/resources/emotedb.cpp
+++ b/src/resources/emotedb.cpp
@@ -43,7 +43,7 @@ void EmoteDB::load()
EmoteSprite *unknownSprite = new EmoteSprite;
unknownSprite->sprite = AnimatedSprite::load(
- paths.getValue("spriteErrorFile", "error.xml") );
+ paths.getStringValue("spriteErrorFile"));
unknownSprite->name = "unknown";
mUnknown.sprites.push_back(unknownSprite);
@@ -78,8 +78,7 @@ void EmoteDB::load()
if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
{
EmoteSprite *currentSprite = new EmoteSprite;
- std::string file = paths.getValue("sprites",
- "graphics/sprites/")
+ std::string file = paths.getStringValue("sprites")
+ (std::string) (const char*)
spriteNode->xmlChildrenNode->content;
currentSprite->sprite = AnimatedSprite::load(file,
diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp
index 3fdee021..a8eed123 100644
--- a/src/resources/itemdb.cpp
+++ b/src/resources/itemdb.cpp
@@ -47,6 +47,7 @@ namespace
// Forward declarations
static void loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node);
static void loadSoundRef(ItemInfo *itemInfo, xmlNodePtr node);
+static void loadFloorSprite(SpriteDisplay *display, xmlNodePtr node);
static char const *const fields[][2] =
{
@@ -84,22 +85,6 @@ static ItemType itemTypeFromString(const std::string &name, int id = 0)
else return ITEM_UNUSABLE;
}
-static WeaponType weaponTypeFromString(const std::string &name, int id = 0)
-{
- if (name=="knife") return WPNTYPE_KNIFE;
- else if (name=="sword") return WPNTYPE_SWORD;
- else if (name=="polearm") return WPNTYPE_POLEARM;
- else if (name=="staff") return WPNTYPE_STAFF;
- else if (name=="whip") return WPNTYPE_WHIP;
- else if (name=="bow") return WPNTYPE_BOW;
- else if (name=="shooting") return WPNTYPE_SHOOTING;
- else if (name=="mace") return WPNTYPE_MACE;
- else if (name=="axe") return WPNTYPE_AXE;
- else if (name=="thrown") return WPNTYPE_THROWN;
-
- else return WPNTYPE_NONE;
-}
-
static std::string normalized(const std::string &name)
{
std::string normalized = name;
@@ -115,8 +100,8 @@ void ItemDB::load()
mUnknown = new ItemInfo;
mUnknown->setName(_("Unknown item"));
- mUnknown->setImageName("");
- std::string errFile = paths.getValue("spriteErrorFile", "error.xml");
+ mUnknown->setDisplay(SpriteDisplay());
+ std::string errFile = paths.getStringValue("spriteErrorFile");
mUnknown->setSprite(errFile, GENDER_MALE);
mUnknown->setSprite(errFile, GENDER_FEMALE);
@@ -152,19 +137,21 @@ void ItemDB::load()
std::string name = XML::getProperty(node, "name", "");
std::string image = XML::getProperty(node, "image", "");
std::string description = XML::getProperty(node, "description", "");
- int weaponType = weaponTypeFromString(XML::getProperty(node, "weapon-type", ""));
+ std::string attackAction = XML::getProperty(node, "attack-action", "");
int attackRange = XML::getProperty(node, "attack-range", 0);
std::string missileParticle = XML::getProperty(node, "missile-particle", "");
+ SpriteDisplay display;
+ display.image = image;
+
ItemInfo *itemInfo = new ItemInfo;
itemInfo->setId(id);
- itemInfo->setImageName(image);
itemInfo->setName(name.empty() ? _("unnamed") : name);
itemInfo->setDescription(description);
itemInfo->setType(itemTypeFromString(typeStr));
itemInfo->setView(view);
itemInfo->setWeight(weight);
- itemInfo->setWeaponType(weaponType);
+ itemInfo->setAttackAction(attackAction);
itemInfo->setAttackRange(attackRange);
itemInfo->setMissileParticle(missileParticle);
@@ -204,8 +191,14 @@ void ItemDB::load()
{
loadSoundRef(itemInfo, itemChild);
}
+ else if (xmlStrEqual(itemChild->name, BAD_CAST "floor"))
+ {
+ loadFloorSprite(&display, itemChild);
+ }
}
+ itemInfo->setDisplay(display);
+
mItemInfos[id] = itemInfo;
if (!name.empty())
{
@@ -222,7 +215,7 @@ void ItemDB::load()
}
}
- if (weaponType > 0)
+ if (!attackAction.empty())
if (attackRange == 0)
logger->log("ItemDB: Missing attack range from weapon %i!", id);
@@ -336,3 +329,22 @@ void loadSoundRef(ItemInfo *itemInfo, xmlNodePtr node)
event.c_str());
}
}
+
+void loadFloorSprite(SpriteDisplay *display, xmlNodePtr floorNode)
+{
+ for_each_xml_child_node(spriteNode, floorNode)
+ {
+ if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
+ {
+ SpriteReference *currentSprite = new SpriteReference;
+ currentSprite->sprite = (const char*)spriteNode->xmlChildrenNode->content;
+ currentSprite->variant = XML::getProperty(spriteNode, "variant", 0);
+ display->sprites.push_back(currentSprite);
+ }
+ else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
+ {
+ std::string particlefx = (const char*)spriteNode->xmlChildrenNode->content;
+ display->particles.push_back(particlefx);
+ }
+ }
+}
diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp
index 4b1d82ea..1cd3c546 100644
--- a/src/resources/iteminfo.cpp
+++ b/src/resources/iteminfo.cpp
@@ -41,35 +41,17 @@ const std::string &ItemInfo::getSprite(Gender gender) const
}
}
-void ItemInfo::setWeaponType(int type)
+void ItemInfo::setAttackAction(std::string attackAction)
{
- // See server item.hpp file for type values.
- switch (type)
- {
- case WPNTYPE_NONE:
- mAttackType = ACTION_DEFAULT;
- break;
- case WPNTYPE_KNIFE:
- case WPNTYPE_SWORD:
- mAttackType = ACTION_ATTACK_STAB;
- break;
- case WPNTYPE_THROWN:
- mAttackType = ACTION_ATTACK_THROW;
- break;
- case WPNTYPE_BOW:
- mAttackType = ACTION_ATTACK_BOW;
- break;
- case WPNTYPE_POLEARM:
- mAttackType = ACTION_ATTACK_SWING;
- break;
- default:
- mAttackType = ACTION_ATTACK;
- }
+ if (attackAction.empty())
+ mAttackAction = SpriteAction::ATTACK; // (Equal to unarmed animation)
+ else
+ mAttackAction = attackAction;
}
void ItemInfo::addSound(EquipmentSoundEvent event, const std::string &filename)
{
- mSounds[event].push_back(paths.getValue("sfx", "sfx/") + filename);
+ mSounds[event].push_back(paths.getStringValue("sfx") + filename);
}
const std::string &ItemInfo::getSound(EquipmentSoundEvent event) const
diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h
index a7c0ddca..ac747e33 100644
--- a/src/resources/iteminfo.h
+++ b/src/resources/iteminfo.h
@@ -22,7 +22,7 @@
#ifndef ITEMINFO_H
#define ITEMINFO_H
-#include "player.h"
+#include "being.h"
#include "resources/spritedef.h"
@@ -90,24 +90,6 @@ enum ItemType
};
/**
- * Enumeration of available weapon's types.
- */
-enum WeaponType
-{
- WPNTYPE_NONE = 0,
- WPNTYPE_KNIFE,
- WPNTYPE_SWORD,
- WPNTYPE_POLEARM,
- WPNTYPE_STAFF,
- WPNTYPE_WHIP,
- WPNTYPE_BOW,
- WPNTYPE_SHOOTING,
- WPNTYPE_MACE,
- WPNTYPE_AXE,
- WPNTYPE_THROWN
-};
-
-/**
* Defines a class for storing item infos. This includes information used when
* the item is equipped.
*/
@@ -122,7 +104,7 @@ class ItemInfo
mWeight(0),
mView(0),
mId(0),
- mAttackType(ACTION_DEFAULT)
+ mAttackAction(SpriteAction::INVALID)
{
}
@@ -143,11 +125,11 @@ class ItemInfo
std::string getParticleEffect() const { return mParticle; }
- void setImageName(const std::string &imageName)
- { mImageName = imageName; }
+ void setDisplay(SpriteDisplay display)
+ { mDisplay = display; }
- const std::string &getImageName() const
- { return mImageName; }
+ const SpriteDisplay &getDisplay() const
+ { return mDisplay; }
void setDescription(const std::string &description)
{ mDescription = description; }
@@ -180,15 +162,15 @@ class ItemInfo
const std::string &getSprite(Gender gender) const;
- void setWeaponType(int);
+ void setAttackAction(std::string attackAction);
// Handlers for seting and getting the string used for particles when attacking
void setMissileParticle(std::string s) { mMissileParticle = s; }
std::string getMissileParticle() const { return mMissileParticle; }
- SpriteAction getAttackType() const
- { return mAttackType; }
+ std::string getAttackAction() const
+ { return mAttackAction; }
int getAttackRange() const
{ return mAttackRange; }
@@ -201,7 +183,7 @@ class ItemInfo
const std::string &getSound(EquipmentSoundEvent event) const;
protected:
- std::string mImageName; /**< The filename of the icon image. */
+ SpriteDisplay mDisplay; /**< Display info (like icon) */
std::string mName;
std::string mDescription; /**< Short description. */
std::string mEffect; /**< Description of effects. */
@@ -211,9 +193,13 @@ class ItemInfo
int mView; /**< Item ID of how this item looks. */
int mId; /**< Item ID */
- // Equipment related members
- SpriteAction mAttackType; /**< Attack type, in case of weapon. */
- int mAttackRange; /**< Attack range, will be zero if non weapon. */
+ // Equipment related members.
+ /** Attack type, in case of weapon.
+ * See SpriteAction in spritedef.h for more info.
+ * Attack action sub-types (bow, sword, ...) are defined in items.xml.
+ */
+ std::string mAttackAction;
+ int mAttackRange; /**< Attack range, will be zero if non weapon. */
// Particle to be shown when weapon attacks
std::string mMissileParticle;
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index b7c4fd72..b30bec0a 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -185,11 +185,9 @@ Map *MapReader::readMap(xmlNodePtr node, const std::string &path)
if (config.getValue("showWarps", 1))
{
map->addParticleEffect(
- paths.getValue("particles",
- "graphics/particles/")
- + paths.getValue("portalEffectFile",
- "warparea.particle.xml"),
- objX, objY, objW, objH);
+ paths.getStringValue("particles")
+ + paths.getStringValue("portalEffectFile"),
+ objX, objY, objW, objH);
}
}
else
diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp
index b08d87f2..6bc64a89 100644
--- a/src/resources/monsterdb.cpp
+++ b/src/resources/monsterdb.cpp
@@ -23,21 +23,21 @@
#include "log.h"
-#include "resources/monsterinfo.h"
+#include "net/net.h"
+
+#include "resources/beinginfo.h"
#include "utils/dtor.h"
#include "utils/gettext.h"
#include "utils/xml.h"
-#include "net/net.h"
#include "configuration.h"
#define OLD_TMWATHENA_OFFSET 1002
namespace
{
- MonsterDB::MonsterInfos mMonsterInfos;
- MonsterInfo mUnknown;
+ BeingInfos mMonsterInfos;
bool mLoaded = false;
}
@@ -46,8 +46,6 @@ void MonsterDB::load()
if (mLoaded)
unload();
- mUnknown.addSprite(paths.getValue("spriteErrorFile", "error.xml"));
-
logger->log("Initializing monster database...");
XML::Document doc("monsters.xml");
@@ -69,39 +67,29 @@ void MonsterDB::load()
continue;
}
- MonsterInfo *currentInfo = new MonsterInfo;
+ BeingInfo *currentInfo = new BeingInfo;
+
+ currentInfo->setWalkMask(Map::BLOCKMASK_WALL
+ | Map::BLOCKMASK_CHARACTER
+ | Map::BLOCKMASK_MONSTER);
+ currentInfo->setBlockType(Map::BLOCKTYPE_MONSTER);
currentInfo->setName(XML::getProperty(monsterNode, "name", _("unnamed")));
- std::string targetCursor;
- targetCursor = XML::getProperty(monsterNode, "targetCursor", "medium");
- if (targetCursor == "small")
- {
- currentInfo->setTargetCursorSize(Being::TC_SMALL);
- }
- else if (targetCursor == "medium")
- {
- currentInfo->setTargetCursorSize(Being::TC_MEDIUM);
- }
- else if (targetCursor == "large")
- {
- currentInfo->setTargetCursorSize(Being::TC_LARGE);
- }
- else
- {
- 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);
- }
+ currentInfo->setTargetCursorSize(XML::getProperty(monsterNode,
+ "targetCursor", "medium"));
+
+ SpriteDisplay display;
//iterate <sprite>s and <sound>s
for_each_xml_child_node(spriteNode, monsterNode)
{
if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
{
- currentInfo->addSprite(
- (const char*) spriteNode->xmlChildrenNode->content);
+ SpriteReference *currentSprite = new SpriteReference;
+ currentSprite->sprite = (const char*)spriteNode->xmlChildrenNode->content;
+ currentSprite->variant = XML::getProperty(spriteNode, "variant", 0);
+ display.sprites.push_back(currentSprite);
}
else if (xmlStrEqual(spriteNode->name, BAD_CAST "sound"))
{
@@ -111,19 +99,19 @@ void MonsterDB::load()
if (event == "hit")
{
- currentInfo->addSound(MONSTER_EVENT_HIT, filename);
+ currentInfo->addSound(SOUND_EVENT_HIT, filename);
}
else if (event == "miss")
{
- currentInfo->addSound(MONSTER_EVENT_MISS, filename);
+ currentInfo->addSound(SOUND_EVENT_MISS, filename);
}
else if (event == "hurt")
{
- currentInfo->addSound(MONSTER_EVENT_HURT, filename);
+ currentInfo->addSound(SOUND_EVENT_HURT, filename);
}
else if (event == "die")
{
- currentInfo->addSound(MONSTER_EVENT_DIE, filename);
+ currentInfo->addSound(SOUND_EVENT_DIE, filename);
}
else
{
@@ -138,18 +126,22 @@ void MonsterDB::load()
const int id = XML::getProperty(spriteNode, "id", 0);
const std::string particleEffect = XML::getProperty(
spriteNode, "particle-effect", "");
- SpriteAction spriteAction = SpriteDef::makeSpriteAction(
- XML::getProperty(spriteNode, "action", "attack"));
+ const std::string spriteAction = XML::getProperty(spriteNode,
+ "action",
+ "attack");
const std::string missileParticle = XML::getProperty(
spriteNode, "missile-particle", "");
- currentInfo->addMonsterAttack(id, particleEffect, spriteAction, missileParticle);
+ currentInfo->addAttack(id, spriteAction,
+ particleEffect, missileParticle);
}
else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
{
- currentInfo->addParticleEffect(
+ display.particles.push_back(
(const char*) spriteNode->xmlChildrenNode->content);
}
}
+ currentInfo->setDisplay(display);
+
mMonsterInfos[XML::getProperty(monsterNode, "id", 0) + offset] = currentInfo;
}
@@ -165,17 +157,17 @@ void MonsterDB::unload()
}
-const MonsterInfo &MonsterDB::get(int id)
+BeingInfo *MonsterDB::get(int id)
{
- MonsterInfoIterator i = mMonsterInfos.find(id);
+ BeingInfoIterator i = mMonsterInfos.find(id);
if (i == mMonsterInfos.end())
{
logger->log("MonsterDB: Warning, unknown monster ID %d requested", id);
- return mUnknown;
+ return BeingInfo::Unknown;
}
else
{
- return *(i->second);
+ return i->second;
}
}
diff --git a/src/resources/monsterdb.h b/src/resources/monsterdb.h
index 0fc8d2cf..50f70438 100644
--- a/src/resources/monsterdb.h
+++ b/src/resources/monsterdb.h
@@ -22,9 +22,7 @@
#ifndef MONSTER_DB_H
#define MONSTER_DB_H
-#include <map>
-
-class MonsterInfo;
+class BeingInfo;
/**
* Monster information database.
@@ -35,10 +33,7 @@ namespace MonsterDB
void unload();
- const MonsterInfo &get(int id);
-
- typedef std::map<int, MonsterInfo*> MonsterInfos;
- typedef MonsterInfos::iterator MonsterInfoIterator;
+ BeingInfo *get(int id);
}
#endif
diff --git a/src/resources/monsterinfo.cpp b/src/resources/monsterinfo.cpp
deleted file mode 100644
index 12cdbe3e..00000000
--- a/src/resources/monsterinfo.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "resources/monsterinfo.h"
-
-#include "utils/dtor.h"
-#include "utils/gettext.h"
-#include "configuration.h"
-
-MonsterInfo::MonsterInfo():
- mName(_("unnamed")),
- mTargetCursorSize(Being::TC_MEDIUM)
-{
-}
-
-MonsterInfo::~MonsterInfo()
-{
- // kill vectors in mSoundEffects
- delete_all(mSounds);
- delete_all(mMonsterAttacks);
- mSounds.clear();
-}
-
-void MonsterInfo::addSound(MonsterSoundEvent event, const std::string &filename)
-{
- if (mSounds.find(event) == mSounds.end())
- {
- mSounds[event] = new std::vector<std::string>;
- }
-
- mSounds[event]->push_back(paths.getValue("sfx", "sfx/")
- + filename);
-}
-
-const std::string &MonsterInfo::getSound(MonsterSoundEvent event) const
-{
- static std::string empty("");
- std::map<MonsterSoundEvent, std::vector<std::string>* >::const_iterator i =
- mSounds.find(event);
- return (i == mSounds.end()) ? empty :
- i->second->at(rand() % i->second->size());
-}
-
-const std::string &MonsterInfo::getAttackParticleEffect(int attackType) const
-{
- static std::string empty("");
- std::map<int, MonsterAttack*>::const_iterator i =
- mMonsterAttacks.find(attackType);
- return (i == mMonsterAttacks.end()) ? empty : (*i).second->particleEffect;
-}
-
-const std::string &MonsterInfo::getAttackMissileParticle(int attackType) const
-{
- static std::string empty("");
- std::map<int, MonsterAttack*>::const_iterator i =
- mMonsterAttacks.find(attackType);
- return (i == mMonsterAttacks.end()) ? empty : (*i).second->missileParticle;
-}
-
-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,
- const std::string &missileParticle)
-{
- MonsterAttack *a = new MonsterAttack;
- a->particleEffect = particleEffect;
- a->missileParticle = missileParticle;
- a->action = action;
- mMonsterAttacks[id] = a;
-}
-
-void MonsterInfo::addParticleEffect(const std::string &filename)
-{
- mParticleEffects.push_back(filename);
-}
diff --git a/src/resources/monsterinfo.h b/src/resources/monsterinfo.h
deleted file mode 100644
index f074254a..00000000
--- a/src/resources/monsterinfo.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef MONSTERINFO_H
-#define MONSTERINFO_H
-
-#include "being.h"
-
-#include <list>
-#include <map>
-#include <string>
-#include <vector>
-
-enum MonsterSoundEvent
-{
- MONSTER_EVENT_HIT,
- MONSTER_EVENT_MISS,
- MONSTER_EVENT_HURT,
- MONSTER_EVENT_DIE
-};
-
-struct MonsterAttack
-{
- std::string missileParticle;
- std::string particleEffect;
- SpriteAction action;
-};
-
-/**
- * Holds information about a certain type of monster. This includes the name
- * of the monster, the sprite to display and the sounds the monster makes.
- *
- * @see MonsterDB
- */
-class MonsterInfo
-{
- public:
- MonsterInfo();
-
- ~MonsterInfo();
-
- void setName(const std::string &name) { mName = name; }
-
- void addSprite(const std::string &filename)
- { mSprites.push_back(filename); }
-
- void setTargetCursorSize(Being::TargetCursorSize targetCursorSize)
- { mTargetCursorSize = targetCursorSize; }
-
- void addSound(MonsterSoundEvent event, const std::string &filename);
-
- void addParticleEffect(const std::string &filename);
-
- const std::string &getName() const
- { return mName; }
-
- const std::list<std::string>& getSprites() const
- { return mSprites; }
-
- Being::TargetCursorSize getTargetCursorSize() const
- { return mTargetCursorSize; }
-
- const std::string &getSound(MonsterSoundEvent event) const;
-
- void addMonsterAttack(int id,
- const std::string &particleEffect,
- SpriteAction action,
- const std::string &missileParticle);
-
- const std::string &getAttackParticleEffect(int attackType) const;
-
- const std::string &getAttackMissileParticle(int attackType) const;
-
- SpriteAction getAttackAction(int attackType) const;
-
- const std::list<std::string>& getParticleEffects() const
- { return mParticleEffects; }
-
- private:
- std::string mName;
- std::list<std::string> mSprites;
- Being::TargetCursorSize mTargetCursorSize;
- std::map<MonsterSoundEvent, std::vector<std::string>* > mSounds;
- std::map<int, MonsterAttack*> mMonsterAttacks;
- std::list<std::string> mParticleEffects;
-};
-
-#endif // MONSTERINFO_H
diff --git a/src/resources/npcdb.cpp b/src/resources/npcdb.cpp
index 21a2e9a1..ec22c225 100644
--- a/src/resources/npcdb.cpp
+++ b/src/resources/npcdb.cpp
@@ -23,13 +23,15 @@
#include "log.h"
+#include "resources/beinginfo.h"
+
+#include "utils/dtor.h"
#include "utils/xml.h"
#include "configuration.h"
namespace
{
- NPCInfos mNPCInfos;
- NPCInfo mUnknown;
+ BeingInfos mNPCInfos;
bool mLoaded = false;
}
@@ -38,12 +40,6 @@ void NPCDB::load()
if (mLoaded)
unload();
- NPCsprite *unknownSprite = new NPCsprite;
- unknownSprite->sprite = paths.getValue("spriteErrorFile",
- "error.xml");
- unknownSprite->variant = 0;
- mUnknown.sprites.push_back(unknownSprite);
-
logger->log("Initializing NPC database...");
XML::Document doc("npcs.xml");
@@ -67,23 +63,30 @@ void NPCDB::load()
continue;
}
- NPCInfo *currentInfo = new NPCInfo;
+ BeingInfo *currentInfo = new BeingInfo;
+ currentInfo->setTargetCursorSize(XML::getProperty(npcNode,
+ "targetCursor", "medium"));
+
+ SpriteDisplay display;
for_each_xml_child_node(spriteNode, npcNode)
{
if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
{
- NPCsprite *currentSprite = new NPCsprite;
+ SpriteReference *currentSprite = new SpriteReference;
currentSprite->sprite = (const char*)spriteNode->xmlChildrenNode->content;
currentSprite->variant = XML::getProperty(spriteNode, "variant", 0);
- currentInfo->sprites.push_back(currentSprite);
+ display.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);
+ display.particles.push_back(particlefx);
}
}
+
+ currentInfo->setDisplay(display);
+
mNPCInfos[id] = currentInfo;
}
@@ -92,40 +95,23 @@ void NPCDB::load()
void NPCDB::unload()
{
- for ( NPCInfosIterator i = mNPCInfos.begin();
- i != mNPCInfos.end();
- i++)
- {
- while (!i->second->sprites.empty())
- {
- delete i->second->sprites.front();
- i->second->sprites.pop_front();
- }
- delete i->second;
- }
-
+ delete_all(mNPCInfos);
mNPCInfos.clear();
- while (!mUnknown.sprites.empty())
- {
- delete mUnknown.sprites.front();
- mUnknown.sprites.pop_front();
- }
-
mLoaded = false;
}
-const NPCInfo& NPCDB::get(int id)
+BeingInfo *NPCDB::get(int id)
{
- NPCInfosIterator i = mNPCInfos.find(id);
+ BeingInfoIterator i = mNPCInfos.find(id);
if (i == mNPCInfos.end())
{
logger->log("NPCDB: Warning, unknown NPC ID %d requested", id);
- return mUnknown;
+ return BeingInfo::Unknown;
}
else
{
- return *(i->second);
+ return i->second;
}
}
diff --git a/src/resources/npcdb.h b/src/resources/npcdb.h
index 9da873e4..b0c89c80 100644
--- a/src/resources/npcdb.h
+++ b/src/resources/npcdb.h
@@ -22,23 +22,7 @@
#ifndef NPC_DB_H
#define NPC_DB_H
-#include <list>
-#include <map>
-#include <string>
-
-struct NPCsprite
-{
- std::string sprite;
- int variant;
-};
-
-struct NPCInfo
-{
- std::list<NPCsprite*> sprites;
- std::list<std::string> particles;
-};
-
-typedef std::map<int, NPCInfo*> NPCInfos;
+class BeingInfo;
/**
* NPC information database.
@@ -49,9 +33,7 @@ namespace NPCDB
void unload();
- const NPCInfo& get(int id);
-
- typedef NPCInfos::iterator NPCInfosIterator;
+ BeingInfo *get(int id);
}
#endif
diff --git a/src/resources/specialdb.cpp b/src/resources/specialdb.cpp
new file mode 100644
index 00000000..ac591c4f
--- /dev/null
+++ b/src/resources/specialdb.cpp
@@ -0,0 +1,132 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "resources/specialdb.h"
+
+#include "log.h"
+
+#include "utils/dtor.h"
+#include "utils/xml.h"
+
+
+namespace
+{
+ SpecialInfos mSpecialInfos;
+ bool mLoaded = false;
+}
+
+SpecialInfo::TargetMode SpecialDB::targetModeFromString(const std::string& str)
+{
+ if (str=="self") return SpecialInfo::TARGET_SELF;
+ else if (str=="friend") return SpecialInfo::TARGET_FRIEND;
+ else if (str=="enemy") return SpecialInfo::TARGET_ENEMY;
+ else if (str=="being") return SpecialInfo::TARGET_BEING;
+ else if (str=="point") return SpecialInfo::TARGET_POINT;
+
+ logger->log("SpecialDB: Warning, unknown target mode \"%s\"", str.c_str() );
+ return SpecialInfo::TARGET_SELF;
+}
+
+void SpecialDB::load()
+{
+ if (mLoaded)
+ unload();
+
+ logger->log("Initializing special database...");
+
+ XML::Document doc("specials.xml");
+ xmlNodePtr root = doc.rootNode();
+
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "specials"))
+ {
+ logger->log("Error loading specials file specials.xml");
+ return;
+ }
+
+ std::string setName;
+
+ for_each_xml_child_node(set, root)
+ {
+ if (xmlStrEqual(set->name, BAD_CAST "set"))
+ {
+ setName = XML::getProperty(set, "name", "Actions");
+
+
+ for_each_xml_child_node(special, set)
+ {
+ if (xmlStrEqual(special->name, BAD_CAST "special"))
+ {
+ SpecialInfo *info = new SpecialInfo();
+ int id = XML::getProperty(special, "id", 0);
+ info->id = id;
+ info->set = setName;
+ info->name = XML::getProperty(special, "name", "");
+ info->icon = XML::getProperty(special, "icon", "");
+
+ info->isActive = XML::getBoolProperty(special, "active", false);
+ info->targetMode = targetModeFromString(XML::getProperty(special, "target", "self"));
+
+ info->level = XML::getProperty(special, "level", -1);
+ info->hasLevel = info->level > -1;
+
+ info->hasRechargeBar = XML::getBoolProperty(special, "recharge", false);
+ info->rechargeNeeded = 0;
+ info->rechargeCurrent = 0;
+
+ if (mSpecialInfos.find(id) != mSpecialInfos.end())
+ {
+ logger->log("SpecialDB: Duplicate special ID %d (ignoring)", id);
+ } else {
+ mSpecialInfos[id] = info;
+ }
+ }
+ }
+ }
+ }
+
+ mLoaded = true;
+}
+
+void SpecialDB::unload()
+{
+
+ delete_all(mSpecialInfos);
+ mSpecialInfos.clear();
+
+ mLoaded = false;
+}
+
+
+SpecialInfo *SpecialDB::get(int id)
+{
+
+ SpecialInfos::iterator i = mSpecialInfos.find(id);
+
+ if (i == mSpecialInfos.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return i->second;
+ }
+ return NULL;
+}
+
diff --git a/src/resources/specialdb.h b/src/resources/specialdb.h
new file mode 100644
index 00000000..38612c2a
--- /dev/null
+++ b/src/resources/specialdb.h
@@ -0,0 +1,72 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SPECIAL_DB_H
+#define SPECIAL_DB_H
+
+#include <string>
+#include <map>
+
+struct SpecialInfo
+{
+ enum TargetMode
+ {
+ TARGET_SELF, // no target selection
+ TARGET_FRIEND, // target friendly being
+ TARGET_ENEMY, // target hostile being
+ TARGET_BEING, // target any being
+ TARGET_POINT // target map location
+ };
+ int id;
+ std::string set; // tab on which the special is shown
+ std::string name; // displayed name of special
+ std::string icon; // filename of graphical icon
+
+ bool isActive; // true when the special can be used
+ TargetMode targetMode; // target mode
+
+ bool hasLevel; // true when the special has levels
+ int level; // level of special when applicable
+
+ bool hasRechargeBar; // true when the special has a recharge bar
+ int rechargeNeeded; // maximum recharge when applicable
+ int rechargeCurrent; // current recharge when applicable
+};
+
+/**
+ * Special information database.
+ */
+namespace SpecialDB
+{
+ void load();
+
+ void unload();
+
+ /** gets the special info for ID. Will return 0 when it is
+ * a server-specific special.
+ */
+ SpecialInfo *get(int id);
+
+ SpecialInfo::TargetMode targetModeFromString(const std::string& str);
+}
+
+typedef std::map<int, SpecialInfo *> SpecialInfos;
+
+#endif
diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp
index c524c43c..311c9d1a 100644
--- a/src/resources/spritedef.cpp
+++ b/src/resources/spritedef.cpp
@@ -36,13 +36,16 @@
#include <set>
-Action *SpriteDef::getAction(SpriteAction action) const
+SpriteReference *SpriteReference::Empty = new SpriteReference(
+ paths.getStringValue("spriteErrorFile"), 0);
+
+Action *SpriteDef::getAction(const std::string &action) const
{
Actions::const_iterator i = mActions.find(action);
if (i == mActions.end())
{
- logger->log("Warning: no action \"%u\" defined!", action);
+ logger->log("Warning: no action \"%s\" defined!", action.c_str());
return NULL;
}
@@ -63,9 +66,8 @@ SpriteDef *SpriteDef::load(const std::string &animationFile, int variant)
{
logger->log("Error, failed to parse %s", animationFile.c_str());
- std::string errorFile = paths.getValue("sprites", "graphics/sprites")
- + paths.getValue("spriteErrorFile",
- "error.xml");
+ std::string errorFile = paths.getStringValue("sprites")
+ + paths.getStringValue("spriteErrorFile");
if (animationFile != errorFile)
{
return load(errorFile, 0);
@@ -82,22 +84,29 @@ SpriteDef *SpriteDef::load(const std::string &animationFile, int variant)
return def;
}
+void SpriteDef::substituteAction(std::string complete, std::string with)
+{
+ if (mActions.find(complete) == mActions.end())
+ {
+ Actions::iterator i = mActions.find(with);
+ if (i != mActions.end())
+ {
+ mActions[complete] = i->second;
+ }
+ }
+}
+
void SpriteDef::substituteActions()
{
- substituteAction(ACTION_STAND, ACTION_DEFAULT);
- substituteAction(ACTION_WALK, ACTION_STAND);
- substituteAction(ACTION_WALK, ACTION_RUN);
- substituteAction(ACTION_ATTACK, ACTION_STAND);
- substituteAction(ACTION_ATTACK_SWING, ACTION_ATTACK);
- substituteAction(ACTION_ATTACK_STAB, ACTION_ATTACK_SWING);
- substituteAction(ACTION_ATTACK_BOW, ACTION_ATTACK_STAB);
- substituteAction(ACTION_ATTACK_THROW, ACTION_ATTACK_SWING);
- substituteAction(ACTION_CAST_MAGIC, ACTION_ATTACK_SWING);
- substituteAction(ACTION_USE_ITEM, ACTION_CAST_MAGIC);
- substituteAction(ACTION_SIT, ACTION_STAND);
- substituteAction(ACTION_SLEEP, ACTION_SIT);
- substituteAction(ACTION_HURT, ACTION_STAND);
- substituteAction(ACTION_DEAD, ACTION_HURT);
+ substituteAction(SpriteAction::STAND, SpriteAction::DEFAULT);
+ substituteAction(SpriteAction::MOVE, SpriteAction::STAND);
+ substituteAction(SpriteAction::ATTACK, SpriteAction::STAND);
+ substituteAction(SpriteAction::CAST_MAGIC, SpriteAction::ATTACK);
+ substituteAction(SpriteAction::USE_ITEM, SpriteAction::CAST_MAGIC);
+ substituteAction(SpriteAction::SIT, SpriteAction::STAND);
+ substituteAction(SpriteAction::SLEEP, SpriteAction::SIT);
+ substituteAction(SpriteAction::HURT, SpriteAction::STAND);
+ substituteAction(SpriteAction::DEAD, SpriteAction::HURT);
}
void SpriteDef::loadSprite(xmlNodePtr spriteNode, int variant,
@@ -169,20 +178,19 @@ void SpriteDef::loadAction(xmlNodePtr node, int variant_offset)
}
ImageSet *imageSet = si->second;
- SpriteAction actionType = makeSpriteAction(actionName);
- if (actionType == ACTION_INVALID)
+ if (actionName == SpriteAction::INVALID)
{
logger->log("Warning: Unknown action \"%s\" defined in %s",
actionName.c_str(), getIdPath().c_str());
return;
}
Action *action = new Action;
- mActions[actionType] = action;
+ mActions[actionName] = action;
// When first action set it as default direction
- if (mActions.empty())
+ if (mActions.size() == 1)
{
- mActions[ACTION_DEFAULT] = action;
+ mActions[SpriteAction::DEFAULT] = action;
}
// Load animations
@@ -283,8 +291,7 @@ void SpriteDef::includeSprite(xmlNodePtr includeNode)
if (filename.empty())
return;
- XML::Document doc(paths.getValue("sprites", "graphics/sprites/")
- + filename);
+ XML::Document doc(paths.getStringValue("sprites") + filename);
xmlNodePtr rootNode = doc.rootNode();
if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "sprite"))
@@ -296,18 +303,6 @@ void SpriteDef::includeSprite(xmlNodePtr includeNode)
loadSprite(rootNode, 0);
}
-void SpriteDef::substituteAction(SpriteAction complete, SpriteAction with)
-{
- if (mActions.find(complete) == mActions.end())
- {
- Actions::iterator i = mActions.find(with);
- if (i != mActions.end())
- {
- mActions[complete] = i->second;
- }
- }
-}
-
SpriteDef::~SpriteDef()
{
// Actions are shared, so ensure they are deleted only once.
@@ -331,63 +326,6 @@ SpriteDef::~SpriteDef()
}
}
-SpriteAction SpriteDef::makeSpriteAction(const std::string &action)
-{
- if (action.empty() || action == "default")
- return ACTION_DEFAULT;
-
- if (action == "stand")
- return ACTION_STAND;
- else if (action == "walk")
- return ACTION_WALK;
- else if (action == "run")
- return ACTION_RUN;
- else if (action == "attack")
- return ACTION_ATTACK;
- else if (action == "attack_swing")
- return ACTION_ATTACK_SWING;
- else if (action == "attack_stab")
- return ACTION_ATTACK_STAB;
- else if (action == "attack_bow")
- return ACTION_ATTACK_BOW;
- else if (action == "attack_throw")
- return ACTION_ATTACK_THROW;
- else if (action == "special0")
- return ACTION_SPECIAL_0;
- else if (action == "special1")
- return ACTION_SPECIAL_1;
- else if (action == "special2")
- return ACTION_SPECIAL_2;
- else if (action == "special3")
- return ACTION_SPECIAL_3;
- else if (action == "special4")
- return ACTION_SPECIAL_4;
- else if (action == "special5")
- return ACTION_SPECIAL_5;
- else if (action == "special6")
- return ACTION_SPECIAL_6;
- else if (action == "special7")
- return ACTION_SPECIAL_7;
- else if (action == "special8")
- return ACTION_SPECIAL_8;
- else if (action == "special9")
- return ACTION_SPECIAL_9;
- else if (action == "cast_magic")
- return ACTION_CAST_MAGIC;
- else if (action == "use_item")
- return ACTION_USE_ITEM;
- else if (action == "sit")
- return ACTION_SIT;
- else if (action == "sleep")
- return ACTION_SLEEP;
- else if (action == "hurt")
- return ACTION_HURT;
- else if (action == "dead")
- return ACTION_DEAD;
- else
- return ACTION_INVALID;
-}
-
SpriteDirection SpriteDef::makeSpriteDirection(const std::string &direction)
{
if (direction.empty() || direction == "default")
diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h
index 5bb6078e..18a70c9b 100644
--- a/src/resources/spritedef.h
+++ b/src/resources/spritedef.h
@@ -26,42 +26,60 @@
#include <libxml/tree.h>
+#include <list>
#include <map>
#include <string>
class Action;
class ImageSet;
-enum SpriteAction
+struct SpriteReference
{
- ACTION_DEFAULT = 0,
- ACTION_STAND,
- ACTION_WALK,
- ACTION_RUN,
- ACTION_ATTACK,
- ACTION_ATTACK_SWING,
- ACTION_ATTACK_STAB,
- ACTION_ATTACK_BOW,
- ACTION_ATTACK_THROW,
- ACTION_SPECIAL_0,
- ACTION_SPECIAL_1,
- ACTION_SPECIAL_2,
- ACTION_SPECIAL_3,
- ACTION_SPECIAL_4,
- ACTION_SPECIAL_5,
- ACTION_SPECIAL_6,
- ACTION_SPECIAL_7,
- ACTION_SPECIAL_8,
- ACTION_SPECIAL_9,
- ACTION_CAST_MAGIC,
- ACTION_USE_ITEM,
- ACTION_SIT,
- ACTION_SLEEP,
- ACTION_HURT,
- ACTION_DEAD,
- ACTION_INVALID
+ static SpriteReference *Empty;
+
+ SpriteReference() {}
+
+ SpriteReference(std::string sprite, int variant)
+ { this->sprite = sprite; this->variant = variant; }
+
+ std::string sprite;
+ int variant;
};
+struct SpriteDisplay
+{
+ std::string image;
+ std::list<SpriteReference*> sprites;
+ std::list<std::string> particles;
+};
+
+typedef std::list<SpriteReference*>::const_iterator SpriteRefs;
+
+/*
+ * Remember those are the main action.
+ * Action subtypes, e.g.: "attack_bow" are to be passed by items.xml after
+ * an ACTION_ATTACK call.
+ * Which special to be use to to be passed with the USE_SPECIAL call.
+ * Running, walking, ... is a sub-type of moving.
+ * ...
+ * Please don't add hard-coded subtypes here!
+ */
+namespace SpriteAction
+{
+ static const std::string DEFAULT = "stand";
+ static const std::string STAND = "stand";
+ static const std::string SIT = "sit";
+ static const std::string SLEEP = "sleep";
+ static const std::string DEAD = "dead";
+ static const std::string MOVE = "walk";
+ static const std::string ATTACK = "attack";
+ static const std::string HURT = "hurt";
+ static const std::string USE_SPECIAL = "special";
+ static const std::string CAST_MAGIC = "magic";
+ static const std::string USE_ITEM = "item";
+ static const std::string INVALID = "";
+}
+
enum SpriteDirection
{
DIRECTION_DEFAULT = 0,
@@ -86,12 +104,7 @@ class SpriteDef : public Resource
/**
* Returns the specified action.
*/
- Action *getAction(SpriteAction action) const;
-
- /**
- * Converts a string into a SpriteAction enum.
- */
- static SpriteAction makeSpriteAction(const std::string &action);
+ Action *getAction(const std::string &action) const;
/**
* Converts a string into a SpriteDirection enum.
@@ -147,12 +160,12 @@ class SpriteDef : public Resource
* When there are no animations defined for the action "complete", its
* animations become a copy of those of the action "with".
*/
- void substituteAction(SpriteAction complete, SpriteAction with);
+ void substituteAction(std::string complete, std::string with);
typedef std::map<std::string, ImageSet*> ImageSets;
typedef ImageSets::iterator ImageSetIterator;
- typedef std::map<SpriteAction, Action*> Actions;
+ typedef std::map<std::string, Action*> Actions;
ImageSets mImageSets;
Actions mActions;
diff --git a/src/gui/theme.cpp b/src/resources/theme.cpp
index 12de1f91..6633f1e0 100644
--- a/src/gui/theme.cpp
+++ b/src/resources/theme.cpp
@@ -21,7 +21,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "gui/theme.h"
+#include "resources/theme.h"
#include "client.h"
#include "configuration.h"
@@ -48,7 +48,7 @@ Theme *Theme::mInstance = 0;
static void initDefaultThemePath()
{
ResourceManager *resman = ResourceManager::getInstance();
- defaultThemePath = branding.getValue("guiThemePath", "");
+ defaultThemePath = branding.getStringValue("guiThemePath");
if (!defaultThemePath.empty() && resman->isDirectory(defaultThemePath))
return;
@@ -81,8 +81,8 @@ Skin::~Skin()
void Skin::updateAlpha(float minimumOpacityAllowed)
{
- const float alpha = std::max((double)minimumOpacityAllowed,
- config.getValue("guialpha", 0.8f));
+ const float alpha = std::max(minimumOpacityAllowed,
+ config.getFloatValue("guialpha"));
for_each(mBorder.grid, mBorder.grid + 9,
std::bind2nd(std::mem_fun(&Image::setAlpha), alpha));
@@ -339,9 +339,9 @@ bool Theme::tryThemePath(std::string themePath)
void Theme::prepareThemePath()
{
// Try theme from settings
- if (!tryThemePath(config.getValue("theme", "")))
+ if (!tryThemePath(config.getStringValue("theme")))
// Try theme from branding
- if (!tryThemePath(branding.getValue("theme", "")))
+ if (!tryThemePath(branding.getStringValue("theme")))
// Use default
mThemePath = defaultThemePath;
diff --git a/src/gui/theme.h b/src/resources/theme.h
index 6798bed5..6798bed5 100644
--- a/src/gui/theme.h
+++ b/src/resources/theme.h
diff --git a/src/gui/userpalette.cpp b/src/resources/userpalette.cpp
index 0f30b752..5067c794 100644
--- a/src/gui/userpalette.cpp
+++ b/src/resources/userpalette.cpp
@@ -20,7 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "userpalette.h"
+#include "resources/userpalette.h"
#include "configuration.h"
#include "client.h"
diff --git a/src/gui/userpalette.h b/src/resources/userpalette.h
index 82bcea1c..82bcea1c 100644
--- a/src/gui/userpalette.h
+++ b/src/resources/userpalette.h
diff --git a/src/resources/wallpaper.cpp b/src/resources/wallpaper.cpp
index 22bbda9c..06675ab1 100644
--- a/src/resources/wallpaper.cpp
+++ b/src/resources/wallpaper.cpp
@@ -53,26 +53,20 @@ static void initDefaultWallpaperPaths()
ResourceManager *resman = ResourceManager::getInstance();
// Init the path
- wallpaperPath = branding.getValue("wallpapersPath", "");
+ wallpaperPath = branding.getStringValue("wallpapersPath");
if (!wallpaperPath.empty() && resman->isDirectory(wallpaperPath))
return;
else
- wallpaperPath = paths.getValue("wallpapers", "");
-
- if (wallpaperPath.empty() || !resman->isDirectory(wallpaperPath))
- wallpaperPath = "graphics/images/";
+ wallpaperPath = paths.getValue("wallpapers", "graphics/images/");
// Init the default file
- wallpaperFile = branding.getValue("wallpaperFile", "");
+ wallpaperFile = branding.getStringValue("wallpaperFile");
- if (!wallpaperFile.empty() && resman->isDirectory(wallpaperFile))
+ if (!wallpaperFile.empty())
return;
else
- wallpaperFile = paths.getValue("wallpaperFile", "");
-
- if (wallpaperFile.empty() || !resman->isDirectory(wallpaperFile))
- wallpaperFile = "login_wallpaper.png";
+ wallpaperFile = paths.getValue("wallpaperFile", "login_wallpaper.png");
}
bool wallpaperCompare(WallpaperData a, WallpaperData b)
@@ -82,7 +76,7 @@ bool wallpaperCompare(WallpaperData a, WallpaperData b)
return (aa > ab || (aa == ab && a.width > b.width));
}
-
+#include <iostream>
void Wallpaper::loadWallpapers()
{
wallpaperData.clear();
diff --git a/src/simpleanimation.cpp b/src/simpleanimation.cpp
index a8d33a43..7ef433ea 100644
--- a/src/simpleanimation.cpp
+++ b/src/simpleanimation.cpp
@@ -33,14 +33,16 @@ SimpleAnimation::SimpleAnimation(Animation *animation):
mAnimation(animation),
mAnimationTime(0),
mAnimationPhase(0),
- mCurrentFrame(mAnimation->getFrame(0))
+ mCurrentFrame(mAnimation->getFrame(0)),
+ mInitialized(true)
{
}
SimpleAnimation::SimpleAnimation(xmlNodePtr animationNode):
mAnimation(new Animation),
mAnimationTime(0),
- mAnimationPhase(0)
+ mAnimationPhase(0),
+ mInitialized(false)
{
initializeAnimation(animationNode);
mCurrentFrame = mAnimation->getFrame(0);
@@ -48,7 +50,8 @@ SimpleAnimation::SimpleAnimation(xmlNodePtr animationNode):
SimpleAnimation::~SimpleAnimation()
{
- delete mAnimation;
+ if (mAnimation)
+ delete mAnimation;
}
bool SimpleAnimation::draw(Graphics *graphics, int posX, int posY) const
@@ -79,38 +82,55 @@ void SimpleAnimation::setFrame(int frame)
void SimpleAnimation::update(int timePassed)
{
- mAnimationTime += timePassed;
-
- while (mAnimationTime > mCurrentFrame->delay && mCurrentFrame->delay > 0)
+ if (mInitialized)
{
- mAnimationTime -= mCurrentFrame->delay;
- mAnimationPhase++;
+ mAnimationTime += timePassed;
- if (mAnimationPhase >= mAnimation->getLength())
- mAnimationPhase = 0;
+ while (mAnimationTime > mCurrentFrame->delay && mCurrentFrame->delay > 0)
+ {
+ mAnimationTime -= mCurrentFrame->delay;
+ mAnimationPhase++;
- mCurrentFrame = mAnimation->getFrame(mAnimationPhase);
+ if (mAnimationPhase >= mAnimation->getLength())
+ mAnimationPhase = 0;
+
+ mCurrentFrame = mAnimation->getFrame(mAnimationPhase);
+ }
}
}
int SimpleAnimation::getLength() const
{
- return mAnimation->getLength();
+ if (mAnimation)
+ return mAnimation->getLength();
+ else
+ return 0;
}
Image *SimpleAnimation::getCurrentImage() const
{
- return mCurrentFrame->image;
+ if (mCurrentFrame)
+ return mCurrentFrame->image;
+ else
+ return NULL;
}
void SimpleAnimation::initializeAnimation(xmlNodePtr animationNode)
{
+ mInitialized = false;
+
+ if (!animationNode)
+ return;
+
ImageSet *imageset = ResourceManager::getInstance()->getImageSet(
XML::getProperty(animationNode, "imageset", ""),
XML::getProperty(animationNode, "width", 0),
XML::getProperty(animationNode, "height", 0)
);
+ if (!imageset)
+ return;
+
// Get animation frames
for ( xmlNodePtr frameNode = animationNode->xmlChildrenNode;
frameNode;
@@ -172,4 +192,6 @@ void SimpleAnimation::initializeAnimation(xmlNodePtr animationNode)
mAnimation->addTerminator();
}
}
+
+ mInitialized = true;
}
diff --git a/src/simpleanimation.h b/src/simpleanimation.h
index a8a43b33..e679442e 100644
--- a/src/simpleanimation.h
+++ b/src/simpleanimation.h
@@ -78,6 +78,9 @@ class SimpleAnimation
/** Current animation phase. */
Frame *mCurrentFrame;
+
+ /** Tell whether the animation is ready */
+ bool mInitialized;
};
#endif
diff --git a/src/sound.cpp b/src/sound.cpp
index 241e25e4..a859cb6e 100644
--- a/src/sound.cpp
+++ b/src/sound.cpp
@@ -142,7 +142,7 @@ void Sound::setSfxVolume(int volume)
static Mix_Music *loadMusic(const std::string &filename)
{
ResourceManager *resman = ResourceManager::getInstance();
- std::string path = resman->getPath("music/" + filename);
+ std::string path = resman->getPath(paths.getStringValue("music") + filename);
if (path.find(".zip/") != std::string::npos ||
path.find(".zip\\") != std::string::npos)
@@ -152,7 +152,7 @@ static Mix_Music *loadMusic(const std::string &filename)
logger->log("Loading music \"%s\" from temporary file tempMusic.ogg",
path.c_str());
bool success = resman->copyFile(
- paths.getValue("music", "music/")
+ paths.getStringValue("music")
+ filename, "tempMusic.ogg");
if (success)
path = resman->getPath("tempMusic.ogg");
@@ -240,7 +240,7 @@ void Sound::playSfx(const std::string &path)
ResourceManager *resman = ResourceManager::getInstance();
SoundEffect *sample = resman->getSoundEffect(
- paths.getValue("sfx", "sfx/") + path);
+ paths.getStringValue("sfx") + path);
if (sample)
{
logger->log("Sound::playSfx() Playing: %s", path.c_str());
diff --git a/src/sprite.h b/src/sprite.h
index 847c01a6..38db8b41 100644
--- a/src/sprite.h
+++ b/src/sprite.h
@@ -1,7 +1,6 @@
/*
* The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2010 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -22,64 +21,90 @@
#ifndef SPRITE_H
#define SPRITE_H
+#include "resources/spritedef.h"
+
class Graphics;
+class Image;
-/**
- * A sprite is some visible object on a map. This abstract class defines the
- * interface used by the map to sort and display the sprite.
- */
class Sprite
{
public:
+ virtual ~Sprite() {}
+
+ /**
+ * Resets the sprite.
+ *
+ * @returns true if the sprite changed, false otherwise
+ */
+ virtual bool reset() = 0;
+
/**
- * Destructor.
+ * Plays an action using the current direction.
+ *
+ * @returns true if the sprite changed, false otherwise
*/
- virtual
- ~Sprite() {}
+ virtual bool play(std::string action) = 0;
/**
- * Draws the sprite to the given graphics context.
+ * Inform the animation of the passed time so that it can output the
+ * correct animation frame.
*
- * Note: this function could be simplified if the graphics context
- * would support setting a translation offset. It already does this
- * partly with the clipping rectangle support.
+ * @returns true if the sprite changed, false otherwise
*/
- virtual void draw(Graphics *graphics, int offsetX, int offsetY) const = 0;
+ virtual bool update(int time) = 0;
/**
- * Returns the horizontal size of the sprites graphical representation
- * in pixels or 0 when it is undefined.
+ * Draw the current animation frame at the coordinates given in screen
+ * pixels.
*/
- virtual int getWidth() const
- { return 0; }
+ virtual bool draw(Graphics* graphics, int posX, int posY) const = 0;
/**
- * Returns the vertical size of the sprites graphical representation
- * in pixels or 0 when it is undefined.
+ * Gets the width in pixels of the image of the current frame
*/
- virtual int getHeight() const
- { return 0; }
+ virtual int getWidth() const = 0;
/**
- * Returns the pixel Y coordinate of the sprite.
+ * Gets the height in pixels of the image of the current frame
*/
- virtual int getPixelY() const = 0;
+ virtual int getHeight() const = 0;
/**
- * Returns the number of Image layers used to draw the sprite.
+ * Returns a reference to the current image being drawn.
*/
- virtual int getNumberOfLayers() const
- { return 0; }
+ virtual const Image* getImage() const = 0;
/**
- * Returns the current alpha value used to draw the sprite.
+ * Sets the direction.
+ *
+ * @returns true if the sprite changed, false otherwise
*/
- virtual float getAlpha() const = 0;
+ virtual bool setDirection(SpriteDirection direction) = 0;
/**
- * Sets the alpha value used to draw the sprite.
+ * Sets the alpha value of the animated sprite
*/
- virtual void setAlpha(float alpha) = 0;
+ virtual void setAlpha(float alpha)
+ { mAlpha = alpha; }
+
+ /**
+ * Returns the current alpha opacity of the animated sprite.
+ */
+ virtual float getAlpha() const
+ { return mAlpha; }
+
+ /**
+ * Returns the current frame number for the sprite.
+ */
+ virtual size_t getCurrentFrame() const = 0;
+
+ /**
+ * Returns the frame count for the sprite.
+ */
+ virtual size_t getFrameCount() const = 0;
+
+ protected:
+ float mAlpha; /**< The alpha opacity used to draw */
};
-#endif
+#endif // SPRITE_H
diff --git a/src/statuseffect.cpp b/src/statuseffect.cpp
index 1f913f4a..d7c3f17a 100644
--- a/src/statuseffect.cpp
+++ b/src/statuseffect.cpp
@@ -21,11 +21,10 @@
#include "statuseffect.h"
+#include "event.h"
#include "log.h"
#include "sound.h"
-#include "gui/widgets/chattab.h"
-
#include "utils/xml.h"
#include "configuration.h"
@@ -52,7 +51,7 @@ void StatusEffect::playSFX()
void StatusEffect::deliverMessage()
{
if (!mMessage.empty())
- localChatTab->chatLog(mMessage, BY_SERVER);
+ SERVER_NOTICE(mMessage)
}
Particle *StatusEffect::getParticle()
@@ -70,22 +69,22 @@ AnimatedSprite *StatusEffect::getIcon()
else
{
AnimatedSprite *sprite = AnimatedSprite::load(
- paths.getValue("sprites", "graphics/sprites/") + mIcon);
+ paths.getStringValue("sprites") + mIcon);
if (false && sprite)
{
- sprite->play(ACTION_DEFAULT);
+ sprite->play(SpriteAction::DEFAULT);
sprite->reset();
}
return sprite;
}
}
-SpriteAction StatusEffect::getAction()
+std::string StatusEffect::getAction()
{
if (mAction.empty())
- return ACTION_INVALID;
+ return SpriteAction::INVALID;
else
- return SpriteDef::makeSpriteAction(mAction);
+ return mAction;
}
diff --git a/src/statuseffect.h b/src/statuseffect.h
index fc0e7336..3f715a16 100644
--- a/src/statuseffect.h
+++ b/src/statuseffect.h
@@ -56,9 +56,9 @@ public:
AnimatedSprite *getIcon();
/**
- * Retrieves an action to perform, or ACTION_INVALID
+ * Retrieves an action to perform, or SpriteAction::INVALID
*/
- SpriteAction getAction();
+ std::string getAction();
/**
* Determines whether the particle effect should be restarted when the
diff --git a/src/text.cpp b/src/text.cpp
index f6c71dba..216b02e2 100644
--- a/src/text.cpp
+++ b/src/text.cpp
@@ -28,10 +28,10 @@
#include "gui/gui.h"
#include "gui/palette.h"
-#include "gui/theme.h"
#include "resources/resourcemanager.h"
#include "resources/image.h"
+#include "resources/theme.h"
#include <guichan/font.hpp>
@@ -41,17 +41,22 @@ Image *Text::mBubbleArrow;
Text::Text(const std::string &text, int x, int y,
gcn::Graphics::Alignment alignment,
- const gcn::Color* color, bool isSpeech) :
+ const gcn::Color* color, bool isSpeech,
+ gcn::Font *font) :
mText(text),
mColor(color),
- mFont(gui->getFont()),
mIsSpeech(isSpeech)
{
+ if (!font)
+ mFont = gui->getFont();
+ else
+ mFont = font;
+
if (textManager == 0)
{
textManager = new TextManager;
Image *sbImage = Theme::getImageFromTheme("bubble.png|W:#"
- + config.getValue("speechBubblecolor", "000000"));
+ + config.getStringValue("speechBubblecolor"));
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);
@@ -62,7 +67,7 @@ Text::Text(const std::string &text, int x, int y,
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);
+ const float bubbleAlpha = config.getFloatValue("speechBubbleAlpha");
for (int i = 0; i < 9; i++)
{
mBubble.grid[i]->setAlpha(bubbleAlpha);
@@ -145,8 +150,8 @@ void Text::draw(gcn::Graphics *graphics, int xOff, int yOff)
FlashText::FlashText(const std::string &text, int x, int y,
gcn::Graphics::Alignment alignment,
- const gcn::Color *color) :
- Text(text, x, y, alignment, color),
+ const gcn::Color *color, gcn::Font *font) :
+ Text(text, x, y, alignment, color, false, font),
mTime(0)
{
}
diff --git a/src/text.h b/src/text.h
index fcfaf6ed..c884b394 100644
--- a/src/text.h
+++ b/src/text.h
@@ -40,7 +40,8 @@ class Text
*/
Text(const std::string &text, int x, int y,
gcn::Graphics::Alignment alignment,
- const gcn::Color *color, bool isSpeech = false);
+ const gcn::Color *color, bool isSpeech = false,
+ gcn::Font *font = 0);
/**
* Destructor. The text is removed from the screen.
@@ -84,7 +85,8 @@ class FlashText : public Text
public:
FlashText(const std::string &text, int x, int y,
gcn::Graphics::Alignment alignment,
- const gcn::Color* color);
+ const gcn::Color* color,
+ gcn::Font *font = 0);
/**
* Remove the text from the screen
diff --git a/src/textparticle.cpp b/src/textparticle.cpp
index e6226449..827343fa 100644
--- a/src/textparticle.cpp
+++ b/src/textparticle.cpp
@@ -36,10 +36,10 @@ TextParticle::TextParticle(Map *map, const std::string &text,
{
}
-void TextParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
+bool TextParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
{
if (!mAlive)
- return;
+ return false;
int screenX = (int) mPos.x + offsetX;
int screenY = (int) mPos.y - (int) mPos.z + offsetY;
@@ -58,4 +58,6 @@ void TextParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
TextRenderer::renderText(graphics, mText,
screenX, screenY, gcn::Graphics::CENTER,
color, mTextFont, mOutline, false);
+
+ return true;
}
diff --git a/src/textparticle.h b/src/textparticle.h
index a61bf8d9..7d99a057 100644
--- a/src/textparticle.h
+++ b/src/textparticle.h
@@ -38,7 +38,7 @@ class TextParticle : public Particle
/**
* Draws the particle image.
*/
- virtual void draw(Graphics *graphics, int offsetX, int offsetY) const;
+ virtual bool draw(Graphics *graphics, int offsetX, int offsetY) const;
// hack to improve text visibility
virtual int getPixelY() const
diff --git a/src/textrenderer.h b/src/textrenderer.h
index 4da868f1..fccdd3c7 100644
--- a/src/textrenderer.h
+++ b/src/textrenderer.h
@@ -24,7 +24,7 @@
#include "graphics.h"
-#include "gui/theme.h"
+#include "resources/theme.h"
/**
* Class for text rendering. Used by the TextParticle, the Text and FlashText
diff --git a/src/utils/copynpaste.cpp b/src/utils/copynpaste.cpp
index 31aa7bf9..3d2e3b80 100644
--- a/src/utils/copynpaste.cpp
+++ b/src/utils/copynpaste.cpp
@@ -269,7 +269,6 @@ static char* getSelection(Display *dpy, Window us, Atom selection)
return (char*)data;
}
}
- printf("Timeout\n");
return NULL;
}
diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp
index 9fe3de14..3988c769 100644
--- a/src/utils/stringutils.cpp
+++ b/src/utils/stringutils.cpp
@@ -26,7 +26,7 @@
#include <cstdarg>
#include <cstdio>
-const int UTF8_MAX_SIZE = 10;
+static int UTF8_MAX_SIZE = 10;
std::string &trim(std::string &str)
{
@@ -174,4 +174,16 @@ const char* getSafeUtf8String(std::string text)
memcpy(buf, text.c_str(), text.size());
memset(buf + text.size(), 0, UTF8_MAX_SIZE);
return buf;
-} \ No newline at end of file
+}
+
+bool getBoolFromString(const std::string &text)
+{
+ std::string txt = text;
+ toLower(trim(txt));
+ if (txt == "true" || txt == "yes" || txt == "on" || txt == "1")
+ return true;
+ else if (txt == "false" || txt == "no" || txt == "off" || txt == "0")
+ return false;
+ else
+ return (bool) atoi(txt.c_str());
+}
diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h
index ec82e240..7c14b1e5 100644
--- a/src/utils/stringutils.h
+++ b/src/utils/stringutils.h
@@ -125,4 +125,12 @@ const std::string findSameSubstring(const std::string &str1, const std::string &
const char* getSafeUtf8String(std::string text);
+/**
+ * Returns a bool value depending on the given string value.
+ *
+ * @param text the string used to get the bool value
+ * @return a boolean value..
+ */
+bool getBoolFromString(const std::string &text);
+
#endif // UTILS_STRINGUTILS_H
diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp
index 9835f88c..bb386f51 100644
--- a/src/utils/xml.cpp
+++ b/src/utils/xml.cpp
@@ -21,15 +21,19 @@
#include "utils/xml.h"
+#include <iostream>
+#include <fstream>
+#include <cstring>
+
+#include <libxml/parser.h>
+#include <libxml/xmlerror.h>
+
#include "log.h"
#include "resources/resourcemanager.h"
#include "utils/zlib.h"
-#include <libxml/parser.h>
-#include <libxml/xmlerror.h>
-
namespace XML
{
static void xmlLogger(void *ctx, xmlErrorPtr error);
@@ -129,6 +133,15 @@ namespace XML
return def;
}
+ bool getBoolProperty(xmlNodePtr node, const char* name, bool def)
+ {
+ xmlChar *prop = xmlGetProp(node, BAD_CAST name);
+
+ if (xmlStrEqual(prop, BAD_CAST "true" ) ) return true;
+ if (xmlStrEqual(prop, BAD_CAST "false") ) return false;
+ return def;
+ }
+
xmlNodePtr findFirstChildByName(xmlNodePtr parent, const char *name)
{
for_each_xml_child_node(child, parent)
diff --git a/src/utils/xml.h b/src/utils/xml.h
index 8ffecb76..48e66787 100644
--- a/src/utils/xml.h
+++ b/src/utils/xml.h
@@ -60,14 +60,14 @@ namespace XML
};
/**
- * Gets an integer property from an xmlNodePtr.
+ * Gets an floating point property from an xmlNodePtr.
*/
- int getProperty(xmlNodePtr node, const char *name, int def);
+ double getFloatProperty(xmlNodePtr node, const char *name, double def);
/**
- * Gets an floating point property from an xmlNodePtr.
+ * Gets an integer property from an xmlNodePtr.
*/
- double getFloatProperty(xmlNodePtr node, const char *name, double def);
+ int getProperty(xmlNodePtr node, const char *name, int def);
/**
* Gets a string property from an xmlNodePtr.
@@ -76,6 +76,11 @@ namespace XML
const std::string &def);
/**
+ * Gets a boolean property from an xmlNodePtr.
+ */
+ bool getBoolProperty(xmlNodePtr node, const char *name, bool def);
+
+ /**
* Finds the first child node with the given name
*/
xmlNodePtr findFirstChildByName(xmlNodePtr parent, const char *name);
diff --git a/src/variabledata.h b/src/variabledata.h
new file mode 100644
index 00000000..f73ebab2
--- /dev/null
+++ b/src/variabledata.h
@@ -0,0 +1,100 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef VARIABLEDATA_H
+#define VARIABLEDATA_H
+
+#include <string>
+
+namespace Mana
+{
+
+class VariableData
+{
+ public:
+ enum DataType
+ {
+ DATA_NONE,
+ DATA_INT,
+ DATA_STRING,
+ DATA_FLOAT,
+ DATA_BOOL
+ };
+
+ virtual ~VariableData() {};
+
+ virtual int getType() const = 0;
+};
+
+class IntData : public VariableData
+{
+public:
+ IntData(int value) { mData = value; }
+
+ int getData() const { return mData; }
+
+ int getType() const { return DATA_INT; }
+
+private:
+ int mData;
+};
+
+class StringData : public VariableData
+{
+public:
+ StringData(const std::string &value) { mData = value; }
+
+ const std::string &getData() const { return mData; }
+
+ int getType() const { return DATA_STRING; }
+
+private:
+ std::string mData;
+};
+
+class FloatData : public VariableData
+{
+public:
+ FloatData(double value) { mData = value; }
+
+ double getData() const { return mData; }
+
+ int getType() const { return DATA_FLOAT; }
+
+private:
+ double mData;
+};
+
+class BoolData : public VariableData
+{
+public:
+ BoolData(bool value) { mData = value; }
+
+ bool getData() const { return mData; }
+
+ int getType() const { return DATA_BOOL; }
+
+private:
+ bool mData;
+};
+
+} // namespace Mana
+
+#endif