diff options
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=""D:\Programming\Libraries\LibXml\libxml2-2.6.17.win32\lib";"D:\Programming\Libraries\LibXml\libxml2-2.6.17.win32\include"" - 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 Binary files differindex 77cdf4b6..77cdf4b6 100644 --- a/data/graphics/gui/target-cursor-blue-l.png +++ b/data/graphics/target-cursor-in-range-l.png diff --git a/data/graphics/gui/target-cursor-blue-m.png b/data/graphics/target-cursor-in-range-m.png Binary files differindex c0107357..c0107357 100644 --- a/data/graphics/gui/target-cursor-blue-m.png +++ b/data/graphics/target-cursor-in-range-m.png diff --git a/data/graphics/gui/target-cursor-blue-s.png b/data/graphics/target-cursor-in-range-s.png Binary files differindex 3e81c75d..3e81c75d 100644 --- a/data/graphics/gui/target-cursor-blue-s.png +++ b/data/graphics/target-cursor-in-range-s.png diff --git a/data/graphics/gui/target-cursor-red-l.png b/data/graphics/target-cursor-normal-l.png Binary files differindex 76d2101b..76d2101b 100644 --- a/data/graphics/gui/target-cursor-red-l.png +++ b/data/graphics/target-cursor-normal-l.png diff --git a/data/graphics/gui/target-cursor-red-m.png b/data/graphics/target-cursor-normal-m.png Binary files differindex e2ab79c2..e2ab79c2 100644 --- a/data/graphics/gui/target-cursor-red-m.png +++ b/data/graphics/target-cursor-normal-m.png diff --git a/data/graphics/gui/target-cursor-red-s.png b/data/graphics/target-cursor-normal-s.png Binary files differindex 09195f44..09195f44 100644 --- a/data/graphics/gui/target-cursor-red-s.png +++ b/data/graphics/target-cursor-normal-s.png @@ -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" /> @@ -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" @@ -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 @@ -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) { } @@ -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 |