summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMake/Modules/FindGuichan.cmake7
-rw-r--r--Mana.vcproj876
-rwxr-xr-xconfigure.ac3
-rw-r--r--data/graphics/CMakeLists.txt9
-rw-r--r--data/graphics/Makefile.am14
-rw-r--r--data/graphics/gui/CMakeLists.txt6
-rw-r--r--data/graphics/gui/Makefile.am6
-rw-r--r--data/graphics/target-cursor-in-range-l.png (renamed from data/graphics/gui/target-cursor-blue-l.png)bin23803 -> 23803 bytes
-rw-r--r--data/graphics/target-cursor-in-range-m.png (renamed from data/graphics/gui/target-cursor-blue-m.png)bin18439 -> 18439 bytes
-rw-r--r--data/graphics/target-cursor-in-range-s.png (renamed from data/graphics/gui/target-cursor-blue-s.png)bin8353 -> 8353 bytes
-rw-r--r--data/graphics/target-cursor-normal-l.png (renamed from data/graphics/gui/target-cursor-red-l.png)bin25586 -> 25586 bytes
-rw-r--r--data/graphics/target-cursor-normal-m.png (renamed from data/graphics/gui/target-cursor-red-m.png)bin17950 -> 17950 bytes
-rw-r--r--data/graphics/target-cursor-normal-s.png (renamed from data/graphics/gui/target-cursor-red-s.png)bin8361 -> 8361 bytes
-rw-r--r--mana.cbp136
-rw-r--r--mana.files136
-rw-r--r--packaging/windows/setup.nsi2
-rw-r--r--po/de.po108
-rw-r--r--src/CMakeLists.txt39
-rw-r--r--src/Makefile.am41
-rw-r--r--src/actor.cpp58
-rw-r--r--src/actor.h128
-rw-r--r--src/actorsprite.cpp464
-rw-r--r--src/actorsprite.h248
-rw-r--r--src/actorspritelistener.h (renamed from src/flooritemmanager.h)46
-rw-r--r--src/actorspritemanager.cpp318
-rw-r--r--src/actorspritemanager.h (renamed from src/beingmanager.h)80
-rw-r--r--src/animatedsprite.cpp52
-rw-r--r--src/animatedsprite.h57
-rw-r--r--src/being.cpp806
-rw-r--r--src/being.h382
-rw-r--r--src/beingmanager.cpp296
-rw-r--r--src/chatlog.cpp177
-rw-r--r--src/chatlog.h73
-rw-r--r--src/client.cpp32
-rw-r--r--src/client.h1
-rw-r--r--src/commandhandler.cpp2
-rw-r--r--src/compoundsprite.cpp367
-rw-r--r--src/compoundsprite.h105
-rw-r--r--src/event.cpp99
-rw-r--r--src/event.h74
-rw-r--r--src/eventmanager.cpp67
-rw-r--r--src/eventmanager.h62
-rw-r--r--src/flooritem.cpp57
-rw-r--r--src/flooritem.h76
-rw-r--r--src/flooritemmanager.cpp80
-rw-r--r--src/game.cpp86
-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.cpp7
-rw-r--r--src/gui/buysell.cpp2
-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.cpp37
-rw-r--r--src/gui/chat.h24
-rw-r--r--src/gui/inventorywindow.cpp27
-rw-r--r--src/gui/inventorywindow.h17
-rw-r--r--src/gui/itempopup.cpp5
-rw-r--r--src/gui/minimap.cpp69
-rw-r--r--src/gui/ministatus.cpp87
-rw-r--r--src/gui/ministatus.h6
-rw-r--r--src/gui/npcdialog.cpp1
-rw-r--r--src/gui/npcdialog.h1
-rw-r--r--src/gui/npcpostdialog.cpp2
-rw-r--r--src/gui/outfitwindow.cpp12
-rw-r--r--src/gui/popupmenu.cpp51
-rw-r--r--src/gui/register.h2
-rw-r--r--src/gui/sell.cpp6
-rw-r--r--src/gui/serverdialog.cpp3
-rw-r--r--src/gui/setup_players.cpp23
-rw-r--r--src/gui/setup_players.h3
-rw-r--r--src/gui/skilldialog.cpp14
-rw-r--r--src/gui/socialwindow.cpp2
-rw-r--r--src/gui/specialswindow.cpp177
-rw-r--r--src/gui/specialswindow.h20
-rw-r--r--src/gui/statuswindow.cpp263
-rw-r--r--src/gui/statuswindow.h14
-rw-r--r--src/gui/trade.cpp9
-rw-r--r--src/gui/viewport.cpp80
-rw-r--r--src/gui/viewport.h9
-rw-r--r--src/gui/widgets/chattab.cpp12
-rw-r--r--src/gui/widgets/chattab.h17
-rw-r--r--src/gui/widgets/itemshortcutcontainer.cpp10
-rw-r--r--src/gui/widgets/playerbox.cpp16
-rw-r--r--src/gui/widgets/playerbox.h8
-rw-r--r--src/gui/widgets/whispertab.cpp7
-rw-r--r--src/gui/widgets/whispertab.h2
-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.cpp3
-rw-r--r--src/itemshortcut.cpp4
-rw-r--r--src/listener.cpp43
-rw-r--r--src/listener.h45
-rw-r--r--src/localplayer.cpp386
-rw-r--r--src/localplayer.h249
-rw-r--r--src/main.cpp8
-rw-r--r--src/map.cpp70
-rw-r--r--src/map.h40
-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/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.cpp44
-rw-r--r--src/net/manaserv/buysellhandler.cpp13
-rw-r--r--src/net/manaserv/charhandler.cpp17
-rw-r--r--src/net/manaserv/charhandler.h6
-rw-r--r--src/net/manaserv/chathandler.cpp4
-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.cpp15
-rw-r--r--src/net/manaserv/guildhandler.h2
-rw-r--r--src/net/manaserv/inventoryhandler.cpp13
-rw-r--r--src/net/manaserv/itemhandler.cpp9
-rw-r--r--src/net/manaserv/npchandler.cpp7
-rw-r--r--src/net/manaserv/partyhandler.cpp17
-rw-r--r--src/net/manaserv/partyhandler.h4
-rw-r--r--src/net/manaserv/playerhandler.cpp77
-rw-r--r--src/net/manaserv/tradehandler.cpp27
-rw-r--r--src/net/npchandler.h4
-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.cpp172
-rw-r--r--src/net/tmwa/buysellhandler.cpp25
-rw-r--r--src/net/tmwa/charserverhandler.cpp57
-rw-r--r--src/net/tmwa/charserverhandler.h8
-rw-r--r--src/net/tmwa/chathandler.cpp44
-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.cpp80
-rw-r--r--src/net/tmwa/generalhandler.h12
-rw-r--r--src/net/tmwa/gui/guildtab.cpp7
-rw-r--r--src/net/tmwa/gui/guildtab.h2
-rw-r--r--src/net/tmwa/gui/partytab.cpp7
-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.cpp3
-rw-r--r--src/net/tmwa/partyhandler.cpp40
-rw-r--r--src/net/tmwa/partyhandler.h4
-rw-r--r--src/net/tmwa/playerhandler.cpp226
-rw-r--r--src/net/tmwa/specialhandler.cpp8
-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.cpp17
-rw-r--r--src/particle.h52
-rw-r--r--src/party.cpp8
-rw-r--r--src/player.cpp360
-rw-r--r--src/player.h161
-rw-r--r--src/playerinfo.cpp312
-rw-r--r--src/playerinfo.h213
-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/itemdb.cpp32
-rw-r--r--src/resources/iteminfo.h12
-rw-r--r--src/resources/monsterdb.cpp71
-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.cpp4
-rw-r--r--src/resources/spritedef.h23
-rw-r--r--src/sprite.h89
-rw-r--r--src/text.cpp13
-rw-r--r--src/text.h6
-rw-r--r--src/textparticle.cpp6
-rw-r--r--src/textparticle.h2
-rw-r--r--src/utils/copynpaste.cpp1
-rw-r--r--src/utils/xml.cpp10
-rw-r--r--src/utils/xml.h13
-rw-r--r--src/variabledata.h85
201 files changed, 6346 insertions, 5494 deletions
diff --git a/CMake/Modules/FindGuichan.cmake b/CMake/Modules/FindGuichan.cmake
index 1623b00d..dbc863e2 100644
--- a/CMake/Modules/FindGuichan.cmake
+++ b/CMake/Modules/FindGuichan.cmake
@@ -85,6 +85,13 @@ FOREACH (COMPONENT ${Guichan_FIND_COMPONENTS})
MESSAGE(FATAL_ERROR "Could NOT find Guichan component ${COMPONENT}")
ENDIF ()
+ # Check guichan >= 0.8.0 by searching for the widgetlistener.hpp file.
+ SET(Guichan_HEADER "guichan/widgetlistener.hpp")
+ IF (NOT EXISTS ${Guichan_INCLUDE_DIR}/${Guichan_HEADER})
+ SET(GUICHAN_FOUND FALSE)
+ MESSAGE(FATAL_ERROR "Guichan version is less than 0.8.0")
+ ENDIF()
+
IF (NOT Guichan_FIND_QUIETLY AND NOT Guichan_QUIET)
MESSAGE(STATUS "Found Guichan ${COMPONENT}: ${Guichan_LIBRARY_${COMPONENT}}")
ENDIF ()
diff --git a/Mana.vcproj b/Mana.vcproj
deleted file mode 100644
index b3ebef21..00000000
--- a/Mana.vcproj
+++ /dev/null
@@ -1,876 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8,00"
- Name="ManaWorld"
- ProjectGUID="{DE31E83E-62BD-460E-8E6A-648CF98CC5A4}"
- RootNamespace="ManaWorld"
- Keyword="Win32Proj"
- SignManifests="true"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="1"
- InheritedPropertySheets="UpgradeFromVC71.vsprops"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- RuntimeTypeInfo="true"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="physfs.lib sdl.lib sdlmain.lib sdl_image.lib sdl_mixer.lib guichan.lib guichan_sdl.lib ws2_32.lib libxml2.lib iconv.lib zlib.lib libcurl.lib"
- OutputFile="$(OutDir)/ManaWorld.exe"
- LinkIncremental="2"
- IgnoreDefaultLibraryNames="libc.lib"
- GenerateDebugInformation="true"
- ProgramDatabaseFile="$(OutDir)/ManaWorld.pdb"
- SubSystem="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="1"
- InheritedPropertySheets="UpgradeFromVC71.vsprops"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="&quot;D:\Programming\Libraries\LibXml\libxml2-2.6.17.win32\lib&quot;;&quot;D:\Programming\Libraries\LibXml\libxml2-2.6.17.win32\include&quot;"
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
- RuntimeLibrary="2"
- RuntimeTypeInfo="true"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="physfs.lib alleg.lib guichan.lib guichan_sdl.lib sdl.lib sdlmain.lib sdl_mixer.lib sdl_image.lib ws2_32.lib libxml2.lib iconv.lib zlib.lib libcurl.lib"
- OutputFile="mana.exe"
- LinkIncremental="1"
- IgnoreDefaultLibraryNames="LIBC.lib"
- GenerateDebugInformation="true"
- ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"
- SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Profile|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- InheritedPropertySheets="UpgradeFromVC71.vsprops"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- RuntimeLibrary="2"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalOptions="SDL.lib"
- AdditionalDependencies="allp.lib"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath=".\src\base64.cpp"
- >
- </File>
- <File
- RelativePath=".\src\base64.h"
- >
- </File>
- <File
- RelativePath=".\src\being.cpp"
- >
- </File>
- <File
- RelativePath=".\src\being.h"
- >
- </File>
- <File
- RelativePath=".\src\configuration.cpp"
- >
- </File>
- <File
- RelativePath=".\src\configuration.h"
- >
- </File>
- <File
- RelativePath=".\src\engine.cpp"
- >
- </File>
- <File
- RelativePath=".\src\engine.h"
- >
- </File>
- <File
- RelativePath=".\src\floor_item.cpp"
- >
- </File>
- <File
- RelativePath=".\src\floor_item.h"
- >
- </File>
- <File
- RelativePath=".\src\game.cpp"
- >
- </File>
- <File
- RelativePath=".\src\game.h"
- >
- </File>
- <File
- RelativePath=".\src\graphics.cpp"
- >
- </File>
- <File
- RelativePath=".\src\graphics.h"
- >
- </File>
- <File
- RelativePath=".\src\log.cpp"
- >
- </File>
- <File
- RelativePath=".\src\log.h"
- >
- </File>
- <File
- RelativePath=".\src\main.cpp"
- >
- </File>
- <File
- RelativePath=".\src\main.h"
- >
- </File>
- <File
- RelativePath=".\src\map.cpp"
- >
- </File>
- <File
- RelativePath=".\src\map.h"
- >
- </File>
- <File
- RelativePath=".\src\sound.cpp"
- >
- </File>
- <File
- RelativePath=".\src\sound.h"
- >
- </File>
- <Filter
- Name="graphic"
- >
- <File
- RelativePath=".\src\graphic\spriteset.cpp"
- >
- </File>
- <File
- RelativePath=".\src\graphic\spriteset.h"
- >
- </File>
- </Filter>
- <Filter
- Name="net"
- >
- <File
- RelativePath=".\src\net\network.cpp"
- >
- </File>
- <File
- RelativePath=".\src\net\network.h"
- >
- </File>
- <File
- RelativePath=".\src\net\protocol.cpp"
- >
- </File>
- <File
- RelativePath=".\src\net\protocol.h"
- >
- </File>
- <File
- RelativePath=".\src\net\win2linux.h"
- >
- </File>
- <File
- RelativePath=".\src\net\win2mac.cpp"
- >
- </File>
- <File
- RelativePath=".\src\net\win2mac.h"
- >
- </File>
- </Filter>
- <Filter
- Name="gui"
- >
- <File
- RelativePath=".\src\gui\box.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\box.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\browserbox.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\browserbox.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\buddywindow.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\buddywindow.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\button.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\button.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\buy.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\buy.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\buysell.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\buysell.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\char_select.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\char_select.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\char_server.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\char_server.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\chargedialog.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\chargedialog.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\chat.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\chat.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\chatinput.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\chatinput.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\checkbox.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\checkbox.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\confirm_dialog.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\confirm_dialog.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\equipment.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\equipment.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\focushandler.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\focushandler.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\gui.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\gui.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\hbox.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\hbox.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\help.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\help.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\inttextbox.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\inttextbox.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\inventory.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\inventory.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\item_amount.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\item_amount.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\itemcontainer.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\itemcontainer.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\linkhandler.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\listbox.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\listbox.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\login.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\login.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\minimap.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\minimap.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\newskill.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\newskill.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\npc.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\npc.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\npc_text.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\npc_text.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\ok_dialog.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\ok_dialog.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\passwordfield.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\passwordfield.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\playerbox.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\playerbox.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\popupmenu.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\popupmenu.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\progressbar.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\progressbar.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\radiobutton.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\radiobutton.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\requesttrade.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\requesttrade.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\scrollarea.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\scrollarea.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\sell.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\sell.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\setup.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\setup.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\shop.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\shop.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\skill.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\skill.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\slider.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\slider.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\stats.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\stats.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\status.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\status.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\textbox.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\textbox.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\textfield.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\textfield.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\trade.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\trade.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\updatewindow.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\updatewindow.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\vbox.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\vbox.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\window.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\window.h"
- >
- </File>
- <File
- RelativePath=".\src\gui\windowcontainer.cpp"
- >
- </File>
- <File
- RelativePath=".\src\gui\windowcontainer.h"
- >
- </File>
- </Filter>
- <Filter
- Name="resources"
- >
- <File
- RelativePath=".\src\resources\buddylist.cpp"
- >
- </File>
- <File
- RelativePath=".\src\resources\buddylist.h"
- >
- </File>
- <File
- RelativePath=".\src\resources\image.cpp"
- >
- </File>
- <File
- RelativePath=".\src\resources\image.h"
- >
- </File>
- <File
- RelativePath=".\src\resources\iteminfo.cpp"
- >
- </File>
- <File
- RelativePath=".\src\resources\iteminfo.h"
- >
- </File>
- <File
- RelativePath=".\src\resources\itemmanager.cpp"
- >
- </File>
- <File
- RelativePath=".\src\resources\itemmanager.h"
- >
- </File>
- <File
- RelativePath=".\src\resources\mapreader.cpp"
- >
- </File>
- <File
- RelativePath=".\src\resources\mapreader.h"
- >
- </File>
- <File
- RelativePath=".\src\resources\music.cpp"
- >
- </File>
- <File
- RelativePath=".\src\resources\music.h"
- >
- </File>
- <File
- RelativePath=".\src\resources\resource.cpp"
- >
- </File>
- <File
- RelativePath=".\src\resources\resource.h"
- >
- </File>
- <File
- RelativePath=".\src\resources\resourcemanager.cpp"
- >
- </File>
- <File
- RelativePath=".\src\resources\resourcemanager.h"
- >
- </File>
- <File
- RelativePath=".\src\resources\soundeffect.cpp"
- >
- </File>
- <File
- RelativePath=".\src\resources\soundeffect.h"
- >
- </File>
- </Filter>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/configure.ac b/configure.ac
index 64097586..058fc0a6 100755
--- a/configure.ac
+++ b/configure.ac
@@ -37,6 +37,9 @@ AC_MSG_ERROR([ *** Unable to find Guichan library (http://guichan.sf.net/)]))
AC_CHECK_HEADERS([guichan.hpp], ,
AC_MSG_ERROR([ *** Guichan library found but cannot find headers (http://guichan.sf.net/)]))
+AC_CHECK_HEADERS([guichan/widgetlistener.hpp], ,
+AC_MSG_ERROR([ *** Guichan library version is found but version is < 0.8.0 (http://guichan.sf.net/)]))
+
if test -n "$SDL_CONFIG"; then
LIBS="$LIBS `$SDL_CONFIG --libs`"
CPPFLAGS="$CPPFLAGS `$SDL_CONFIG --cflags`"
diff --git a/data/graphics/CMakeLists.txt b/data/graphics/CMakeLists.txt
index 5a9b0f65..a46ccfd0 100644
--- a/data/graphics/CMakeLists.txt
+++ b/data/graphics/CMakeLists.txt
@@ -1,3 +1,12 @@
ADD_SUBDIRECTORY(gui)
ADD_SUBDIRECTORY(images)
ADD_SUBDIRECTORY(sprites)
+
+SET (FILES
+ target-cursor-in-range-l.png
+ target-cursor-in-range-m.png
+ target-cursor-in-range-s.png
+ target-cursor-normal-l.png
+ target-cursor-normal-m.png
+ target-cursor-normal-s.png
+ )
diff --git a/data/graphics/Makefile.am b/data/graphics/Makefile.am
index b77b57ca..d2f93f58 100644
--- a/data/graphics/Makefile.am
+++ b/data/graphics/Makefile.am
@@ -1,4 +1,16 @@
-EXTRA_DIST = CMakeLists.txt
+graphicsdir = $(pkgdatadir)/data/graphics
+
+graphics_DATA = \
+ target-cursor-in-range-l.png \
+ target-cursor-in-range-m.png \
+ target-cursor-in-range-s.png \
+ target-cursor-normal-l.png \
+ target-cursor-normal-m.png \
+ target-cursor-normal-s.png
+
+EXTRA_DIST = \
+ $(graphics_DATA) \
+ CMakeLists.txt
SUBDIRS = gui images sprites
diff --git a/data/graphics/gui/CMakeLists.txt b/data/graphics/gui/CMakeLists.txt
index a7c21e5e..92a1e3ef 100644
--- a/data/graphics/gui/CMakeLists.txt
+++ b/data/graphics/gui/CMakeLists.txt
@@ -32,12 +32,6 @@ SET (FILES
tab.png
tab_hilight.png
tabselected.png
- target-cursor-blue-l.png
- target-cursor-blue-m.png
- target-cursor-blue-s.png
- target-cursor-red-l.png
- target-cursor-red-m.png
- target-cursor-red-s.png
unknown-item.png
vscroll_down_default.png
vscroll_down_highlight.png
diff --git a/data/graphics/gui/Makefile.am b/data/graphics/gui/Makefile.am
index 6d04666a..04f957b7 100644
--- a/data/graphics/gui/Makefile.am
+++ b/data/graphics/gui/Makefile.am
@@ -35,12 +35,6 @@ gui_DATA = \
tab.png \
tab_hilight.png \
tabselected.png \
- target-cursor-blue-l.png \
- target-cursor-blue-m.png \
- target-cursor-blue-s.png \
- target-cursor-red-l.png \
- target-cursor-red-m.png \
- target-cursor-red-s.png \
unknown-item.png \
vscroll_down_default.png \
vscroll_down_highlight.png \
diff --git a/data/graphics/gui/target-cursor-blue-l.png b/data/graphics/target-cursor-in-range-l.png
index 77cdf4b6..77cdf4b6 100644
--- a/data/graphics/gui/target-cursor-blue-l.png
+++ b/data/graphics/target-cursor-in-range-l.png
Binary files differ
diff --git a/data/graphics/gui/target-cursor-blue-m.png b/data/graphics/target-cursor-in-range-m.png
index c0107357..c0107357 100644
--- a/data/graphics/gui/target-cursor-blue-m.png
+++ b/data/graphics/target-cursor-in-range-m.png
Binary files differ
diff --git a/data/graphics/gui/target-cursor-blue-s.png b/data/graphics/target-cursor-in-range-s.png
index 3e81c75d..3e81c75d 100644
--- a/data/graphics/gui/target-cursor-blue-s.png
+++ b/data/graphics/target-cursor-in-range-s.png
Binary files differ
diff --git a/data/graphics/gui/target-cursor-red-l.png b/data/graphics/target-cursor-normal-l.png
index 76d2101b..76d2101b 100644
--- a/data/graphics/gui/target-cursor-red-l.png
+++ b/data/graphics/target-cursor-normal-l.png
Binary files differ
diff --git a/data/graphics/gui/target-cursor-red-m.png b/data/graphics/target-cursor-normal-m.png
index e2ab79c2..e2ab79c2 100644
--- a/data/graphics/gui/target-cursor-red-m.png
+++ b/data/graphics/target-cursor-normal-m.png
Binary files differ
diff --git a/data/graphics/gui/target-cursor-red-s.png b/data/graphics/target-cursor-normal-s.png
index 09195f44..09195f44 100644
--- a/data/graphics/gui/target-cursor-red-s.png
+++ b/data/graphics/target-cursor-normal-s.png
Binary files differ
diff --git a/mana.cbp b/mana.cbp
index cc12f237..9091380c 100644
--- a/mana.cbp
+++ b/mana.cbp
@@ -11,6 +11,7 @@
<Option object_output=".objs\" />
<Option type="0" />
<Option compiler="gcc" />
+ <Option parameters="-u -d C:\mana\data" />
<Option projectResourceIncludeDirsRelation="0" />
<Compiler>
<Add option="-O3" />
@@ -94,6 +95,13 @@
</Linker>
<Unit filename="src\SDLMain.h" />
<Unit filename="src\SDLMain.m" />
+ <Unit filename="src\actor.cpp" />
+ <Unit filename="src\actor.h" />
+ <Unit filename="src\actorsprite.cpp" />
+ <Unit filename="src\actorsprite.h" />
+ <Unit filename="src\actorspritelistener.h" />
+ <Unit filename="src\actorspritemanager.cpp" />
+ <Unit filename="src\actorspritemanager.h" />
<Unit filename="src\animatedsprite.cpp" />
<Unit filename="src\animatedsprite.h" />
<Unit filename="src\animationparticle.cpp" />
@@ -102,16 +110,18 @@
<Unit filename="src\avatar.h" />
<Unit filename="src\being.cpp" />
<Unit filename="src\being.h" />
- <Unit filename="src\beingmanager.cpp" />
- <Unit filename="src\beingmanager.h" />
<Unit filename="src\channel.cpp" />
<Unit filename="src\channel.h" />
<Unit filename="src\channelmanager.cpp" />
<Unit filename="src\channelmanager.h" />
+ <Unit filename="src\chatlog.cpp" />
+ <Unit filename="src\chatlog.h" />
<Unit filename="src\client.cpp" />
<Unit filename="src\client.h" />
<Unit filename="src\commandhandler.cpp" />
<Unit filename="src\commandhandler.h" />
+ <Unit filename="src\compoundsprite.cpp" />
+ <Unit filename="src\compoundsprite.h" />
<Unit filename="src\configlistener.h" />
<Unit filename="src\configuration.cpp" />
<Unit filename="src\configuration.h" />
@@ -119,12 +129,13 @@
<Unit filename="src\effectmanager.h" />
<Unit filename="src\emoteshortcut.cpp" />
<Unit filename="src\emoteshortcut.h" />
- <Unit filename="src\engine.h" />
<Unit filename="src\equipment.h" />
+ <Unit filename="src\event.cpp" />
+ <Unit filename="src\event.h" />
+ <Unit filename="src\eventmanager.cpp" />
+ <Unit filename="src\eventmanager.h" />
<Unit filename="src\flooritem.cpp" />
<Unit filename="src\flooritem.h" />
- <Unit filename="src\flooritemmanager.cpp" />
- <Unit filename="src\flooritemmanager.h" />
<Unit filename="src\game.cpp" />
<Unit filename="src\game.h" />
<Unit filename="src\graphics.cpp" />
@@ -236,9 +247,9 @@
<Unit filename="src\gui\unregisterdialog.cpp" />
<Unit filename="src\gui\unregisterdialog.h" />
<Unit filename="src\gui\updatewindow.cpp" />
+ <Unit filename="src\gui\updatewindow.h" />
<Unit filename="src\gui\userpalette.cpp" />
<Unit filename="src\gui\userpalette.h" />
- <Unit filename="src\gui\updatewindow.h" />
<Unit filename="src\gui\viewport.cpp" />
<Unit filename="src\gui\viewport.h" />
<Unit filename="src\gui\widgets\avatarlistbox.cpp" />
@@ -339,6 +350,8 @@
<Unit filename="src\guild.h" />
<Unit filename="src\imageparticle.cpp" />
<Unit filename="src\imageparticle.h" />
+ <Unit filename="src\imagesprite.cpp" />
+ <Unit filename="src\imagesprite.h" />
<Unit filename="src\inventory.cpp" />
<Unit filename="src\inventory.h" />
<Unit filename="src\item.cpp" />
@@ -349,9 +362,10 @@
<Unit filename="src\joystick.h" />
<Unit filename="src\keyboardconfig.cpp" />
<Unit filename="src\keyboardconfig.h" />
+ <Unit filename="src\listener.cpp" />
+ <Unit filename="src\listener.h" />
<Unit filename="src\localplayer.cpp" />
<Unit filename="src\localplayer.h" />
- <Unit filename="src\lockedarray.h" />
<Unit filename="src\log.cpp" />
<Unit filename="src\log.h" />
<Unit filename="src\main.cpp" />
@@ -364,60 +378,12 @@
</Unit>
<Unit filename="src\map.cpp" />
<Unit filename="src\map.h" />
- <Unit filename="src\monster.cpp" />
- <Unit filename="src\monster.h" />
<Unit filename="src\net\adminhandler.h" />
<Unit filename="src\net\charhandler.cpp" />
<Unit filename="src\net\charhandler.h" />
<Unit filename="src\net\chathandler.h" />
<Unit filename="src\net\download.cpp" />
<Unit filename="src\net\download.h" />
- <Unit filename="src\net\tmwa\adminhandler.cpp" />
- <Unit filename="src\net\tmwa\adminhandler.h" />
- <Unit filename="src\net\tmwa\beinghandler.cpp" />
- <Unit filename="src\net\tmwa\beinghandler.h" />
- <Unit filename="src\net\tmwa\buysellhandler.cpp" />
- <Unit filename="src\net\tmwa\buysellhandler.h" />
- <Unit filename="src\net\tmwa\charserverhandler.cpp" />
- <Unit filename="src\net\tmwa\charserverhandler.h" />
- <Unit filename="src\net\tmwa\chathandler.cpp" />
- <Unit filename="src\net\tmwa\chathandler.h" />
- <Unit filename="src\net\tmwa\gamehandler.cpp" />
- <Unit filename="src\net\tmwa\gamehandler.h" />
- <Unit filename="src\net\tmwa\generalhandler.cpp" />
- <Unit filename="src\net\tmwa\generalhandler.h" />
- <Unit filename="src\net\tmwa\gui\guildtab.cpp" />
- <Unit filename="src\net\tmwa\gui\guildtab.h" />
- <Unit filename="src\net\tmwa\gui\partytab.cpp" />
- <Unit filename="src\net\tmwa\gui\partytab.h" />
- <Unit filename="src\net\tmwa\guildhandler.cpp" />
- <Unit filename="src\net\tmwa\guildhandler.h" />
- <Unit filename="src\net\tmwa\inventoryhandler.cpp" />
- <Unit filename="src\net\tmwa\inventoryhandler.h" />
- <Unit filename="src\net\tmwa\itemhandler.cpp" />
- <Unit filename="src\net\tmwa\itemhandler.h" />
- <Unit filename="src\net\tmwa\loginhandler.cpp" />
- <Unit filename="src\net\tmwa\loginhandler.h" />
- <Unit filename="src\net\tmwa\messagehandler.cpp" />
- <Unit filename="src\net\tmwa\messagehandler.h" />
- <Unit filename="src\net\tmwa\messagein.cpp" />
- <Unit filename="src\net\tmwa\messagein.h" />
- <Unit filename="src\net\tmwa\messageout.cpp" />
- <Unit filename="src\net\tmwa\messageout.h" />
- <Unit filename="src\net\tmwa\network.cpp" />
- <Unit filename="src\net\tmwa\network.h" />
- <Unit filename="src\net\tmwa\npchandler.cpp" />
- <Unit filename="src\net\tmwa\npchandler.h" />
- <Unit filename="src\net\tmwa\partyhandler.cpp" />
- <Unit filename="src\net\tmwa\partyhandler.h" />
- <Unit filename="src\net\tmwa\playerhandler.cpp" />
- <Unit filename="src\net\tmwa\playerhandler.h" />
- <Unit filename="src\net\tmwa\protocol.h" />
- <Unit filename="src\net\tmwa\specialhandler.cpp" />
- <Unit filename="src\net\tmwa\specialhandler.h" />
- <Unit filename="src\net\tmwa\token.h" />
- <Unit filename="src\net\tmwa\tradehandler.cpp" />
- <Unit filename="src\net\tmwa\tradehandler.h" />
<Unit filename="src\net\gamehandler.h" />
<Unit filename="src\net\generalhandler.h" />
<Unit filename="src\net\guildhandler.h" />
@@ -436,6 +402,7 @@
<Unit filename="src\net\manaserv\chathandler.h" />
<Unit filename="src\net\manaserv\connection.cpp" />
<Unit filename="src\net\manaserv\connection.h" />
+ <Unit filename="src\net\manaserv\defines.h" />
<Unit filename="src\net\manaserv\effecthandler.cpp" />
<Unit filename="src\net\manaserv\effecthandler.h" />
<Unit filename="src\net\manaserv\gamehandler.cpp" />
@@ -485,10 +452,54 @@
<Unit filename="src\net\playerhandler.h" />
<Unit filename="src\net\serverinfo.h" />
<Unit filename="src\net\specialhandler.h" />
+ <Unit filename="src\net\tmwa\adminhandler.cpp" />
+ <Unit filename="src\net\tmwa\adminhandler.h" />
+ <Unit filename="src\net\tmwa\beinghandler.cpp" />
+ <Unit filename="src\net\tmwa\beinghandler.h" />
+ <Unit filename="src\net\tmwa\buysellhandler.cpp" />
+ <Unit filename="src\net\tmwa\buysellhandler.h" />
+ <Unit filename="src\net\tmwa\charserverhandler.cpp" />
+ <Unit filename="src\net\tmwa\charserverhandler.h" />
+ <Unit filename="src\net\tmwa\chathandler.cpp" />
+ <Unit filename="src\net\tmwa\chathandler.h" />
+ <Unit filename="src\net\tmwa\gamehandler.cpp" />
+ <Unit filename="src\net\tmwa\gamehandler.h" />
+ <Unit filename="src\net\tmwa\generalhandler.cpp" />
+ <Unit filename="src\net\tmwa\generalhandler.h" />
+ <Unit filename="src\net\tmwa\gui\guildtab.cpp" />
+ <Unit filename="src\net\tmwa\gui\guildtab.h" />
+ <Unit filename="src\net\tmwa\gui\partytab.cpp" />
+ <Unit filename="src\net\tmwa\gui\partytab.h" />
+ <Unit filename="src\net\tmwa\guildhandler.cpp" />
+ <Unit filename="src\net\tmwa\guildhandler.h" />
+ <Unit filename="src\net\tmwa\inventoryhandler.cpp" />
+ <Unit filename="src\net\tmwa\inventoryhandler.h" />
+ <Unit filename="src\net\tmwa\itemhandler.cpp" />
+ <Unit filename="src\net\tmwa\itemhandler.h" />
+ <Unit filename="src\net\tmwa\loginhandler.cpp" />
+ <Unit filename="src\net\tmwa\loginhandler.h" />
+ <Unit filename="src\net\tmwa\messagehandler.cpp" />
+ <Unit filename="src\net\tmwa\messagehandler.h" />
+ <Unit filename="src\net\tmwa\messagein.cpp" />
+ <Unit filename="src\net\tmwa\messagein.h" />
+ <Unit filename="src\net\tmwa\messageout.cpp" />
+ <Unit filename="src\net\tmwa\messageout.h" />
+ <Unit filename="src\net\tmwa\network.cpp" />
+ <Unit filename="src\net\tmwa\network.h" />
+ <Unit filename="src\net\tmwa\npchandler.cpp" />
+ <Unit filename="src\net\tmwa\npchandler.h" />
+ <Unit filename="src\net\tmwa\partyhandler.cpp" />
+ <Unit filename="src\net\tmwa\partyhandler.h" />
+ <Unit filename="src\net\tmwa\playerhandler.cpp" />
+ <Unit filename="src\net\tmwa\playerhandler.h" />
+ <Unit filename="src\net\tmwa\protocol.h" />
+ <Unit filename="src\net\tmwa\specialhandler.cpp" />
+ <Unit filename="src\net\tmwa\specialhandler.h" />
+ <Unit filename="src\net\tmwa\token.h" />
+ <Unit filename="src\net\tmwa\tradehandler.cpp" />
+ <Unit filename="src\net\tmwa\tradehandler.h" />
<Unit filename="src\net\tradehandler.h" />
<Unit filename="src\net\worldinfo.h" />
- <Unit filename="src\npc.cpp" />
- <Unit filename="src\npc.h" />
<Unit filename="src\openglgraphics.cpp" />
<Unit filename="src\openglgraphics.h" />
<Unit filename="src\particle.cpp" />
@@ -500,8 +511,8 @@
<Unit filename="src\particleemitterprop.h" />
<Unit filename="src\party.cpp" />
<Unit filename="src\party.h" />
- <Unit filename="src\player.cpp" />
- <Unit filename="src\player.h" />
+ <Unit filename="src\playerinfo.cpp" />
+ <Unit filename="src\playerinfo.h" />
<Unit filename="src\playerrelations.cpp" />
<Unit filename="src\playerrelations.h" />
<Unit filename="src\position.cpp" />
@@ -515,6 +526,8 @@
<Unit filename="src\resources\ambientoverlay.h" />
<Unit filename="src\resources\animation.cpp" />
<Unit filename="src\resources\animation.h" />
+ <Unit filename="src\resources\beinginfo.cpp" />
+ <Unit filename="src\resources\beinginfo.h" />
<Unit filename="src\resources\colordb.cpp" />
<Unit filename="src\resources\colordb.h" />
<Unit filename="src\resources\dye.cpp" />
@@ -537,8 +550,6 @@
<Unit filename="src\resources\mapreader.h" />
<Unit filename="src\resources\monsterdb.cpp" />
<Unit filename="src\resources\monsterdb.h" />
- <Unit filename="src\resources\monsterinfo.cpp" />
- <Unit filename="src\resources\monsterinfo.h" />
<Unit filename="src\resources\music.cpp" />
<Unit filename="src\resources\music.h" />
<Unit filename="src\resources\npcdb.cpp" />
@@ -549,6 +560,8 @@
<Unit filename="src\resources\resourcemanager.h" />
<Unit filename="src\resources\soundeffect.cpp" />
<Unit filename="src\resources\soundeffect.h" />
+ <Unit filename="src\resources\specialdb.cpp" />
+ <Unit filename="src\resources\specialdb.h" />
<Unit filename="src\resources\spritedef.cpp" />
<Unit filename="src\resources\spritedef.h" />
<Unit filename="src\resources\wallpaper.cpp" />
@@ -592,6 +605,7 @@
<Unit filename="src\utils\stringutils.h" />
<Unit filename="src\utils\xml.cpp" />
<Unit filename="src\utils\xml.h" />
+ <Unit filename="src\variabledata.h" />
<Unit filename="src\vector.cpp" />
<Unit filename="src\vector.h" />
<Unit filename="src\winver.h" />
diff --git a/mana.files b/mana.files
index 1a6026f3..42b79487 100644
--- a/mana.files
+++ b/mana.files
@@ -12,6 +12,9 @@
./data/graphics/images/CMakeLists.txt
./data/graphics/images/Makefile.am
./data/graphics/Makefile.am
+./data/graphics/sprites/CMakeLists.txt
+./data/graphics/sprites/error.xml
+./data/graphics/sprites/Makefile.am
./data/help/about.txt
./data/help/changes.txt
./data/help/CMakeLists.txt
@@ -38,6 +41,13 @@
./Makefile.am
./packaging/windows/readme.txt
./po/CMakeLists.txt
+./src/actor.cpp
+./src/actor.h
+./src/actorsprite.cpp
+./src/actorsprite.h
+./src/actorspritelistener.h
+./src/actorspritemanager.cpp
+./src/actorspritemanager.h
./src/animatedsprite.cpp
./src/animatedsprite.h
./src/animationparticle.cpp
@@ -46,17 +56,19 @@
./src/avatar.h
./src/being.cpp
./src/being.h
-./src/beingmanager.cpp
-./src/beingmanager.h
./src/channel.cpp
./src/channel.h
./src/channelmanager.cpp
./src/channelmanager.h
+./src/chatlog.cpp
+./src/chatlog.h
./src/client.cpp
./src/client.h
./src/CMakeLists.txt
./src/commandhandler.cpp
./src/commandhandler.h
+./src/compoundsprite.cpp
+./src/compoundsprite.h
./src/configlistener.h
./src/configuration.cpp
./src/configuration.h
@@ -65,10 +77,12 @@
./src/emoteshortcut.cpp
./src/emoteshortcut.h
./src/equipment.h
+./src/event.cpp
+./src/event.h
+./src/eventmanager.cpp
+./src/eventmanager.h
./src/flooritem.cpp
./src/flooritem.h
-./src/flooritemmanager.cpp
-./src/flooritemmanager.h
./src/game.cpp
./src/game.h
./src/graphics.cpp
@@ -283,6 +297,8 @@
./src/gui/worldselectdialog.h
./src/imageparticle.cpp
./src/imageparticle.h
+./src/imagesprite.cpp
+./src/imagesprite.h
./src/inventory.cpp
./src/inventory.h
./src/item.cpp
@@ -293,6 +309,8 @@
./src/joystick.h
./src/keyboardconfig.cpp
./src/keyboardconfig.h
+./src/listener.cpp
+./src/listener.h
./src/localplayer.cpp
./src/localplayer.h
./src/log.cpp
@@ -302,60 +320,12 @@
./src/Makefile.am
./src/map.cpp
./src/map.h
-./src/monster.cpp
-./src/monster.h
./src/net/adminhandler.h
./src/net/charhandler.cpp
./src/net/charhandler.h
./src/net/chathandler.h
./src/net/download.cpp
./src/net/download.h
-./src/net/tmwa/adminhandler.cpp
-./src/net/tmwa/adminhandler.h
-./src/net/tmwa/beinghandler.cpp
-./src/net/tmwa/beinghandler.h
-./src/net/tmwa/buysellhandler.cpp
-./src/net/tmwa/buysellhandler.h
-./src/net/tmwa/charserverhandler.cpp
-./src/net/tmwa/charserverhandler.h
-./src/net/tmwa/chathandler.cpp
-./src/net/tmwa/chathandler.h
-./src/net/tmwa/gamehandler.cpp
-./src/net/tmwa/gamehandler.h
-./src/net/tmwa/generalhandler.cpp
-./src/net/tmwa/generalhandler.h
-./src/net/tmwa/gui/guildtab.cpp
-./src/net/tmwa/gui/guildtab.h
-./src/net/tmwa/guildhandler.cpp
-./src/net/tmwa/guildhandler.h
-./src/net/tmwa/gui/partytab.cpp
-./src/net/tmwa/gui/partytab.h
-./src/net/tmwa/inventoryhandler.cpp
-./src/net/tmwa/inventoryhandler.h
-./src/net/tmwa/itemhandler.cpp
-./src/net/tmwa/itemhandler.h
-./src/net/tmwa/loginhandler.cpp
-./src/net/tmwa/loginhandler.h
-./src/net/tmwa/messagehandler.cpp
-./src/net/tmwa/messagehandler.h
-./src/net/tmwa/messagein.cpp
-./src/net/tmwa/messagein.h
-./src/net/tmwa/messageout.cpp
-./src/net/tmwa/messageout.h
-./src/net/tmwa/network.cpp
-./src/net/tmwa/network.h
-./src/net/tmwa/npchandler.cpp
-./src/net/tmwa/npchandler.h
-./src/net/tmwa/partyhandler.cpp
-./src/net/tmwa/partyhandler.h
-./src/net/tmwa/playerhandler.cpp
-./src/net/tmwa/playerhandler.h
-./src/net/tmwa/protocol.h
-./src/net/tmwa/specialhandler.cpp
-./src/net/tmwa/specialhandler.h
-./src/net/tmwa/token.h
-./src/net/tmwa/tradehandler.cpp
-./src/net/tmwa/tradehandler.h
./src/net/gamehandler.h
./src/net/generalhandler.h
./src/net/guildhandler.h
@@ -374,6 +344,7 @@
./src/net/manaserv/chathandler.h
./src/net/manaserv/connection.cpp
./src/net/manaserv/connection.h
+./src/net/manaserv/defines.h
./src/net/manaserv/effecthandler.cpp
./src/net/manaserv/effecthandler.h
./src/net/manaserv/gamehandler.cpp
@@ -423,10 +394,54 @@
./src/net/playerhandler.h
./src/net/serverinfo.h
./src/net/specialhandler.h
+./src/net/tmwa/adminhandler.cpp
+./src/net/tmwa/adminhandler.h
+./src/net/tmwa/beinghandler.cpp
+./src/net/tmwa/beinghandler.h
+./src/net/tmwa/buysellhandler.cpp
+./src/net/tmwa/buysellhandler.h
+./src/net/tmwa/charserverhandler.cpp
+./src/net/tmwa/charserverhandler.h
+./src/net/tmwa/chathandler.cpp
+./src/net/tmwa/chathandler.h
+./src/net/tmwa/gamehandler.cpp
+./src/net/tmwa/gamehandler.h
+./src/net/tmwa/generalhandler.cpp
+./src/net/tmwa/generalhandler.h
+./src/net/tmwa/gui/guildtab.cpp
+./src/net/tmwa/gui/guildtab.h
+./src/net/tmwa/guildhandler.cpp
+./src/net/tmwa/guildhandler.h
+./src/net/tmwa/gui/partytab.cpp
+./src/net/tmwa/gui/partytab.h
+./src/net/tmwa/inventoryhandler.cpp
+./src/net/tmwa/inventoryhandler.h
+./src/net/tmwa/itemhandler.cpp
+./src/net/tmwa/itemhandler.h
+./src/net/tmwa/loginhandler.cpp
+./src/net/tmwa/loginhandler.h
+./src/net/tmwa/messagehandler.cpp
+./src/net/tmwa/messagehandler.h
+./src/net/tmwa/messagein.cpp
+./src/net/tmwa/messagein.h
+./src/net/tmwa/messageout.cpp
+./src/net/tmwa/messageout.h
+./src/net/tmwa/network.cpp
+./src/net/tmwa/network.h
+./src/net/tmwa/npchandler.cpp
+./src/net/tmwa/npchandler.h
+./src/net/tmwa/partyhandler.cpp
+./src/net/tmwa/partyhandler.h
+./src/net/tmwa/playerhandler.cpp
+./src/net/tmwa/playerhandler.h
+./src/net/tmwa/protocol.h
+./src/net/tmwa/specialhandler.cpp
+./src/net/tmwa/specialhandler.h
+./src/net/tmwa/token.h
+./src/net/tmwa/tradehandler.cpp
+./src/net/tmwa/tradehandler.h
./src/net/tradehandler.h
./src/net/worldinfo.h
-./src/npc.cpp
-./src/npc.h
./src/openglgraphics.cpp
./src/openglgraphics.h
./src/particlecontainer.cpp
@@ -438,8 +453,8 @@
./src/particle.h
./src/party.cpp
./src/party.h
-./src/player.cpp
-./src/player.h
+./src/playerinfo.cpp
+./src/playerinfo.h
./src/playerrelations.cpp
./src/playerrelations.h
./src/position.cpp
@@ -453,6 +468,8 @@
./src/resources/ambientoverlay.h
./src/resources/animation.cpp
./src/resources/animation.h
+./src/resources/beinginfo.cpp
+./src/resources/beinginfo.h
./src/resources/colordb.cpp
./src/resources/colordb.h
./src/resources/dye.cpp
@@ -475,8 +492,6 @@
./src/resources/mapreader.h
./src/resources/monsterdb.cpp
./src/resources/monsterdb.h
-./src/resources/monsterinfo.cpp
-./src/resources/monsterinfo.h
./src/resources/music.cpp
./src/resources/music.h
./src/resources/npcdb.cpp
@@ -487,6 +502,8 @@
./src/resources/resourcemanager.h
./src/resources/soundeffect.cpp
./src/resources/soundeffect.h
+./src/resources/specialdb.cpp
+./src/resources/specialdb.h
./src/resources/spritedef.cpp
./src/resources/spritedef.h
./src/resources/wallpaper.cpp
@@ -531,9 +548,12 @@
./src/utils/stringutils.h
./src/utils/xml.cpp
./src/utils/xml.h
+./src/variabledata.h
./src/vector.cpp
./src/vector.h
./src/winver.h
+./tools/dyecmd/CMakeLists.txt
+./tools/dyecmd/src/CMakeLists.txt
./tools/dyecmd/src/dyecmd.cpp
./tools/dyecmd/src/dye.cpp
./tools/dyecmd/src/dye.h
diff --git a/packaging/windows/setup.nsi b/packaging/windows/setup.nsi
index 9c620f35..1b5dc97c 100644
--- a/packaging/windows/setup.nsi
+++ b/packaging/windows/setup.nsi
@@ -203,6 +203,8 @@ Section "Core files (required)" SecCore
File "${SRCDIR}\README"
SetOutPath "$INSTDIR\data\fonts"
File "${SRCDIR}\data\fonts\*.ttf"
+ SetOutPath "$INSTDIR\data\graphics"
+ File "${SRCDIR}\data\graphics\*.png"
SetOutPath "$INSTDIR\data\graphics\gui"
File "${SRCDIR}\data\graphics\gui\*.png"
File "${SRCDIR}\data\graphics\gui\*.xml"
diff --git a/po/de.po b/po/de.po
index db9b2351..94b04e40 100644
--- a/po/de.po
+++ b/po/de.po
@@ -1,10 +1,12 @@
# German translation of The Mana World.
-# Copyright (C) 2007 The Mana World Development Team
+# Copyright (C) 2007-2009 The Mana World Development Team
+# Copyright (C) 2010 The Mana Development Team
# This file is distributed under the same license as the The Mana World package.
#
# Matthias Hartmann <hartmann.matthias@gmail.com>, 2007.
# Jonathan Raphael Joachim Kolberg, 2009, 2010.
# seeseekey <seeseekey@googlemail.com>, 2009.
+# Andrej, 2009.
msgid ""
msgstr ""
"Project-Id-Version: The Mana World 0.1.0\n"
@@ -192,7 +194,7 @@ msgstr ""
#: src/commandhandler.cpp:184
msgid "/announce > Global announcement (GM only)"
-msgstr "/announce > Globale Ansage (Nur von GM's nutzbar)"
+msgstr "/announce > Globale Ansage (Nur von GMs nutzbar)"
#: src/commandhandler.cpp:188
msgid "For more information, type /help <command>."
@@ -597,7 +599,7 @@ msgstr "Abbrechen"
#: src/gui/changeemaildialog.cpp:45 src/gui/changeemaildialog.cpp:54
msgid "Change Email Address"
-msgstr "Email-Adresse ändern"
+msgstr "E-MailAdresse ändern"
#: src/gui/changeemaildialog.cpp:49 src/gui/changepassworddialog.cpp:52
#, c-format
@@ -661,7 +663,7 @@ msgstr "Charakter erstellen"
#: src/gui/charcreatedialog.cpp:67 src/gui/login.cpp:52
#: src/gui/register.cpp:67
msgid "Name:"
-msgstr "Name :"
+msgstr "Name:"
#. TRANSLATORS: This is a narrow symbol used to denote 'next'.
#. You may change this symbol if your language uses another.
@@ -722,7 +724,7 @@ msgstr "Bestätige Charakter-Löschung"
#: src/gui/charselectdialog.cpp:70
msgid "Are you sure you want to delete this character?"
-msgstr "Bist du sicher, dass du diesen Charakter löschen möchtest?"
+msgstr "Bist Du sicher, dass du diesen Charakter löschen möchtest?"
#: src/gui/charselectdialog.cpp:117
msgid "Account and Character Management"
@@ -906,11 +908,11 @@ msgstr "Wähle aus, wie viele Gegenstände Du wegwerfen möchtest."
#: src/gui/itemamount.cpp:134
msgid "Select amount of items to store."
-msgstr "Wähle aus, wie viele Gegenstände du einlagern möchtest."
+msgstr "Wähle aus, wie viele Gegenstände Du einlagern möchtest."
#: src/gui/itemamount.cpp:137
msgid "Select amount of items to retrieve."
-msgstr "Wähle aus, wie viele Gegenstände du wieder haben möchtest."
+msgstr "Wähle aus, wie viele Gegenstände Du wieder haben möchtest."
#: src/gui/itemamount.cpp:140
msgid "Select amount of items to split."
@@ -1138,7 +1140,7 @@ msgstr "Der Nutzername muss kürzer als %d Zeichen sein."
#: src/gui/register.cpp:182 src/gui/unregisterdialog.cpp:117
#, c-format
msgid "The password needs to be at least %d characters long."
-msgstr "Das Passwort muss aus mindestens %d bestehen."
+msgstr "Das Passwort muss aus mindestens %d Zeichen bestehen."
#: src/gui/register.cpp:190 src/gui/unregisterdialog.cpp:124
#, c-format
@@ -1177,7 +1179,7 @@ msgstr "Benutzerdefinierter Zeiger"
#: src/gui/serverdialog.cpp:242
msgid "Please type both the address and the port of a server."
-msgstr "Bitte die Adresse und den Port eines Servers eingeben"
+msgstr "Bitte die Adresse und den Port eines Servers eingeben."
#: src/gui/serverdialog.cpp:357
#, c-format
@@ -1284,7 +1286,7 @@ msgstr "Fenster zurücksetzen"
#: src/gui/setup_joystick.cpp:37 src/gui/setup_joystick.cpp:78
msgid "Press the button to start calibration"
-msgstr "Knopf drücken um die Kalibrierung zu starten"
+msgstr "Knopf drücken, um die Kalibrierung zu starten"
#: src/gui/setup_joystick.cpp:38 src/gui/setup_joystick.cpp:76
msgid "Calibrate"
@@ -1431,7 +1433,7 @@ msgstr "Mittel"
#: src/gui/setup_video.cpp:174
msgid "max"
-msgstr "max"
+msgstr "Maximal"
#: src/gui/setup_video.cpp:196
msgid "Full screen"
@@ -1492,7 +1494,7 @@ msgstr "Chat über Spielern"
#: src/gui/setup_video.cpp:234
msgid "Gui opacity"
-msgstr "GUI Transparenz"
+msgstr "GUI-Transparenz"
#: src/gui/setup_video.cpp:235
msgid "Ambient FX"
@@ -1517,13 +1519,13 @@ msgstr "Nein"
#, fuzzy
msgid ""
"Failed to switch to windowed mode and restoration of old mode also failed!"
-msgstr "und Wiederherstellung der alten Auflösung schlug fehl!"
+msgstr "Auflösung und Wiederherstellung der alten Auflösung schlug fehl!"
#: src/gui/setup_video.cpp:387
#, fuzzy
msgid ""
"Failed to switch to fullscreen mode and restoration of old mode also failed!"
-msgstr "und Wiederherstellung der alten Auflösung schlug fehl!"
+msgstr "Auflösung und Wiederherstellung der alten Auflösung schlug fehl!"
#: src/gui/setup_video.cpp:398
#, fuzzy
@@ -1731,7 +1733,7 @@ msgstr "Anfrage für eine Party erhalten, aber du bist bereits in einer Party."
#: src/gui/socialwindow.cpp:503
#, c-format
msgid "%s has invited you to join the guild %s."
-msgstr "%s hat dich eingeladen, seiner Gilde %s beizutreten."
+msgstr "%s hat Dich eingeladen, seiner Gilde %s beizutreten."
#: src/gui/socialwindow.cpp:508
msgid "Accept Guild Invite"
@@ -1818,11 +1820,11 @@ msgstr "MP:"
#: src/gui/statuswindow.cpp:132 src/gui/statuswindow.cpp:219
#, c-format
msgid "Job: %d"
-msgstr "Job: %d"
+msgstr "Beruf: %d"
#: src/gui/statuswindow.cpp:133
msgid "Job:"
-msgstr "Job:"
+msgstr "Beruf:"
#: src/gui/statuswindow.cpp:194
#, fuzzy
@@ -1957,7 +1959,7 @@ msgstr "Fertig"
#: src/gui/widgets/channeltab.cpp:49
msgid "/users > Lists the users in the current channel"
-msgstr "/users > Zeigt eine Liste der Spiele im aktuellen Kanal"
+msgstr "/users > Zeigt eine Liste der Spieler im aktuellen Kanal"
#: src/gui/widgets/channeltab.cpp:50
msgid "/topic > Set the topic of the current channel"
@@ -1969,7 +1971,7 @@ msgstr "/quit > Verlasse einen Kanal"
#: src/gui/widgets/channeltab.cpp:52
msgid "/op > Make a user a channel operator"
-msgstr "/op > Ernenne einen Spieler zum Kanalwärter"
+msgstr "/op > Ernenne einen Spieler zum Kanalmoderator"
#: src/gui/widgets/channeltab.cpp:53
msgid "/kick > Kick a user from the channel"
@@ -1981,7 +1983,7 @@ msgstr "Befehl: /users"
#: src/gui/widgets/channeltab.cpp:64
msgid "This command shows the users in this channel."
-msgstr "Dieser Befehl zeit eine Liste der Spieler im aktuellen Kanal."
+msgstr "Dieser Befehl zeigt eine Liste der Spieler im aktuellen Kanal."
#: src/gui/widgets/channeltab.cpp:68
msgid "Command: /topic <message>"
@@ -2015,7 +2017,7 @@ msgstr "Dieser Befehl macht Spieler <Name> zu einem Moderator des Kanals"
msgid "Channel operators can kick and op other users from the channel."
msgstr ""
"Moderatoren können andere Spieler aus dem Kanal werfen oder ihnen ebenfalls "
-"Moderator-Rechte verleihen."
+"Moderatorrechte verleihen."
#: src/gui/widgets/channeltab.cpp:89
msgid "Command: /kick <nick>"
@@ -2307,7 +2309,7 @@ msgstr "Bitte beheben, oder es wird zu merkwürdigem Verhalten im Spiel kommen."
#: src/localplayer.cpp:914
msgid "Unable to pick up item."
-msgstr "Kann das nicht aufheben."
+msgstr "Kann Gegenstand nicht aufheben."
#. TRANSLATORS: This sentence may be translated differently
#. for different grammatical numbers (singular, plural, ...)
@@ -2328,53 +2330,53 @@ msgstr "Optionen:"
#: src/main.cpp:45
msgid " -v --version : Display the version"
-msgstr " -v --version : Die Version des Spieles anzeigen"
+msgstr " -v --version : Die Version des Spieles anzeigen"
#: src/main.cpp:46
msgid " -h --help : Display this help"
-msgstr " - --help : Zeigt diesen Hilfstext an"
+msgstr " - --help : Zeigt diesen Hilfstext an"
#: src/main.cpp:47
#, fuzzy
msgid " -C --config-dir : Configuration directory to use"
-msgstr " -C --config-file : zu benutzende Konfigurationsdatei"
+msgstr " -C --config-file : zu benutzende Konfigurationsdatei"
#: src/main.cpp:48
msgid " -U --username : Login with this username"
-msgstr " -U --username : Mit angegebenem Benutzernamen anmelden"
+msgstr " -U --username : Mit angegebenem Benutzernamen anmelden"
#: src/main.cpp:49
msgid " -P --password : Login with this password"
-msgstr " -P --password : Angegebenes Passwort benutzen"
+msgstr " -P --password : Angegebenes Passwort benutzen"
#: src/main.cpp:50
msgid " -c --character : Login with this character"
-msgstr " -c --charakter : Mit angegebenem Spieler anmelden"
+msgstr " -c --charakter : Mit angegebenem Spieler anmelden"
#: src/main.cpp:51
msgid " -s --server : Login server name or IP"
-msgstr " -s --server : Name oder IP-Adresse des Loginservers"
+msgstr " -s --server : Name oder IP-Adresse des Loginservers"
#: src/main.cpp:52
msgid " -p --port : Login server port"
-msgstr " -p --port : Port des Loginservers"
+msgstr " -p --port : Port des Loginservers"
#: src/main.cpp:53
#, fuzzy
msgid " --update-host : Use this update host"
-msgstr " -H --update-host : Benutze angegebenen Updateserver"
+msgstr " -H --update-host : Benutze angegebenen Updateserver"
#: src/main.cpp:54
msgid " -D --default : Choose default character server and character"
-msgstr " -D --default : Wähle zuletzt benutzten Server und Spieler aus"
+msgstr " -D --default : Wähle zuletzt benutzten Server und Spieler aus"
#: src/main.cpp:56
msgid " -u --skip-update : Skip the update downloads"
-msgstr " -u --skip-update : Ãœberspringe das Herunterladen von Updates"
+msgstr " -u --skip-update : Ãœberspringe das Herunterladen von Updates"
#: src/main.cpp:57
msgid " -d --data : Directory to load game data from"
-msgstr " -d --data : Datenverzeichnis, aus dem das Spiel geladen werden soll"
+msgstr " -d --data : Datenverzeichnis, aus dem das Spiel geladen werden soll"
#: src/main.cpp:58
#, fuzzy
@@ -2391,7 +2393,7 @@ msgstr ""
#: src/main.cpp:61
#, fuzzy
msgid " --no-opengl : Disable OpenGL for this session"
-msgstr " -O --no-opengl : OpenGL-Erweiterungen deaktivieren"
+msgstr " -O --no-opengl : OpenGL-Erweiterungen deaktivieren"
#: src/net/ea/adminhandler.cpp:63
msgid "Kick failed!"
@@ -2541,7 +2543,7 @@ msgstr "Glück %+d"
#: src/net/ea/generalhandler.cpp:130
msgid "Authentication failed."
-msgstr "Authentifizierung verweigert"
+msgstr "Authentifizierung fehlgeschlagen"
#: src/net/ea/generalhandler.cpp:133
msgid "No servers available."
@@ -2821,7 +2823,7 @@ msgstr "Gegenstand konnte nicht benutzt werden."
#: src/net/ea/inventoryhandler.cpp:391
msgid "Unable to equip."
-msgstr "Kann Gegenstand nicht Ausrüsten."
+msgstr "Kann Gegenstand nicht ausrüsten."
#: src/net/ea/inventoryhandler.cpp:402
msgid "Unable to unequip."
@@ -2866,7 +2868,7 @@ msgstr "Vom Server zurückgewiesen"
msgid ""
"You have been permanently banned from the game. Please contact the GM team."
msgstr ""
-"Du wurdest permanent vom Spiel ausgeschlossen. Bitte wende Dich an das GM "
+"Du wurdest permanent vom Spiel ausgeschlossen. Bitte wende Dich an das GM-"
"Team."
#: src/net/ea/loginhandler.cpp:165
@@ -2876,7 +2878,7 @@ msgid ""
"Please contact the GM team via the forums."
msgstr ""
"Du wurdest zeitweise, bis %s vom Spiel ausgeschlossen.\n"
-"Bitte wende dich mittels des Forums an das GM Team."
+"Bitte wende dich mittels des Forums an das GM-Team."
#: src/net/ea/loginhandler.cpp:172
msgid "This user name is already taken."
@@ -2964,7 +2966,7 @@ msgstr "Du bist nicht länger lebendig."
#: src/net/ea/playerhandler.cpp:103 src/net/manaserv/beinghandler.cpp:308
msgid "The cold hands of the grim reaper are grabbing for your soul."
-msgstr "Die kalten Hände des Sensemanns greifen nach Deiner Seele."
+msgstr "Die kalten Hände des Sensenmanns greifen nach Deiner Seele."
#: src/net/ea/playerhandler.cpp:104 src/net/manaserv/beinghandler.cpp:309
msgid "Game Over!"
@@ -3014,7 +3016,7 @@ msgstr "Sieht aus, als würde Dein Kopf Dich anschauen."
msgid ""
"You screwed up again, dump your body down the tubes and get you another one."
msgstr ""
-"Du hast schon wieder versagt. Spül Deine Überreste hinunter und hol Dir ein "
+"Du hast schon wieder versagt. Spül Deine Überreste hinunter und hol Dir einen "
"paar Neue."
#: src/net/ea/playerhandler.cpp:123
@@ -3105,7 +3107,7 @@ msgstr "Handel fehlgeschlagen!"
#: src/net/ea/specialhandler.cpp:150
msgid "Emote failed!"
-msgstr "Emote fehlgeschlagen!"
+msgstr "Gefühl fehlgeschlagen!"
#: src/net/ea/specialhandler.cpp:153
msgid "Sit failed!"
@@ -3161,11 +3163,11 @@ msgstr "Du brauchst noch einen blauen Edelstein!"
#: src/net/ea/specialhandler.cpp:198
msgid "You're carrying to much to do this!"
-msgstr "Du schleppst zu viel herum um das zu machen!"
+msgstr "Du schleppst zu viel herum, um das zu machen!"
#: src/net/ea/specialhandler.cpp:201
msgid "Huh? What's that?"
-msgstr "Eha? Was ist das?"
+msgstr "Huch? Was ist das?"
#: src/net/ea/specialhandler.cpp:210
msgid "Warp failed..."
@@ -3186,7 +3188,7 @@ msgstr "Erbitte einen Handel"
#: src/net/ea/tradehandler.cpp:108 src/net/manaserv/tradehandler.cpp:117
#, c-format
msgid "%s wants to trade with you, do you accept?"
-msgstr "%s möchte mit dir handeln, stimmst du zu?"
+msgstr "%s möchte mit dir handeln, stimmst Du zu?"
#: src/net/ea/tradehandler.cpp:124
msgid "Trading isn't possible. Trade partner is too far away."
@@ -3377,7 +3379,7 @@ msgstr "Einladung gesendet."
#: src/net/manaserv/guildhandler.cpp:203
msgid "Member was promoted successfully."
-msgstr "Mitglied wurde erfolgreich Befördert."
+msgstr "Mitglied wurde erfolgreich befördert."
#: src/net/manaserv/guildhandler.cpp:208
msgid "Failed to promote member."
@@ -3660,16 +3662,16 @@ msgstr "unbenannt"
#~ msgstr "Verfehlt"
#~ msgid "HP Bar"
-#~ msgstr "HP Leiste"
+#~ msgstr "HP-Leiste"
#~ msgid "3/4 HP Bar"
-#~ msgstr "3/4 HP Leiste"
+#~ msgstr "3/4 HP-Leiste"
#~ msgid "1/2 HP Bar"
-#~ msgstr "1/2 HP Leiste"
+#~ msgstr "1/2 HP-Leiste"
#~ msgid "1/4 HP Bar"
-#~ msgstr "1/4 HP Leiste"
+#~ msgstr "1/4 HP-Leiste"
#~ msgid "help"
#~ msgstr "Hilfe"
@@ -4723,7 +4725,7 @@ msgstr "unbenannt"
#~ msgstr "Freundesliste"
#~ msgid "Job Level: %d"
-#~ msgstr "Beruf Stufe: %d"
+#~ msgstr "Berufsstufe: %d"
#~ msgid "Ok"
#~ msgstr "Ok"
@@ -4741,7 +4743,7 @@ msgstr "unbenannt"
#~ msgstr "zweihändige Waffen"
#~ msgid "Failed to switch to "
-#~ msgstr "Konnte Auflösung nicht ändern in "
+#~ msgstr "Konnte Auflösung nicht ändern zu "
#~ msgid "Mystery Skill"
#~ msgstr "Unbekannter Skill"
@@ -4774,7 +4776,7 @@ msgstr "unbenannt"
#~ msgstr "Max Level"
#~ msgid "curl error "
-#~ msgstr "curl fehler "
+#~ msgstr "curl-Fehler "
#~ msgid "Buddys"
#~ msgstr "Freunde"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b15948d3..ca6dddb2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -348,6 +348,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
@@ -370,8 +372,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
@@ -382,6 +382,8 @@ SET(SRCS
resources/resourcemanager.h
resources/soundeffect.h
resources/soundeffect.cpp
+ resources/specialdb.cpp
+ resources/specialdb.h
resources/spritedef.h
resources/spritedef.cpp
resources/wallpaper.cpp
@@ -402,6 +404,13 @@ SET(SRCS
utils/mkdir.h
utils/xml.cpp
utils/xml.h
+ actor.cpp
+ actor.h
+ actorsprite.cpp
+ actorsprite.h
+ actorspritelistener.h
+ actorspritemanager.cpp
+ actorspritemanager.h
animatedsprite.cpp
animatedsprite.h
animationparticle.cpp
@@ -410,8 +419,8 @@ SET(SRCS
avatar.h
being.cpp
being.h
- beingmanager.cpp
- beingmanager.h
+ chatlog.cpp
+ chatlog.h
client.cpp
client.h
channel.cpp
@@ -420,6 +429,8 @@ SET(SRCS
channelmanager.h
commandhandler.cpp
commandhandler.h
+ compoundsprite.cpp
+ compoundsprite.h
configlistener.h
configuration.cpp
configuration.h
@@ -428,10 +439,12 @@ SET(SRCS
emoteshortcut.cpp
emoteshortcut.h
equipment.h
+ event.cpp
+ event.h
+ eventmanager.cpp
+ eventmanager.h
flooritem.cpp
flooritem.h
- flooritemmanager.cpp
- flooritemmanager.h
game.cpp
game.h
graphics.cpp
@@ -441,6 +454,8 @@ SET(SRCS
guild.h
imageparticle.cpp
imageparticle.h
+ imagesprite.cpp
+ imagesprite.h
inventory.cpp
inventory.h
item.cpp
@@ -451,6 +466,8 @@ SET(SRCS
joystick.h
keyboardconfig.cpp
keyboardconfig.h
+ listener.cpp
+ listener.h
localplayer.cpp
localplayer.h
log.cpp
@@ -459,10 +476,6 @@ SET(SRCS
main.h
map.cpp
map.h
- monster.cpp
- monster.h
- npc.cpp
- npc.h
openglgraphics.cpp
openglgraphics.h
particle.cpp
@@ -474,8 +487,8 @@ SET(SRCS
particleemitterprop.h
party.cpp
party.h
- player.cpp
- player.h
+ playerinfo.cpp
+ playerinfo.h
playerrelations.cpp
playerrelations.h
position.cpp
@@ -502,6 +515,7 @@ SET(SRCS
tileset.h
units.cpp
units.h
+ variabledata.h
vector.cpp
vector.h
)
@@ -568,6 +582,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 d12a9a56..1ba073c3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -228,9 +228,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 +245,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 +269,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,6 +279,8 @@ 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/wallpaper.cpp \
@@ -301,6 +303,13 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
utils/mutex.h \
utils/xml.cpp \
utils/xml.h \
+ actor.cpp \
+ actor.h \
+ actorsprite.cpp \
+ actorsprite.h \
+ actorspritelistener.h \
+ actorspritemanager.cpp \
+ actorspritemanager.h \
animatedsprite.cpp \
animatedsprite.h \
animationparticle.cpp \
@@ -309,8 +318,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 \
@@ -319,6 +328,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
channelmanager.h \
commandhandler.cpp \
commandhandler.h \
+ compoundsprite.cpp \
+ compoundsprite.h \
configlistener.h \
configuration.cpp \
configuration.h \
@@ -327,10 +338,12 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
emoteshortcut.cpp \
emoteshortcut.h \
equipment.h \
+ event.cpp \
+ event.h \
+ eventmanager.cpp \
+ eventmanager.h \
flooritem.cpp \
flooritem.h \
- flooritemmanager.cpp \
- flooritemmanager.h \
game.cpp \
game.h \
graphics.cpp \
@@ -340,6 +353,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
guild.h \
imageparticle.cpp \
imageparticle.h \
+ imagesprite.cpp \
+ imagesprite.h \
inventory.cpp \
inventory.h \
item.cpp \
@@ -350,6 +365,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
joystick.h \
keyboardconfig.cpp \
keyboardconfig.h \
+ listener.cpp \
+ listener.h \
localplayer.cpp \
localplayer.h \
log.cpp \
@@ -358,10 +375,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 \
@@ -373,8 +386,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 \
@@ -401,6 +414,7 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
tileset.h \
units.cpp \
units.h \
+ variabledata.h \
vector.cpp \
vector.h \
winver.h
@@ -418,6 +432,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..6a1dcbc7
--- /dev/null
+++ b/src/actorsprite.cpp
@@ -0,0 +1,464 @@
+/*
+ * 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 "imagesprite.h"
+#include "localplayer.h"
+#include "log.h"
+#include "simpleanimation.h"
+#include "sound.h"
+#include "statuseffect.h"
+
+#include "gui/theme.h"
+
+#include "net/net.h"
+
+#include "resources/image.h"
+#include "resources/imageset.h"
+#include "resources/resourcemanager.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)
+{
+ handleStatusEffect(StatusEffect::getStatusEffect(oldMode, false), -1);
+ handleStatusEffect(StatusEffect::getStatusEffect(newMode, true), -1);
+}
+
+void ActorSprite::updateStatusEffect(int index, bool newStatus)
+{
+ 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..a6c82420
--- /dev/null
+++ b/src/actorspritemanager.cpp
@@ -0,0 +1,318 @@
+/*
+ * 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 "gui/viewport.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)
+ {
+ viewport->clearHover(*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..9ddc001c 100644
--- a/src/animatedsprite.cpp
+++ b/src/animatedsprite.cpp
@@ -41,11 +41,12 @@ 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();
@@ -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(SpriteAction 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);
}
+
+ // 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..67e9c7cb 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(SpriteAction 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..56c2c69a 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -21,104 +21,167 @@
#include "being.h"
+#include "actorspritemanager.h"
#include "animatedsprite.h"
#include "client.h"
#include "configuration.h"
#include "effectmanager.h"
#include "graphics.h"
+#include "guild.h"
#include "localplayer.h"
#include "log.h"
#include "map.h"
#include "particle.h"
+#include "party.h"
#include "simpleanimation.h"
#include "sound.h"
+#include "sprite.h"
#include "text.h"
#include "statuseffect.h"
+#include "gui/buy.h"
+#include "gui/buysell.h"
#include "gui/gui.h"
+#include "gui/npcdialog.h"
+#include "gui/npcpostdialog.h"
+#include "gui/sell.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/npchandler.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 "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"
+#define PARTICLE_LOCATION "graphics/particles/"
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.getValue("visiblenames", 1);
+
+ config.addListener("visiblenames", this);
+
+ if (getType() == PLAYER || getType() == NPC)
+ setShowName(true);
+
+ updateColors();
}
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();
@@ -189,7 +252,7 @@ void Being::setPath(const Path &path)
mAction != WALK && mAction != DEAD)
{
nextTile();
- mWalkTime = tick_time;
+ mActionTime = tick_time;
}
}
@@ -292,6 +355,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 +375,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 +433,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);
+}
+
+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;
+}
+
+Guild *Being::getGuild(int id) const
+{
+ 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;
- // Clear particle effect list because child particles became invalid
- mChildParticleEffects.clear();
- mMustResetParticles = true; // Reset status particles on next redraw
+ if (this == player_node && socialWindow)
+ socialWindow->removeTab(guild);
+
+ guild->removeMember(mId);
+ }
+
+ mGuilds.clear();
}
-void Being::controlParticle(Particle *particle)
+void Being::setParty(Party *party)
{
- mChildParticleEffects.addLocally(particle);
+ 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)
@@ -416,13 +562,40 @@ void Being::setAction(Action action, int attackType)
break;
case ATTACK:
if (mEquippedWeapon)
+ {
currentAction = mEquippedWeapon->getAttackType();
+ 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
@@ -431,6 +604,7 @@ void Being::setAction(Action action, int attackType)
break;
case DEAD:
currentAction = ACTION_DEAD;
+ sound.playSfx(mInfo->getSound(SOUND_EVENT_DIE));
break;
case STAND:
currentAction = ACTION_STAND;
@@ -439,11 +613,12 @@ void Being::setAction(Action action, int attackType)
if (currentAction != ACTION_INVALID)
{
- for (SpriteIterator it = mSprites.begin(); it != mSprites.end(); it++)
- if (*it)
- (*it)->play(currentAction);
+ play(currentAction);
mAction = action;
}
+
+ if (currentAction != ACTION_WALK)
+ mActionTime = tick_time;
}
void Being::setDirection(Uint8 direction)
@@ -469,9 +644,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 */
@@ -507,7 +680,7 @@ void Being::nextTile()
mX = pos.x;
mY = pos.y;
setAction(WALK);
- mWalkTime += (int)(mWalkSpeed.x / 10);
+ mActionTime += (int)(mWalkSpeed.x / 10);
}
int Being::getCollisionRadius() const
@@ -607,6 +780,69 @@ void Being::logic()
}
else if (Net::getNetworkType() == ServerInfo::TMWATHENA)
{
+ int frameCount = getFrameCount();
+
+ switch (mAction)
+ {
+ case STAND:
+ case SIT:
+ case DEAD:
+ case HURT:
+ break;
+
+ case WALK:
+ 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,
+ PARTICLE_LOCATION).empty())
+ particleEffect = PARTICLE_LOCATION +
+ 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 +855,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);
}
}
@@ -751,67 +937,6 @@ 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
{
@@ -824,9 +949,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 +969,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.getValue("visiblenames", 1));
+ }
}
-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.getValue("showgender", false))
+ {
+ 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.getValue("showMonstersTakedDamage", false))
{
- 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("graphics/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()
@@ -1034,3 +1165,44 @@ 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()
+{
+ Net::getNpcHandler()->talk(mId);
+}
+
+bool Being::isTalking()
+{
+ return NpcDialog::isActive() || BuyDialog::isActive() ||
+ SellDialog::isActive() || BuySellDialog::isActive() ||
+ NpcPostDialog::isActive();
+}
diff --git a/src/being.h b/src/being.h
index 71b3e2cf..f06fd2bc 100644
--- a/src/being.h
+++ b/src/being.h
@@ -22,19 +22,18 @@
#ifndef BEING_H
#define BEING_H
+#include "actorsprite.h"
#include "configlistener.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 +44,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:
- 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
@@ -85,14 +80,6 @@ class Being : public Sprite, public ConfigListener
HURT
};
- enum TargetCursorSize
- {
- TC_SMALL = 0,
- TC_MEDIUM,
- TC_LARGE,
- NUM_TC
- };
-
enum Speech
{
NO_SPEECH = 0,
@@ -128,29 +115,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 +201,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 +223,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 +326,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 +375,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 +400,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 +412,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 +433,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 +459,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 +470,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();
+ static bool isTalking();
+
+ 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 +546,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 +568,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 +581,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..1c43b403
--- /dev/null
+++ b/src/chatlog.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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.getValue("MostUsedServerName0",
+ "server.themanaworld.org");
+
+ 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 ac10112e..b64f9a89 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 "eventmanager.h"
#include "game.h"
#include "itemshortcut.h"
#include "keyboardconfig.h"
@@ -69,6 +71,7 @@
#include "resources/image.h"
#include "resources/itemdb.h"
#include "resources/monsterdb.h"
+#include "resources/specialdb.h"
#include "resources/npcdb.h"
#include "resources/resourcemanager.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;
@@ -220,6 +224,12 @@ Client::Client(const Options &options):
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));
@@ -401,6 +411,9 @@ Client::Client(const Options &options):
branding.getValue("defaultServerType", "tmwathena"));
}
+ if (chatLogger)
+ chatLogger->setServerName(mCurrentServer.hostname);
+
if (loginData.username.empty() && loginData.remember)
loginData.username = config.getValue("username", "");
@@ -416,6 +429,9 @@ Client::Client(const Options &options):
SDL_initFramerate(&mFpsManager);
config.addListener("fpslimit", this);
optionChanged("fpslimit");
+
+ // Initialize PlayerInfo
+ PlayerInfo::init();
}
Client::~Client()
@@ -576,9 +592,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);
+ Mana::EventManager::trigger("Client", event);
+ }
if (mOldState == STATE_GAME)
{
@@ -736,11 +755,14 @@ int Client::exec()
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;
@@ -1151,7 +1173,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 +1181,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();
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..2567b3b4 100644
--- a/src/commandhandler.cpp
+++ b/src/commandhandler.cpp
@@ -389,7 +389,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..d1c6cd57
--- /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(SpriteAction 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..38c38453
--- /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(SpriteAction 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/event.cpp b/src/event.cpp
new file mode 100644
index 00000000..65fdee8a
--- /dev/null
+++ b/src/event.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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 "variabledata.h"
+
+namespace Mana
+{
+
+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();
+}
+
+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();
+}
+
+
+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();
+}
+
+} // namespace Mana
diff --git a/src/event.h b/src/event.h
new file mode 100644
index 00000000..03751739
--- /dev/null
+++ b/src/event.h
@@ -0,0 +1,74 @@
+/*
+ * 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>
+
+namespace Mana
+{
+
+// Possible exception that can be thrown
+enum BadEvent {
+ BAD_KEY,
+ BAD_VALUE,
+ KEY_ALREADY_EXISTS
+};
+
+class VariableData;
+typedef std::map<std::string, VariableData *> VariableMap;
+
+class Event
+{
+public:
+ // String passed can be retivered with getName()
+ // and is to used to identify what type of event
+ // this is.
+ Event(const std::string &name)
+ { mEventName = name; }
+
+ ~Event();
+
+ const std::string &getName() const
+ { return mEventName; }
+
+ // Sets or gets a interger with a key to identify
+ void setInt(const std::string &key, int value) throw (BadEvent);
+ int getInt(const std::string &key) const throw (BadEvent);
+
+ // Sets or gets a string with a key to identify
+ void setString(const std::string &key, const std::string &value) throw (BadEvent);
+ const std::string &getString(const std::string &key) const throw (BadEvent);
+
+ // Sets or gets a floating point number with key to identify
+ void setFloat(const std::string &key, double value) throw (BadEvent);
+ double getFloat(const std::string &key) const throw (BadEvent);
+
+private:
+ std::string mEventName;
+
+ VariableMap mData;
+};
+
+} // namespace Mana
+
+#endif
diff --git a/src/eventmanager.cpp b/src/eventmanager.cpp
new file mode 100644
index 00000000..86b61781
--- /dev/null
+++ b/src/eventmanager.cpp
@@ -0,0 +1,67 @@
+/*
+ * 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 "eventmanager.h"
+
+#include "listener.h"
+
+namespace Mana
+{
+
+ListenMap EventManager::mBindings;
+
+void EventManager::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 EventManager::remove(Listener *listener)
+{
+ ListenMap::iterator it = mBindings.begin();
+ while (it != mBindings.end())
+ {
+ it->second.erase(listener);
+ it++;
+ }
+}
+
+void EventManager::bind(Listener *listener, const std::string &channel)
+{
+ mBindings[channel].insert(listener);
+}
+
+void EventManager::unbind(Listener *listener, const std::string &channel)
+{
+ mBindings[channel].erase(listener);
+}
+
+} // namespace Mana
diff --git a/src/eventmanager.h b/src/eventmanager.h
new file mode 100644
index 00000000..ac6c997c
--- /dev/null
+++ b/src/eventmanager.h
@@ -0,0 +1,62 @@
+/*
+ * 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 EVENTMANAGER_H
+#define EVENTMANAGER_H
+
+#include "event.h"
+
+#include <string>
+#include <map>
+#include <set>
+
+#define SERVER_NOTICE(message) { \
+Mana::Event event("ServerNotice"); \
+event.setString("message", message); \
+Mana::EventManager::trigger("Notices", event); }
+
+namespace Mana
+{
+
+class Listener;
+
+typedef std::set<Listener *> ListenerSet;
+typedef std::map<std::string, ListenerSet > ListenMap;
+
+class EventManager
+{
+public:
+ // Sends event to all listener on the channel
+ static void trigger(const std::string &channel, const Event &event);
+
+ // Removes a listener from all channels
+ static void remove(Listener *listener);
+
+ // Adds or removes a listener to a channel.
+ static void bind(Listener *listener, const std::string &channel);
+ static void unbind(Listener *listener, const std::string &channel);
+
+private:
+ static ListenMap mBindings;
+};
+
+} // 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..3aa093a6 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 "eventmanager.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::EventManager::trigger("Game", Mana::Event("EnginesInitalizing"));
+
+ actorSpriteManager = new ActorSpriteManager;
commandHandler = new CommandHandler;
- floorItemManager = new FloorItemManager;
channelManager = new ChannelManager;
effectManager = new EffectManager;
particleEngine = new Particle(NULL);
particleEngine->setupEngine();
+
+ Mana::EventManager::trigger("Game", Mana::Event("EnginesInitalized"));
}
/**
@@ -145,15 +147,17 @@ static void initEngines()
*/
static void createGuiWindows()
{
+ Mana::EventManager::trigger("Game", Mana::Event("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,7 @@ static void createGuiWindows()
logger->setChatWindow(chatWindow);
}
- Net::getGeneralHandler()->guiWindowsLoaded();
+ Mana::EventManager::trigger("Game", Mana::Event("GuiWindowsLoaded"));
}
#define del_0(X) { delete X; X = 0; }
@@ -183,7 +187,8 @@ static void createGuiWindows()
*/
static void destroyGuiWindows()
{
- Net::getGeneralHandler()->guiWindowsUnloaded();
+ Mana::EventManager::trigger("Game", Mana::Event("GuiWindowsUnloading"));
+
logger->setChatWindow(NULL);
del_0(localChatTab) // Need to do this first, so it can remove itself
del_0(chatWindow)
@@ -201,12 +206,14 @@ static void destroyGuiWindows()
del_0(outfitWindow)
del_0(specialsWindow)
del_0(socialWindow)
+
+ Mana::EventManager::trigger("Game", Mana::Event("GuiWindowsUnloaded"));
}
Game *Game::mInstance = 0;
Game::Game():
- mLastTarget(Being::UNKNOWN),
+ mLastTarget(ActorSprite::UNKNOWN),
mCurrentMap(0), mMapName("")
{
assert(!mInstance);
@@ -230,10 +237,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 +258,8 @@ Game::Game():
joystick = new Joystick(0);
setupWindow->setInGame(true);
+
+ Mana::EventManager::trigger("Game", Mana::Event("Constructed"));
}
Game::~Game()
@@ -261,10 +268,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 +279,8 @@ Game::~Game()
del_0(mCurrentMap)
mInstance = 0;
+
+ Mana::EventManager::trigger("Game", Mana::Event("Destructed"));
}
static bool saveScreenshot()
@@ -334,7 +342,8 @@ void Game::logic()
handleInput();
// Handle all necessary game logic
- beingManager->logic();
+ ActorSprite::actorLogic();
+ actorSpriteManager->logic();
particleEngine->update();
if (mCurrentMap)
mCurrentMap->update();
@@ -449,7 +458,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 +611,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 +628,7 @@ void Game::handleInput()
default: break;
}
- item = floorItemManager->findByCoordinates(
- x, y);
+ item = actorSpriteManager->findItem(x, y);
}
if (item)
@@ -753,7 +762,7 @@ void Game::handleInput()
return;
// Moving player around
- if (player_node->isAlive() && !NPC::isTalking() &&
+ if (player_node->isAlive() && !Being::isTalking() &&
!chatWindow->isInputFocused() && !quitDialog)
{
// Get the state of the keyboard keys
@@ -831,8 +840,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 +853,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 +874,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 +885,8 @@ void Game::handleInput()
if (target)
{
- if (target->getType() == Being::NPC)
- static_cast<NPC*>(target)->talk();
+ if (target->canTalk())
+ target->talkTo();
}
}
@@ -892,7 +901,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 +921,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 +954,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 +971,7 @@ void Game::changeMap(const std::string &mapPath)
delete mCurrentMap;
mCurrentMap = newMap;
- Net::getGameHandler()->mapLoaded(mapPath);
+ Mana::Event event("MapLoaded");
+ event.setString("mapPath", mapPath);
+ Mana::EventManager::trigger("Game", event);
}
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..a214c075 100644
--- a/src/gui/buy.cpp
+++ b/src/gui/buy.cpp
@@ -21,6 +21,9 @@
#include "gui/buy.h"
+#include "shopitem.h"
+#include "units.h"
+
#include "gui/setup.h"
#include "gui/widgets/button.h"
@@ -31,10 +34,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"
diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp
index c6b4ef41..3e810a4a 100644
--- a/src/gui/buysell.cpp
+++ b/src/gui/buysell.cpp
@@ -21,8 +21,6 @@
#include "buysell.h"
-#include "npc.h"
-
#include "gui/setup.h"
#include "gui/widgets/button.h"
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..103a2647 100644
--- a/src/gui/chat.cpp
+++ b/src/gui/chat.cpp
@@ -21,7 +21,7 @@
#include "chat.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
#include "configuration.h"
#include "localplayer.h"
#include "party.h"
@@ -77,6 +77,8 @@ ChatWindow::ChatWindow():
Window(_("Chat")),
mTmpVisible(false)
{
+ listen("Notices");
+
setWindowName("Chat");
setupWindow->registerWindowForReset(this);
@@ -281,20 +283,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 +410,17 @@ 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);
+ }
+ }
+}
+
void ChatWindow::addInputText(const std::string &text)
{
const int caretPos = mChatInput->getCaretPosition();
@@ -446,7 +459,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;
@@ -470,10 +483,14 @@ void ChatWindow::whisper(const std::string &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 +499,7 @@ void ChatWindow::whisper(const std::string &nick,
}
else
{
- if (own)
+ if (own == BY_PLAYER)
{
Net::getChatHandler()->privateMessage(nick, mes);
@@ -546,7 +563,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/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index 591ebd2f..fb7d1c8c 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -23,9 +23,9 @@
#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"
@@ -60,6 +60,8 @@ InventoryWindow::InventoryWindow(Inventory *inventory):
mInventory(inventory),
mSplit(false)
{
+ listen("Attributes");
+
setWindowName(isMainInventory() ? "Inventory" : "Storage");
setupWindow->registerWindowForReset(this);
setResizable(true);
@@ -341,10 +343,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..3adbc1cc 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,11 +102,6 @@ class InventoryWindow : public Window,
* window has been closed.
*/
void close();
-
- /**
- * Updates the weight bar.
- */
- void updateWeight();
void slotsChanged(Inventory* inventory);
@@ -115,7 +112,15 @@ class InventoryWindow : public Window,
*/
static bool isStorageActive() { return instances.size() > 1; }
+ void event(const std::string &channel, const Mana::Event &event);
+
private:
+ /**
+ * Updates the weight bar.
+ */
+ void updateWeight();
+
+
typedef std::list<InventoryWindow*> WindowList;
static WindowList instances;
diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp
index 0cde9395..03e6e380 100644
--- a/src/gui/itempopup.cpp
+++ b/src/gui/itempopup.cpp
@@ -103,8 +103,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.getValue("itemIcons", "graphics/items/")
+ + item.getDisplay().image);
+
mIcon->setImage(image);
if (image)
{
diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp
index 35844f64..1d01f48c 100644
--- a/src/gui/minimap.cpp
+++ b/src/gui/minimap.cpp
@@ -21,14 +21,13 @@
#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"
@@ -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..eb7c0756 100644
--- a/src/gui/ministatus.cpp
+++ b/src/gui/ministatus.cpp
@@ -24,7 +24,7 @@
#include "animatedsprite.h"
#include "configuration.h"
#include "graphics.h"
-#include "localplayer.h"
+#include "playerinfo.h"
#include "gui/gui.h"
#include "gui/statuswindow.h"
@@ -35,6 +35,7 @@
#include "net/net.h"
#include "net/playerhandler.h"
+#include "net/gamehandler.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
@@ -44,22 +45,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 +85,6 @@ MiniStatusWindow::MiniStatusWindow():
mTextPopup = new TextPopup();
addMouseListener(this);
-
- update(StatusWindow::HP);
}
void MiniStatusWindow::setIcon(int index, AnimatedSprite *sprite)
@@ -104,19 +117,23 @@ 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)
+ if (event.getName() == "UpdateAttribute")
{
- StatusWindow::updateHPBar(mHpBar);
- }
- else if (id == StatusWindow::MP)
- {
- StatusWindow::updateMPBar(mMpBar);
- }
- else if (id == StatusWindow::EXP)
- {
- StatusWindow::updateXPBar(mXpBar);
+ 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);
+ }
}
}
@@ -152,23 +169,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
{
diff --git a/src/gui/ministatus.h b/src/gui/ministatus.h
index bb8d4094..1c772850 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,7 +38,7 @@ class TextPopup;
*
* \ingroup Interface
*/
-class MiniStatusWindow : public Popup
+class MiniStatusWindow : public Popup, public Mana::Listener
{
public:
MiniStatusWindow();
@@ -50,7 +52,7 @@ class MiniStatusWindow : public Popup
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
diff --git a/src/gui/npcdialog.cpp b/src/gui/npcdialog.cpp
index 6d3995a7..4e9c0b01 100644
--- a/src/gui/npcdialog.cpp
+++ b/src/gui/npcdialog.cpp
@@ -22,7 +22,6 @@
#include "gui/npcdialog.h"
#include "configuration.h"
-#include "npc.h"
#include "gui/setup.h"
diff --git a/src/gui/npcdialog.h b/src/gui/npcdialog.h
index a8521ce9..26ff9c1a 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"
diff --git a/src/gui/npcpostdialog.cpp b/src/gui/npcpostdialog.cpp
index 19d0cf61..68a91f36 100644
--- a/src/gui/npcpostdialog.cpp
+++ b/src/gui/npcpostdialog.cpp
@@ -21,8 +21,6 @@
#include "gui/npcpostdialog.h"
-#include "npc.h"
-
#include "gui/widgets/button.h"
#include "gui/widgets/chattab.h"
#include "gui/widgets/label.h"
diff --git a/src/gui/outfitwindow.cpp b/src/gui/outfitwindow.cpp
index 89bf47da..51b4b5c5 100644
--- a/src/gui/outfitwindow.cpp
+++ b/src/gui/outfitwindow.cpp
@@ -22,12 +22,12 @@
#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"
@@ -168,7 +168,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 +206,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 +245,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 +319,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..76569d38 100644
--- a/src/gui/popupmenu.cpp
+++ b/src/gui/popupmenu.cpp
@@ -21,14 +21,13 @@
#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 "playerrelations.h"
#include "gui/chat.h"
@@ -76,7 +75,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 +144,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 +152,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 +181,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 +199,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 +223,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 +288,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 +318,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 +332,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());
}
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..b017983c 100644
--- a/src/gui/sell.cpp
+++ b/src/gui/sell.cpp
@@ -21,7 +21,6 @@
#include "gui/sell.h"
-#include "npc.h"
#include "shopitem.h"
#include "units.h"
@@ -197,6 +196,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/serverdialog.cpp b/src/gui/serverdialog.cpp
index 0762b00f..ad8ab3c8 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"
@@ -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);
diff --git a/src/gui/setup_players.cpp b/src/gui/setup_players.cpp
index 802a5b2e..f7a39240 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)),
@@ -229,7 +230,9 @@ Setup_Players::Setup_Players():
mWhisperTab(config.getValue("whispertab", false)),
mWhisperTabCheckBox(new CheckBox(_("Put all whispers in tabs"), mWhisperTab)),
mShowGender(config.getValue("showgender", false)),
- mShowGenderCheckBox(new CheckBox(_("Show gender"), mShowGender))
+ mShowGenderCheckBox(new CheckBox(_("Show gender"), mShowGender)),
+ mEnableChatLog(config.getValue("enableChatLog", false)),
+ 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);
@@ -345,8 +352,10 @@ void Setup_Players::apply()
config.setValue("showgender", mShowGender);
- if (beingManager && mShowGender != showGender)
- beingManager->updatePlayerNames();
+ if (actorSpriteManager && mShowGender != showGender)
+ actorSpriteManager->updatePlayerNames();
+
+ config.setValue("enableChatLog", mEnableChatLog);
}
void Setup_Players::cancel()
@@ -355,6 +364,8 @@ void Setup_Players::cancel()
mWhisperTabCheckBox->setSelected(mWhisperTab);
mShowGender = config.getValue("showgender", false);
mShowGenderCheckBox->setSelected(mShowGender);
+ mEnableChatLog = config.getValue("enableChatLog", false);
+ 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/skilldialog.cpp b/src/gui/skilldialog.cpp
index 53528cee..ccf4b418 100644
--- a/src/gui/skilldialog.cpp
+++ b/src/gui/skilldialog.cpp
@@ -21,8 +21,8 @@
#include "gui/skilldialog.h"
-#include "localplayer.h"
#include "log.h"
+#include "playerinfo.h"
#include "gui/setup.h"
#include "gui/theme.h"
@@ -240,10 +240,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 +259,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 +410,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/socialwindow.cpp b/src/gui/socialwindow.cpp
index 098ecbc5..25447f30 100644
--- a/src/gui/socialwindow.cpp
+++ b/src/gui/socialwindow.cpp
@@ -20,11 +20,9 @@
#include "gui/socialwindow.h"
-#include "beingmanager.h"
#include "guild.h"
#include "localplayer.h"
#include "party.h"
-#include "player.h"
#include "gui/confirmdialog.h"
#include "gui/okdialog.h"
diff --git a/src/gui/specialswindow.cpp b/src/gui/specialswindow.cpp
index 44551825..c751d6cb 100644
--- a/src/gui/specialswindow.cpp
+++ b/src/gui/specialswindow.cpp
@@ -20,7 +20,6 @@
#include "gui/specialswindow.h"
-#include "localplayer.h"
#include "log.h"
#include "gui/setup.h"
@@ -42,6 +41,8 @@
#include "net/net.h"
#include "net/specialhandler.h"
+#include "resources/specialdb.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/statuswindow.cpp b/src/gui/statuswindow.cpp
index ede85133..3dd50232 100644
--- a/src/gui/statuswindow.cpp
+++ b/src/gui/statuswindow.cpp
@@ -22,9 +22,9 @@
#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"
@@ -38,6 +38,7 @@
#include "net/net.h"
#include "net/playerhandler.h"
+#include "net/gamehandler.h"
#include "utils/gettext.h"
#include "utils/mathutils.h"
@@ -94,6 +95,8 @@ class ChangeDisplay : public AttrDisplay, gcn::ActionListener
StatusWindow::StatusWindow():
Window(player_node->getName())
{
+ listen("Attributes");
+
setWindowName("Status");
setupWindow->registerWindowForReset(this);
setResizable(true);
@@ -109,21 +112,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 +139,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 +188,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();
+ 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();
- return _("Money");
- }
- else if (id == Net::getPlayerHandler()->getJobLocation())
- {
- mJobLvlLabel->setCaption(strprintf(_("Job: %d"),
- player_node->getAttributeBase(id)));
- mJobLvlLabel->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 +319,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 +362,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 +385,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 +419,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 +484,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 +504,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/trade.cpp b/src/gui/trade.cpp
index dcb38e8e..4a86c235 100644
--- a/src/gui/trade.cpp
+++ b/src/gui/trade.cpp
@@ -24,6 +24,7 @@
#include "inventory.h"
#include "item.h"
#include "localplayer.h"
+#include "playerinfo.h"
#include "units.h"
#include "gui/inventorywindow.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);
@@ -285,7 +286,7 @@ void TradeWindow::action(const gcn::ActionEvent &event)
{
setVisible(false);
reset();
- player_node->setTrading(false);
+ PlayerInfo::setTrading(false);
Net::getTradeHandler()->cancel();
}
@@ -310,7 +311,7 @@ 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."),
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index 99325db8..66f614a8 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -21,16 +21,13 @@
#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 "textmanager.h"
#include "gui/gui.h"
@@ -40,7 +37,6 @@
#include "net/net.h"
-#include "resources/monsterinfo.h"
#include "resources/resourcemanager.h"
#include "utils/stringutils.h"
@@ -207,12 +203,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 +345,7 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
return;
// Check if we are busy
- if (NPC::isTalking())
+ if (Being::isTalking())
return;
mPlayerFollowMouse = false;
@@ -381,33 +381,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 +420,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 +447,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) /
@@ -507,27 +494,23 @@ 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);
+ mHoverBeing = actorSpriteManager->findBeingByPixel(x, y);
+ mBeingPopup->show(getMouseX(), getMouseY(), mHoverBeing);
- mHoverItem = floorItemManager->findByCoordinates(x / mMap->getTileWidth(),
- y / mMap->getTileHeight());
+ mHoverItem = actorSpriteManager->findItem(x / mMap->getTileWidth(),
+ y / mMap->getTileHeight());
if (mHoverBeing)
{
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:
@@ -562,8 +545,11 @@ void Viewport::hideBeingPopup()
mBeingPopup->setVisible(false);
}
-void Viewport::clearHoverBeing(Being *being)
+void Viewport::clearHover(ActorSprite *actor)
{
- if (mHoverBeing == being)
+ if (mHoverBeing == actor)
mHoverBeing = 0;
+
+ if (mHoverItem == actor)
+ mHoverItem = 0;
}
diff --git a/src/gui/viewport.h b/src/gui/viewport.h
index 9658f934..f91504f2 100644
--- a/src/gui/viewport.h
+++ b/src/gui/viewport.h
@@ -22,7 +22,7 @@
#ifndef VIEWPORT_H
#define VIEWPORT_H
-#include "beingmanager.h"
+#include "actorspritemanager.h"
#include "configlistener.h"
#include "position.h"
@@ -30,6 +30,7 @@
#include <guichan/mouselistener.hpp>
+class ActorSprite;
class Being;
class BeingPopup;
class FloorItem;
@@ -159,10 +160,10 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
void hideBeingPopup();
protected:
- friend class BeingManager;
+ friend class ActorSpriteManager;
- /// Clears the hovered being if it matches
- void clearHoverBeing(Being *being);
+ /// Clears any matching hovers
+ void clearHover(ActorSprite *actor);
private:
/**
diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/chattab.cpp
index 39ea6887..03ff79d9 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"
@@ -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.getValue("enableChatLog", false))
+ 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/itemshortcutcontainer.cpp b/src/gui/widgets/itemshortcutcontainer.cpp
index 83efd4d4..b3cefc5f 100644
--- a/src/gui/widgets/itemshortcutcontainer.cpp
+++ b/src/gui/widgets/itemshortcutcontainer.cpp
@@ -27,7 +27,7 @@
#include "item.h"
#include "itemshortcut.h"
#include "keyboardconfig.h"
-#include "localplayer.h"
+#include "playerinfo.h"
#include "gui/inventorywindow.h"
#include "gui/itempopup.h"
@@ -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/playerbox.cpp b/src/gui/widgets/playerbox.cpp
index 57cbec6f..468c77f5 100644
--- a/src/gui/widgets/playerbox.cpp
+++ b/src/gui/widgets/playerbox.cpp
@@ -22,9 +22,9 @@
#include "gui/widgets/playerbox.h"
#include "animatedsprite.h"
+#include "being.h"
#include "configuration.h"
#include "graphics.h"
-#include "player.h"
#include "gui/theme.h"
@@ -36,8 +36,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);
@@ -72,7 +72,7 @@ PlayerBox::~PlayerBox()
{
instances--;
- mPlayer = 0;
+ mBeing = 0;
if (instances == 0)
{
@@ -82,13 +82,13 @@ 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)
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/whispertab.cpp b/src/gui/widgets/whispertab.cpp
index 7542e251..685d28ab 100644
--- a/src/gui/widgets/whispertab.cpp
+++ b/src/gui/widgets/whispertab.cpp
@@ -21,6 +21,7 @@
#include "whispertab.h"
+#include "chatlog.h"
#include "commandhandler.h"
#include "localplayer.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/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..8a195b8c
--- /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(SpriteAction 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..6e55ad0a 100644
--- a/src/item.cpp
+++ b/src/item.cpp
@@ -58,8 +58,9 @@ void Item::setId(int id)
mDrawImage->decRef();
ResourceManager *resman = ResourceManager::getInstance();
+ SpriteDisplay display = getInfo().getDisplay();
std::string imagePath = paths.getValue("itemIcons", "graphics/items/")
- + getInfo().getImageName();
+ + 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/listener.cpp b/src/listener.cpp
new file mode 100644
index 00000000..5aac7b66
--- /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 "eventmanager.h"
+
+namespace Mana
+{
+
+Listener::~Listener()
+{
+ EventManager::remove(this);
+}
+
+void Listener::listen(const std::string &channel)
+{
+ EventManager::bind(this, channel);
+}
+
+void Listener::ignore(const std::string &channel)
+{
+ EventManager::unbind(this, channel);
+}
+
+} // namespace Mana
diff --git a/src/listener.h b/src/listener.h
new file mode 100644
index 00000000..25b388a0
--- /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:
+ ~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..5a62ea3d 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -24,27 +24,23 @@
#include "client.h"
#include "configuration.h"
#include "effectmanager.h"
-#include "equipment.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"
@@ -61,7 +57,6 @@
#include "resources/animation.h"
#include "resources/imageset.h"
-#include "resources/itemdb.h"
#include "resources/iteminfo.h"
#include "resources/resourcemanager.h"
@@ -80,29 +75,17 @@ 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),
@@ -113,29 +96,14 @@ LocalPlayer::LocalPlayer(int id, int subtype):
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);
}
@@ -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)
@@ -1022,7 +960,7 @@ void LocalPlayer::attack(Being *target, bool keep)
setDirection(LEFT);
}
- mWalkTime = tick_time;
+ mActionTime = tick_time;
mTargetTime = tick_time;
}
@@ -1053,189 +991,6 @@ 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)
@@ -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();
@@ -1373,43 +1129,6 @@ void LocalPlayer::handleStatusEffect(StatusEffect *effect, int 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 +1142,23 @@ 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");
+ }
+ }
+ }
+}
+
void LocalPlayer::changeAwayMode()
{
mAwayMode = !mAwayMode;
diff --git a/src/localplayer.h b/src/localplayer.h
index 2c06dfb5..99c3acf5 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -22,7 +22,9 @@
#ifndef LOCALPLAYER_H
#define LOCALPLAYER_H
-#include "player.h"
+#include "actorspritelistener.h"
+#include "being.h"
+#include "listener.h"
#include "gui/userpalette.h"
@@ -32,84 +34,23 @@
#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 Mana::Listener
{
public:
/**
@@ -144,11 +85,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 +94,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 +111,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 +171,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 +179,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 +204,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 +230,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 +241,12 @@ 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 +254,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,7 +265,6 @@ 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. */
@@ -474,29 +273,11 @@ class LocalPlayer : public Player
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 56019976..0dd00f56 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -41,6 +41,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
@@ -56,6 +60,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
@@ -86,6 +91,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 }
@@ -144,6 +150,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..f5214420 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,19 +133,18 @@ 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();
for (int y = startY; y < endY; y++)
{
- // If drawing the fringe layer, make sure all sprites above this row of
+ // 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++;
}
}
@@ -163,14 +161,13 @@ void MapLayer::draw(Graphics *graphics, int startX, int startY,
}
}
- // 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++;
}
}
}
@@ -283,7 +280,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,9 +306,9 @@ 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);
@@ -327,24 +324,25 @@ void Map::draw(Graphics *graphics, int scrollX, int scrollY)
(*layeri)->draw(graphics,
startX, startY, endX, endY,
scrollX, scrollY,
- mSprites, mDebugFlags);
+ 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,
@@ -524,12 +522,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 +546,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
diff --git a/src/map.h b/src/map.h
index 9fc32232..86a5d3ee 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,20 @@ 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;
private:
int mX, mY;
int mWidth, mHeight;
- bool mIsFringeLayer; /**< Whether the sprites are drawn. */
+ bool mIsFringeLayer; /**< Whether the actors are drawn. */
Image **mTiles;
};
@@ -190,7 +187,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 +292,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 +316,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 +364,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/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..f499ff0a 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;
@@ -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..c1efca0d 100644
--- a/src/net/manaserv/buysellhandler.cpp
+++ b/src/net/manaserv/buysellhandler.cpp
@@ -21,10 +21,9 @@
#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"
@@ -49,8 +48,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 +63,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 +80,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..37ce2bf5 100644
--- a/src/net/manaserv/chathandler.cpp
+++ b/src/net/manaserv/chathandler.cpp
@@ -21,8 +21,8 @@
#include "net/manaserv/chathandler.h"
+#include "actorspritemanager.h"
#include "being.h"
-#include "beingmanager.h"
#include "client.h"
#include "channel.h"
#include "channelmanager.h"
@@ -153,7 +153,7 @@ void ChatHandler::handleGameChatMessage(Net::MessageIn &msg)
return;
}
- Being *being = beingManager->findBeing(id);
+ Being *being = actorSpriteManager->findBeing(id);
std::string mes;
if (being)
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 271fff15..65010ad3 100644
--- a/src/net/manaserv/gamehandler.cpp
+++ b/src/net/manaserv/gamehandler.cpp
@@ -109,16 +109,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..1c9625bf 100644
--- a/src/net/manaserv/guildhandler.cpp
+++ b/src/net/manaserv/guildhandler.cpp
@@ -21,6 +21,7 @@
#include "net/manaserv/guildhandler.h"
+#include "eventmanager.h"
#include "guild.h"
#include "log.h"
#include "localplayer.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..3f8aa8b5 100644
--- a/src/net/manaserv/inventoryhandler.cpp
+++ b/src/net/manaserv/inventoryhandler.cpp
@@ -26,6 +26,7 @@
#include "item.h"
#include "itemshortcut.h"
#include "localplayer.h"
+#include "playerinfo.h"
#include "gui/chat.h"
@@ -60,8 +61,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 +71,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 +83,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;
@@ -130,7 +131,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 +150,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/npchandler.cpp b/src/net/manaserv/npchandler.cpp
index 392ec4fd..509f26e1 100644
--- a/src/net/manaserv/npchandler.cpp
+++ b/src/net/manaserv/npchandler.cpp
@@ -21,8 +21,7 @@
#include "net/manaserv/npchandler.h"
-#include "beingmanager.h"
-#include "npc.h"
+#include "actorspritemanager.h"
#include "gui/npcdialog.h"
#include "gui/npcpostdialog.h"
@@ -56,8 +55,8 @@ NpcHandler::NpcHandler()
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;
}
diff --git a/src/net/manaserv/partyhandler.cpp b/src/net/manaserv/partyhandler.cpp
index ec153fa8..00bb0fae 100644
--- a/src/net/manaserv/partyhandler.cpp
+++ b/src/net/manaserv/partyhandler.cpp
@@ -21,13 +21,12 @@
#include "net/manaserv/partyhandler.h"
+#include "eventmanager.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 2347fee2..fa823a11 100644
--- a/src/net/manaserv/playerhandler.cpp
+++ b/src/net/manaserv/playerhandler.cpp
@@ -28,7 +28,7 @@
#include "localplayer.h"
#include "log.h"
#include "particle.h"
-#include "npc.h"
+#include "playerinfo.h"
#include "configuration.h"
#include "gui/chat.h"
@@ -39,6 +39,7 @@
#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"
@@ -113,13 +114,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;
@@ -133,26 +134,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.getValue("particles", "graphics/particles/")
+ + paths.getValue("levelUpEffectFile", "levelup.particle.xml")
+ ,0, 0);
player_node->controlParticle(effect);
} break;
case GPMSG_LEVEL_PROGRESS:
{
- player_node->setExp(msg.readInt8(), false);
+ PlayerInfo::setAttribute(EXP, msg.readInt8());
} break;
@@ -176,18 +177,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;
@@ -212,21 +214,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;
}
@@ -241,7 +245,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;
/*
@@ -334,11 +338,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..a80fc6e6 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 "eventmanager.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..2a9cfab5 100644
--- a/src/net/npchandler.h
+++ b/src/net/npchandler.h
@@ -29,6 +29,8 @@ namespace Net {
class NpcHandler
{
public:
+ virtual ~NpcHandler() {}
+
virtual void talk(int npcId) = 0;
virtual void nextDialog(int npcId) = 0;
@@ -55,8 +57,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..feaf7efd 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 "eventmanager.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..5c89cd31 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,7 +233,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
* later versions of eAthena for both mobs and
* players
*/
- dstBeing = beingManager->findBeing(msg.readInt32());
+ dstBeing = actorSpriteManager->findBeing(msg.readInt32());
Uint16 srcX, srcY, dstX, dstY;
msg.readCoordinatePair(srcX, srcY, dstX, dstY);
@@ -267,7 +258,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
// A being should be removed or has died
id = msg.readInt32();
- dstBeing = beingManager->findBeing(id);
+ dstBeing = actorSpriteManager->findBeing(id);
if (!dstBeing)
break;
@@ -289,7 +280,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
if (msg.readInt8() == 1)
dstBeing->setAction(Being::DEAD);
else
- beingManager->destroyBeing(dstBeing);
+ actorSpriteManager->destroy(dstBeing);
break;
@@ -297,7 +288,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
// A being changed mortality status
id = msg.readInt32();
- dstBeing = beingManager->findBeing(id);
+ dstBeing = actorSpriteManager->findBeing(id);
if (!dstBeing)
break;
@@ -313,8 +304,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 +320,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 +348,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
case 0x02: // Sit
if (srcBeing)
{
- srcBeing->setFrame(0);
srcBeing->setAction(Being::SIT);
}
break;
@@ -365,7 +355,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
case 0x03: // Stand up
if (srcBeing)
{
- srcBeing->setFrame(0);
srcBeing->setAction(Being::STAND);
}
break;
@@ -374,11 +363,11 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
case SMSG_BEING_SELFEFFECT: {
id = (Uint32)msg.readInt32();
- if (!beingManager->findBeing(id))
+ if (!actorSpriteManager->findBeing(id))
break;
int effectType = msg.readInt32();
- Being* being = beingManager->findBeing(id);
+ Being* being = actorSpriteManager->findBeing(id);
effectManager->trigger(effectType, being);
@@ -386,7 +375,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
}
case SMSG_BEING_EMOTION:
- if (!(dstBeing = beingManager->findBeing(msg.readInt32())))
+ if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
{
break;
}
@@ -415,14 +404,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 +426,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 +471,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 +486,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 +509,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 +519,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 +548,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 +592,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 +615,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,7 +639,7 @@ 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;
@@ -664,10 +647,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
y = msg.readInt16();
dstBeing->setTileCoords(x, y);
if (dstBeing->getCurrentAction() == Being::WALK)
- {
- dstBeing->setFrame(0);
dstBeing->setAction(Being::STAND);
- }
}
}
break;
@@ -684,7 +664,7 @@ 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);
stunMode = msg.readInt16();
statusEffects = msg.readInt16();
statusEffects |= ((Uint32) msg.readInt16()) << 16;
@@ -704,7 +684,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..a43784de 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 "eventmanager.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"
@@ -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 640d04c1..2b65b515 100644
--- a/src/net/tmwa/chathandler.cpp
+++ b/src/net/tmwa/chathandler.cpp
@@ -21,8 +21,9 @@
#include "net/tmwa/chathandler.h"
+#include "actorspritemanager.h"
#include "being.h"
-#include "beingmanager.h"
+#include "eventmanager.h"
#include "game.h"
#include "localplayer.h"
#include "playerrelations.h"
@@ -70,19 +71,28 @@ 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);
+ chatWindow->whisper(nick, strprintf(_("Whisper could not "
+ "be sent, %s is offline."), nick.c_str()),
+ BY_SERVER);
break;
case 0x02:
- localChatTab->chatLog(_("Whisper could not be sent, "
- "ignored by user."), BY_SERVER);
+ chatWindow->whisper(nick, strprintf(_("Whisper could not "
+ "be sent, ignored by %s."), nick.c_str()),
+ BY_SERVER);
break;
}
break;
@@ -112,7 +122,7 @@ void ChatHandler::handleMessage(Net::MessageIn &msg)
// Received speech from being
case SMSG_BEING_CHAT: {
chatMsgLength = msg.readInt16() - 8;
- being = beingManager->findBeing(msg.readInt32());
+ being = actorSpriteManager->findBeing(msg.readInt32());
if (!being || chatMsgLength <= 0)
break;
@@ -197,47 +207,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 179d98e4..03d27b47 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 "eventmanager.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:
@@ -104,6 +104,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);
@@ -141,16 +156,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..1cc6cb47 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"
@@ -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..8b788bad 100644
--- a/src/net/tmwa/gui/guildtab.cpp
+++ b/src/net/tmwa/gui/guildtab.cpp
@@ -21,6 +21,7 @@
#include "net/tmwa/gui/guildtab.h"
+#include "chatlog.h"
#include "commandhandler.h"
#include "guild.h"
#include "localplayer.h"
@@ -114,4 +115,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..0f3e8e24 100644
--- a/src/net/tmwa/gui/partytab.cpp
+++ b/src/net/tmwa/gui/partytab.cpp
@@ -21,6 +21,7 @@
#include "net/tmwa/gui/partytab.h"
+#include "chatlog.h"
#include "commandhandler.h"
#include "localplayer.h"
#include "party.h"
@@ -206,4 +207,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..a09f2dfe 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 "eventmanager.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..ae9731ba 100644
--- a/src/net/tmwa/inventoryhandler.cpp
+++ b/src/net/tmwa/inventoryhandler.cpp
@@ -23,6 +23,7 @@
#include "configuration.h"
#include "equipment.h"
+#include "eventmanager.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..bd655fa6 100644
--- a/src/net/tmwa/npchandler.cpp
+++ b/src/net/tmwa/npchandler.cpp
@@ -21,9 +21,8 @@
#include "net/tmwa/npchandler.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
#include "localplayer.h"
-#include "npc.h"
#include "gui/npcdialog.h"
diff --git a/src/net/tmwa/partyhandler.cpp b/src/net/tmwa/partyhandler.cpp
index e86d41fa..6983b731 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 "eventmanager.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,8 @@ 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);
+ Being *b = actorSpriteManager->findBeing(id);
+ b->setParty(NULL);
taParty->removeMember(id);
}
@@ -274,9 +267,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 +312,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 +327,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 +345,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..733d4a88 100644
--- a/src/net/tmwa/playerhandler.cpp
+++ b/src/net/tmwa/playerhandler.cpp
@@ -21,10 +21,11 @@
#include "net/tmwa/playerhandler.h"
+#include "eventmanager.h"
#include "game.h"
#include "localplayer.h"
#include "log.h"
-#include "npc.h"
+#include "playerinfo.h"
#include "units.h"
#include "gui/buy.h"
@@ -36,8 +37,6 @@
#include "gui/statuswindow.h"
#include "gui/viewport.h"
-#include "gui/widgets/chattab.h"
-
#include "net/messagein.h"
#include "net/messageout.h"
@@ -54,9 +53,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 {
@@ -217,7 +213,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 +233,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 +252,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 +297,28 @@ 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();
+ 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 +329,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 +342,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 +367,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 +379,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 +391,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 +403,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 +415,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 +426,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 +481,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 +524,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 +533,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 +586,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..f147ef9b 100644
--- a/src/net/tmwa/specialhandler.cpp
+++ b/src/net/tmwa/specialhandler.cpp
@@ -21,8 +21,8 @@
#include "net/tmwa/specialhandler.h"
-#include "localplayer.h"
#include "log.h"
+#include "playerinfo.h"
#include "gui/skilldialog.h"
@@ -105,8 +105,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 +118,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;
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..e9712d5e 100644
--- a/src/net/tmwa/tradehandler.cpp
+++ b/src/net/tmwa/tradehandler.cpp
@@ -21,16 +21,16 @@
#include "net/tmwa/tradehandler.h"
+#include "eventmanager.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..6a3fd7da 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--;
@@ -99,8 +94,9 @@ void Particle::setupEngine()
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..77174d52 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,8 @@ 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());
+ 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..28d37c83
--- /dev/null
+++ b/src/playerinfo.cpp
@@ -0,0 +1,312 @@
+/*
+ * 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 "eventmanager.h"
+#include "inventory.h"
+#include "listener.h"
+#include "log.h"
+
+#include "resources/itemdb.h"
+#include "resources/iteminfo.h"
+
+namespace PlayerInfo {
+
+class PlayerInfoListener;
+
+PlayerInfoListener *mListener = 0;
+
+PlayerInfoBackend mData;
+
+Inventory *mInventory = 0;
+Equipment *mEquipment = 0;
+
+std::map<int, Special> mSpecials;
+char mSpecialRechargeUpdateNeeded = 0;
+
+bool mTrading = false;
+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);
+ Mana::EventManager::trigger("Attributes", event);
+}
+
+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);
+ Mana::EventManager::trigger("Attributes", event);
+}
+
+// --- 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);
+}
+
+// --- 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;
+}
+
+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++;
+}
+
+bool isTrading()
+{
+ return mTrading;
+}
+
+void setTrading(bool trading)
+{
+ bool notify = mTrading != trading;
+ mTrading = trading;
+
+ if (notify)
+ {
+ Mana::Event event("Trading");
+ event.setInt("trading", trading);
+ Mana::EventManager::trigger("Status", event);
+ }
+}
+
+class PlayerInfoListener : Mana::Listener
+{
+public:
+ PlayerInfoListener()
+ {
+ 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 PlayerInfoListener();
+}
+
+} // namespace PlayerInfo
diff --git a/src/playerinfo.h b/src/playerinfo.h
new file mode 100644
index 00000000..3214e64e
--- /dev/null
+++ b/src/playerinfo.h
@@ -0,0 +1,213 @@
+/*
+ * 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;
+
+/**
+ * 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 --------------------------------------------------
+
+ /**
+ * 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);
+
+// --- 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);
+
+ /**
+ * Does necessary updates every tick.
+ */
+ void logic();
+
+ /**
+ * 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);
+
+ /**
+ * 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..c9447283
--- /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(ACTION_ATTACK, "", "");
+
+ Attacks::const_iterator i = mAttacks.find(type);
+ return (i == mAttacks.end()) ? empty : (*i).second;
+}
+
+void BeingInfo::addAttack(int id, SpriteAction 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..8485ac6c
--- /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 {
+ SpriteAction action;
+ std::string particleEffect;
+ std::string missileParticle;
+
+ Attack(SpriteAction 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, SpriteAction 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/itemdb.cpp b/src/resources/itemdb.cpp
index 3fdee021..bfa19cf1 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] =
{
@@ -115,7 +116,7 @@ void ItemDB::load()
mUnknown = new ItemInfo;
mUnknown->setName(_("Unknown item"));
- mUnknown->setImageName("");
+ mUnknown->setDisplay(SpriteDisplay());
std::string errFile = paths.getValue("spriteErrorFile", "error.xml");
mUnknown->setSprite(errFile, GENDER_MALE);
mUnknown->setSprite(errFile, GENDER_FEMALE);
@@ -156,9 +157,11 @@ void ItemDB::load()
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));
@@ -204,8 +207,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())
{
@@ -336,3 +345,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.h b/src/resources/iteminfo.h
index a7c0ddca..d9fc05cc 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"
@@ -143,11 +143,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; }
@@ -201,7 +201,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. */
diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp
index b08d87f2..ed062acf 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
{
@@ -142,14 +130,17 @@ void MonsterDB::load()
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 +156,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..383e8a27 100644
--- a/src/resources/spritedef.cpp
+++ b/src/resources/spritedef.cpp
@@ -36,6 +36,10 @@
#include <set>
+SpriteReference *SpriteReference::Empty = new SpriteReference(
+ paths.getValue("spriteErrorFile", "error.xml"),
+ 0);
+
Action *SpriteDef::getAction(SpriteAction action) const
{
Actions::const_iterator i = mActions.find(action);
diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h
index 5bb6078e..bc9ae45f 100644
--- a/src/resources/spritedef.h
+++ b/src/resources/spritedef.h
@@ -26,12 +26,35 @@
#include <libxml/tree.h>
+#include <list>
#include <map>
#include <string>
class Action;
class ImageSet;
+struct SpriteReference
+{
+ 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;
+
enum SpriteAction
{
ACTION_DEFAULT = 0,
diff --git a/src/sprite.h b/src/sprite.h
index 847c01a6..cce41f1d 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(SpriteAction 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/text.cpp b/src/text.cpp
index f6c71dba..9f970872 100644
--- a/src/text.cpp
+++ b/src/text.cpp
@@ -41,12 +41,17 @@ 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;
@@ -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/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/xml.cpp b/src/utils/xml.cpp
index 341f34c0..94e0e38d 100644
--- a/src/utils/xml.cpp
+++ b/src/utils/xml.cpp
@@ -27,6 +27,7 @@
#include <iostream>
#include <fstream>
+#include <cstring>
namespace XML
{
@@ -135,6 +136,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 72745501..253c4e09 100644
--- a/src/utils/xml.h
+++ b/src/utils/xml.h
@@ -69,14 +69,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.
@@ -85,6 +85,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..c2eca3fb
--- /dev/null
+++ b/src/variabledata.h
@@ -0,0 +1,85 @@
+/*
+ * 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 {
+ DATA_NONE,
+ DATA_INT,
+ DATA_STRING,
+ DATA_FLOAT
+ };
+
+ 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;
+};
+
+} // namespace Mana
+
+#endif