diff --git a/.gitignore b/.gitignore index 6dbbad9f..754b7124 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,5 @@ src/libraries/external/boost_* *.iobj *.filters +# sapphire version +src/servers/Server_Common/Version\.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a6c4e855..2b3fced6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,14 @@ include( "cmake/boost.cmake" ) include( "cmake/mysql.cmake" ) include( "cmake/compiler.cmake" ) +############################## +# Git # +############################## +include(GetGitRevisionDescription) +get_git_head_revision(GIT_REFSPEC GIT_SHA1) +git_describe(VERSION --tags --dirty=-d) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/servers/Server_Common/Version.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/servers/Server_Common/Version.cpp" @ONLY) + ########################################################################## # Common include folders include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/libraries/external/ChaiScript-6.0.0/include/") diff --git a/README.md b/README.md index 4fa10544..6574ac0d 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,42 @@ # Sapphire - FINAL FANTASY XIV Server Emulator [![Discord Server](https://img.shields.io/badge/discord-Sapphire-7289DA.svg)](https://discord.gg/KfrZCkx) -[![Build Status](https://travis-ci.org/SapphireMordred/Sapphire.svg?branch=master)](https://travis-ci.org/SapphireMordred/Sapphire) +[![Linux Build Status](https://travis-ci.org/SapphireMordred/Sapphire.svg?branch=master)](https://travis-ci.org/SapphireMordred/Sapphire) +[![Windows Build Status](https://ci.appveyor.com/api/projects/status/lil7lxa3ty165emm?svg=true)](https://ci.appveyor.com/project/SapphireMordred/Sapphire) ![FFXIV Sapphire](http://i.imgur.com/I4bj1tR.png) Sapphire is a FINAL FANTASY XIV 4.0+ Server Emulator currently in development. -## Features - -* Fully working base world servers, including character creation, chat, player interaction, etc. -* Basic action/battle system -* Teleports, discovery -* NPCs, enemies -* Support for most Quest types(instanced content planned, to be added later) -* Content scripting via ChaiScript -* Retail GM commands working +Sapphire is a **research project** to learn how retail servers work and currently not production code; at this time it is **insecure** (use throwaway passwords for accounts) and you should expect a lot of things unimplemented or broken (of course contributions are always welcome). ## Dependencies + Compiling Sapphire requires the following software: | *Name* | *Windows* | *Linux* | | ------ | --------- | ------- | -| CMake 2.6+ and C++14 capable compiler | [Visual Studio 2017](https://www.visualstudio.com/) | Your favorite C++14 capable compiler | +| CMake 2.6+ and C++14 capable compiler | [Visual Studio 2017](https://www.visualstudio.com/) | `gcc 4.9` and `g++ 4.9` or newer | | Boost 1.63.0 | [Win32 precompiled binaries](https://sourceforge.net/projects/boost/files/boost-binaries/1.63.0/boost_1_63_0-msvc-14.0-32.exe/download) | Boost libraries from your distribution's package manager | | MySQL Server 5.7 | [Official Site](https://dev.mysql.com/downloads/mysql/) | MySQL server from your distribution's package manager | | C# Compiler(used for various tools) | [Visual Studio 2017](https://www.visualstudio.com/) \| [Mono](http://www.mono-project.com/) | [Mono](http://www.mono-project.com/) from your distribution's package manager | **Windows** Set the environment variables ``BOOST_ROOT_DIR`` and ``BOOST_LIB_DIR`` to ``[boost main folder]`` and ``[boost main folder]/lib32-msvc-14.0`` respectively **or** copy your boost installation into the project's ``src/lib`` folder. + +Visual Studio 2017 users: open `Visual Studio Installer` and ensure `Individual Components > SDKs, libraries, and frameworks > Windows Universal C Runtime` is installed. You may also need to install `Individual Components > Compilers, build tools, and runtimes > VC++ 2015.3 v140 toolset for desktop (x86, 64)`. + +To enable [Edit and Continue](https://msdn.microsoft.com/en-us/library/esaeyddf.aspx) ensure you define `-DCMAKE_BUILD_TYPE="Debug"` when generating with CMake. + +If you installed CMake outside of Visual Studio and have it in your `PATH` environment variable, navigate to Sapphire folder and `cmake -DCMAKE_BUILD_TYPE="Debug" && cmake --build .`. + +Otherwise: * In *Visual Studio 2017*: Open the project via ``File`` > ``Open`` > ``Folder`` and wait, till CMake automatically finishes cache generation. Right click any CMakeLists.txt and select build to build a application. To configure debug startup parameters, select ``Debug and Launch settings``, the application you want to set up parameters for, and add a ``args`` json array containing your launch parameters in ``configurations``. If Visual Studio fails to generate a CMake Cache or does not show options to build, make sure that the newest version of it is installed and all environment variables are set correctly. Keep in mind that generating a cache can take a while on some machines. -* In *Visual Studio 2015*: Generate a Visual Studio project via CMake: ``cmake -G "Visual Studio 14 2015"`` and open it as a normal solution in Visual Studio. + +The solution `Sapphire.sln` is also generated in the main Sapphire folder. **Linux** -Generate a cache with CMake and use your favorite C++14 capable compiler to compile those wonderful lines of code into binaries with ``make``. -Sapphire is **not** currently configured to compile in 64bit. Make sure that all libraries have their ``:i386`` versions installed. +`cmake . -DSAPPHIRE_BOOST_VER="your.boost.ver" && make -j JOBS` where `JOBS` is number of cores on your system. +`-j JOBS` can be omitted if your system lacks resources (spoiler: your system probably lacks resources if running on 1GB RAM or lower, or if the build fails due to being out of memory) ## Links diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake new file mode 100644 index 00000000..543305e1 --- /dev/null +++ b/cmake/GetGitRevisionDescription.cmake @@ -0,0 +1,168 @@ +# - Returns a version string from Git +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# get_git_head_revision( [ ...]) +# +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# git_local_changes() +# +# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. +# Uses the return code of "git diff-index --quiet HEAD --". +# Does not regard untracked files. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +function(get_git_head_revision _refspecvar _hashvar) + set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories + set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") + get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) + if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) + # We have reached the root directory, we are not in git + set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + return() + endif() + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + endwhile() + # check if this is a submodule + if(NOT IS_DIRECTORY ${GIT_DIR}) + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${GIT_DIR}/HEAD") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" + @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) + set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) +endfunction() + +function(git_describe _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() + + #message(STATUS "Arguments to execute_process: ${ARGN}") + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + describe + ${hash} + ${ARGN} + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +function(git_get_exact_tag _var) + git_describe(out --exact-match ${ARGN}) + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +function(git_local_changes _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + diff-index --quiet HEAD -- + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(res EQUAL 0) + set(${_var} "CLEAN" PARENT_SCOPE) + else() + set(${_var} "DIRTY" PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/GetGitRevisionDescription.cmake.in b/cmake/GetGitRevisionDescription.cmake.in new file mode 100644 index 00000000..04db9a8e --- /dev/null +++ b/cmake/GetGitRevisionDescription.cmake.in @@ -0,0 +1,41 @@ +# +# Internal file for GetGitRevisionDescription.cmake +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() diff --git a/scripts/chai/skill/cnj/skillDef_121.chai b/scripts/chai/skill/cnj/skillDef_121.chai index 19749681..048ec609 100644 --- a/scripts/chai/skill/cnj/skillDef_121.chai +++ b/scripts/chai/skill/cnj/skillDef_121.chai @@ -11,7 +11,7 @@ class skillDef_121Def def onFinish( player, target ) { player.handleScriptSkill( STD_DAMAGE, 121, 50, 0, target ); - target.addStatusEffectByIdIfNotExist(143, 20000, 0); + target.addStatusEffectByIdIfNotExist(143, 20000, player, 0); } }; diff --git a/scripts/chai/skill/cnj/skillDef_124.chai b/scripts/chai/skill/cnj/skillDef_124.chai new file mode 100644 index 00000000..325dd3d9 --- /dev/null +++ b/scripts/chai/skill/cnj/skillDef_124.chai @@ -0,0 +1,18 @@ +// Skill Name: Medica +// Skill ID: 124 + +class skillDef_124Def +{ + def skillDef_124Def() + { + + } + + def onFinish( player, target ) + { + player.handleScriptSkill( STD_HEAL, 124, 300, 0, player ); + } + +}; + +GLOBAL skillDef_124 = skillDef_124Def(); diff --git a/scripts/chai/skill/cnj/skillDef_125.chai b/scripts/chai/skill/cnj/skillDef_125.chai index 5adb4eca..2795dc85 100644 --- a/scripts/chai/skill/cnj/skillDef_125.chai +++ b/scripts/chai/skill/cnj/skillDef_125.chai @@ -10,7 +10,7 @@ class skillDef_125Def def onFinish( player, target ) { - target.addStatusEffectByIdIfNotExist( 148, 60000, 0 ); + target.addStatusEffectByIdIfNotExist( 148, 60000, player, 0 ); } }; diff --git a/scripts/chai/skill/cnj/skillDef_128.chai b/scripts/chai/skill/cnj/skillDef_128.chai index 74b58e85..0d5aa11f 100644 --- a/scripts/chai/skill/cnj/skillDef_128.chai +++ b/scripts/chai/skill/cnj/skillDef_128.chai @@ -10,7 +10,7 @@ class skillDef_128Def def onFinish( player, target ) { - target.addStatusEffectByIdIfNotExist(3, 30000, 0); + target.addStatusEffectByIdIfNotExist( 3, 30000, player, 0 ); } }; diff --git a/scripts/chai/skill/cnj/skillDef_132.chai b/scripts/chai/skill/cnj/skillDef_132.chai index 765f82a1..3cca7909 100644 --- a/scripts/chai/skill/cnj/skillDef_132.chai +++ b/scripts/chai/skill/cnj/skillDef_132.chai @@ -11,7 +11,7 @@ class skillDef_132Def def onFinish( player, target ) { player.handleScriptSkill( STD_DAMAGE, 132, 50, 0, target ); - target.addStatusEffectByIdIfNotExist( 143, 20000, 0 ); + target.addStatusEffectByIdIfNotExist( 143, 20000, player, 0 ); } }; diff --git a/scripts/chai/skill/cnj/skillDef_133.chai b/scripts/chai/skill/cnj/skillDef_133.chai new file mode 100644 index 00000000..9a279eaa --- /dev/null +++ b/scripts/chai/skill/cnj/skillDef_133.chai @@ -0,0 +1,19 @@ +// Skill Name: Medica II +// Skill ID: 133 + +class skillDef_133Def +{ + def skillDef_133Def() + { + + } + + def onFinish( player, target ) + { + player.handleScriptSkill( STD_HEAL, 133, 200, 0, player ); + target.addStatusEffectByIdIfNotExist( 150, 30000, player, 50 ); + } + +}; + +GLOBAL skillDef_133 = skillDef_133Def(); diff --git a/scripts/chai/skill/skillDef_3.chai b/scripts/chai/skill/skillDef_3.chai index 8936bec9..e888058a 100644 --- a/scripts/chai/skill/skillDef_3.chai +++ b/scripts/chai/skill/skillDef_3.chai @@ -10,7 +10,7 @@ class skillDef_3Def def onFinish( player, target ) { - player.addStatusEffectById(50, 20000, 30); + player.addStatusEffectById(50, 20000, player, 30); } }; diff --git a/sql/zonepositions.sql b/sql/zonepositions.sql index d77e9044..34bfa0c8 100644 --- a/sql/zonepositions.sql +++ b/sql/zonepositions.sql @@ -23,7 +23,7 @@ CREATE TABLE IF NOT EXISTS `zonepositions` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; --- Dumping data for table sapphire.zonepositions: 157 rows +-- Dumping data for table sapphire.zonepositions: 186 rows DELETE FROM `zonepositions`; /*!40000 ALTER TABLE `zonepositions` DISABLE KEYS */; INSERT INTO `zonepositions` (`id`, `target_zone_id`, `pos_x`, `pos_y`, `pos_z`, `pos_o`, `radius`) VALUES @@ -192,7 +192,27 @@ INSERT INTO `zonepositions` (`id`, `target_zone_id`, `pos_x`, `pos_y`, `pos_z`, (4203092, 129, -213.582, 16, 48.801, -0.006, 2), (6390356, 128, -11.685, 91.499, -13.191, -0.377, 2), (4170499, 134, -39.562, 36.039, 152.972, 2.041, 2), - (4170784, 135, -39.271, 71.504, 116.516, 1.587, 2); + (4170784, 135, -39.271, 71.504, 116.516, 1.587, 2), + (6100648, 478, -74.827, 209.524, -23.346, 2.854, 2), + (5865600, 478, 135.482, 207, 114.076, -2.166, 2), + (5865605, 478, 79.813, 203.98, 132.018, 2.558, 2), + (5865668, 399, -221.2, 104.271, -599.535, 0.268, 2), + (5865672, 399, -221.2, 155.809, -516.036, 0.295, 2), + (5865598, 399, -221.2, 104.271, -599.535, 0.268, 2), + (5865604, 399, -533.153, 153.074, -487.968, 0.18, 2), + (5916706, 418, -111.521, 15.14, -29.188, 0.0077, 2), + (5916705, 418, 47.713, 23.979, 1.144, 1.457, 2), + (5916704, 418, 47.701, -12.02, 67.738, 2.057, 2), + (5916727, 155, -161.481, 304.153, -321.403, 0.795, 2), + (5916708, 419, 0.000456, 16.015, -35.806, -0.0296, 2), + (5916724, 419, 80.156, 10.054, -123.9, -2.445, 2), + (5916722, 419, -80.517, 10.054, -123.315, 2.468, 2), + (5916717, 419, -136.889, -12.634, -16.757, 0.978, 2), + (5916716, 419, 136.079, -9.234, -66.426, -0.989, 2), + (6905273, 612, 475.811, 61.576, -555.551, -1.274, 2), + (6905297, 620, -653.588, 51.867, -790.168, 1.1366, 2), + (6906489, 635, -82.295, 0, 8.925, 1.77, 2), + (6906492, 635, 100.312, 2.731, -113.366, -0.481, 2); /*!40000 ALTER TABLE `zonepositions` ENABLE KEYS */; /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; diff --git a/src/servers/Server_Common/Common.h b/src/servers/Server_Common/Common.h index f4577309..752eb711 100644 --- a/src/servers/Server_Common/Common.h +++ b/src/servers/Server_Common/Common.h @@ -424,15 +424,6 @@ namespace Core { Land = 0x200, }; - enum UserLevel : uint8_t - { - all = 0xff, - player = 0x01, - gm = 0x02, - dev = 0x04, - admin = 0x08 - }; - struct QuestActive { QuestActive() @@ -571,6 +562,35 @@ namespace Core { LimitBreak = 8, }; + enum ActionEffectType : uint8_t + { + Nothing = 0, + Miss = 1, + FullResist = 2, + Damage = 3, + Heal = 4, + BlockedDamage = 5, + ParriedDamage = 6, + Invulnerable = 7, + NoEffectText = 8, + Unknown_0 = 9, + MpLoss = 10, + MpGain = 11, + TpLoss = 12, + TpGain = 13, + GpGain = 14 + }; + + enum ActionHitSeverityType : uint8_t + { + NormalDamage = 0, + CritHeal = 0, + CritDamage = 1, + NormalHeal = 1, + DirectHitDamage = 2, + CritDirectHitDamage = 3 + }; + enum HandleActionType : uint8_t { Event, @@ -743,7 +763,7 @@ namespace Core { Flee = 0x1B, - Unk3 = 0x20, + Unk3 = 0x20, // Animation related? CombatIndicationShow = 0x22, @@ -769,7 +789,7 @@ namespace Core { ItemRepairMsg = 0x5C, LeveStartAnim = 0x66, - Unk4 = 0x67, + LeveStartError = 0x67, PlayerNameGrayout = 0x6A, ItemObtainMsg = 0x75, @@ -869,7 +889,7 @@ namespace Core { AchievementPopup = 0x203, - Unk7 = 0x205, + Unk7 = 0x205, // LogMessage? AchievementMsg = 0x206, SetItemLevel = 0x209, diff --git a/src/servers/Server_Common/Database/Database.h b/src/servers/Server_Common/Database/Database.h index 6bc8b11c..cce94691 100644 --- a/src/servers/Server_Common/Database/Database.h +++ b/src/servers/Server_Common/Database/Database.h @@ -33,7 +33,26 @@ namespace Db { return static_cast< T >( atol( m_pValue ) ); } + + uint64_t getUInt64() + { + if( m_pValue ) + { + #ifdef _WIN32 + uint64_t value; + sscanf( m_pValue, "%I64d", &value ); + return value; + #else + uint64_t value; + sscanf( m_pValue, "%Lu", &value ); + return value; + #endif + } + else + return 0; + } + uint32_t getLength() const; private: diff --git a/src/servers/Server_Common/Exd/ExdData.cpp b/src/servers/Server_Common/Exd/ExdData.cpp index 5f9f22c5..0c5fd98f 100644 --- a/src/servers/Server_Common/Exd/ExdData.cpp +++ b/src/servers/Server_Common/Exd/ExdData.cpp @@ -315,8 +315,7 @@ bool Core::Data::ExdData::loadActionInfo() for( auto row : rows ) { auto& fields = row.second; - - ActionInfo info{ 0 }; + auto info = boost::make_shared< ActionInfo >(); uint32_t id = row.first; if( id == 0 ) @@ -350,7 +349,7 @@ bool Core::Data::ExdData::loadActionInfo() uint16_t recast_time = getField< uint16_t >( fields, 37 ); // 37 int8_t model = getField< int8_t >( fields, 39 ); // 39: Action model - uint8_t aspect = getField< uint8_t >( fields, 40 ); // 40: Action aspect + uint8_t aspect = getField< uint8_t >( fields, 40 ); // 40: Action aspect uint8_t typeshift = 0x6; uint8_t mask = 1 << typeshift; @@ -360,36 +359,36 @@ bool Core::Data::ExdData::loadActionInfo() - info.id = id; - info.name = name; - info.category = category; + info->id = id; + info->name = name; + info->category = category; - info.class_job = class_job; - info.unlock_level = unlock_level; - info.range = range; - info.can_target_self = can_target_self; - info.can_target_party = can_target_party; - info.can_target_friendly = can_target_friendly; - info.can_target_enemy = can_target_enemy; + info->class_job = class_job; + info->unlock_level = unlock_level; + info->range = range; + info->can_target_self = can_target_self; + info->can_target_party = can_target_party; + info->can_target_friendly = can_target_friendly; + info->can_target_enemy = can_target_enemy; - info.can_target_ko = can_target_ko; + info->can_target_ko = can_target_ko; - info.is_aoe = is_aoe; + info->is_aoe = is_aoe; - info.aoe_type = aoe_type; - info.radius = radius; + info->aoe_type = aoe_type; + info->radius = radius; - info.points_type = points_type; - info.points_cost = points_cost; + info->points_type = points_type; + info->points_cost = points_cost; - info.is_instant = is_instant; - info.cast_time = cast_time * 100; - info.recast_time = recast_time * 100; + info->is_instant = is_instant; + info->cast_time = cast_time * 100; + info->recast_time = recast_time * 100; - info.model = model; - info.aspect = aspect; + info->model = model; + info->aspect = aspect; - m_actionInfoMap[id] = info; + m_actionInfoMap.emplace( std::make_pair( info->id, info ) ); } @@ -464,6 +463,22 @@ boost::shared_ptr< Core::Data::AetheryteInfo > } +boost::shared_ptr< Core::Data::ActionInfo > +Core::Data::ExdData::getActionInfo( uint32_t actionId ) +{ + try + { + return m_actionInfoMap[actionId]; + } + catch ( ... ) + { + return nullptr; + } + + return nullptr; + +} + boost::shared_ptr< Core::Data::CustomTalkInfo > Core::Data::ExdData::getCustomTalkInfo( uint32_t customTalkId ) { diff --git a/src/servers/Server_Common/Exd/ExdData.h b/src/servers/Server_Common/Exd/ExdData.h index f0c5793f..a6376550 100644 --- a/src/servers/Server_Common/Exd/ExdData.h +++ b/src/servers/Server_Common/Exd/ExdData.h @@ -299,7 +299,7 @@ namespace Core { std::map m_classJobInfoMap; std::map m_paramGrowthInfoMap; std::map m_EventActionInfoMap; - std::map m_actionInfoMap; + std::map > m_actionInfoMap; std::map m_statusEffectInfoMap; std::map > m_aetheryteInfoMap; std::map m_tribeInfoMap; @@ -317,6 +317,7 @@ namespace Core { boost::shared_ptr< OpeningInfo > getOpeningInfo( uint32_t openingId ); boost::shared_ptr< CustomTalkInfo > getCustomTalkInfo( uint32_t customTalkId ); boost::shared_ptr< AetheryteInfo > getAetheryteInfo( uint32_t aetheryteId ); + boost::shared_ptr< ActionInfo > getActionInfo( uint32_t actionId ); boost::shared_ptr< PlaceNameInfo > getPlaceNameInfo( uint32_t placeNameId ); boost::shared_ptr< ItemInfo > getItemInfo( uint32_t catalogId ); boost::shared_ptr< RaceInfo > getRaceInfo( uint32_t raceId ); diff --git a/src/servers/Server_Common/Network/PacketDef/Ipcs.h b/src/servers/Server_Common/Network/PacketDef/Ipcs.h index d18c36f6..b4ade11c 100644 --- a/src/servers/Server_Common/Network/PacketDef/Ipcs.h +++ b/src/servers/Server_Common/Network/PacketDef/Ipcs.h @@ -116,6 +116,7 @@ namespace Packets { WeatherChange = 0x01AF, // updated for sb Discovery = 0x01B2, // updated for sb + EorzeaTimeOffset = 0x01B4, CFAvailableContents = 0x01CF, diff --git a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h index 6bf6759b..10a34cd0 100644 --- a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h @@ -301,12 +301,12 @@ struct FFXIVIpcUpdateHpMpTp : FFXIVIpcBasePacket */ struct effectEntry { - uint8_t unknown_1; - uint8_t unknown_2; + Common::ActionEffectType effectType; + Common::ActionHitSeverityType hitSeverity; uint8_t unknown_3; int8_t bonusPercent; - int16_t param1; - uint8_t unknown_5; + int16_t value; + uint8_t valueMultiplier; // This multiplies whatever value is in the 'value' param by 10. Possibly a workaround for big numbers uint8_t unknown_6; }; @@ -1281,6 +1281,11 @@ struct FFXIVIpcCFMemberStatus : FFXIVIpcBasePacket uint32_t unknown3; }; +struct FFXIVIpcEorzeaTimeOffset : FFXIVIpcBasePacket +{ + uint64_t timestamp; +}; + } /* Server */ diff --git a/src/servers/Server_Common/Version.cpp.in b/src/servers/Server_Common/Version.cpp.in new file mode 100644 index 00000000..4a7bacda --- /dev/null +++ b/src/servers/Server_Common/Version.cpp.in @@ -0,0 +1,10 @@ +#include "Version.h" + +namespace Core { + namespace Version { + + const std::string GIT_HASH = "@GIT_SHA1@"; + const std::string VERSION = "@VERSION@"; + + } /* Version */ +} /* Core */ diff --git a/src/servers/Server_Common/Version.h b/src/servers/Server_Common/Version.h new file mode 100644 index 00000000..3a02b99e --- /dev/null +++ b/src/servers/Server_Common/Version.h @@ -0,0 +1,15 @@ +#ifndef _VERSION_H +#define _VERSION_H + +#include + +namespace Core { + namespace Version { + + extern const std::string GIT_HASH; + extern const std::string VERSION; + + } /* Version */ +} /* Core */ + +#endif diff --git a/src/servers/Server_REST/PlayerMinimal.cpp b/src/servers/Server_REST/PlayerMinimal.cpp index d7fc2f27..9643a35b 100644 --- a/src/servers/Server_REST/PlayerMinimal.cpp +++ b/src/servers/Server_REST/PlayerMinimal.cpp @@ -70,7 +70,7 @@ namespace Core { setBirthDay( field[2].get< int8_t >(), field[3].get< int8_t >() ); m_guardianDeity = field[4].get< int8_t >(); m_class = field[5].get< int8_t >(); - m_contentId = field[7].get< uint64_t >(); + m_contentId = field[7].getUInt64(); m_zoneId = field[8].get< uint16_t >(); auto pQR2 = g_database.query( "SELECT * FROM characlass WHERE CharacterId = " + std::to_string( charId ) + ";" ); diff --git a/src/servers/Server_REST/PlayerMinimal.h b/src/servers/Server_REST/PlayerMinimal.h index 01083752..26b3b753 100644 --- a/src/servers/Server_REST/PlayerMinimal.h +++ b/src/servers/Server_REST/PlayerMinimal.h @@ -30,7 +30,7 @@ namespace Core { std::string getClassString(); // return the id of the actor - uint32_t getId() + uint32_t getId() const { return m_iD; } @@ -45,13 +45,13 @@ namespace Core { m_contentId = id; } - uint64_t getContentId() + uint64_t getContentId() const { return m_contentId; } - uint32_t getAccountId() + uint32_t getAccountId() const { return m_accountId; } @@ -84,12 +84,12 @@ namespace Core { m_class = classId; } - uint8_t getClass() + uint8_t getClass() const { return m_class; } - uint8_t getGuardianDeity() + uint8_t getGuardianDeity() const { return m_guardianDeity; } @@ -105,17 +105,17 @@ namespace Core { m_birthMonth = month; } - uint8_t getBirthDay() + uint8_t getBirthDay() const { return m_birthDay; } - uint8_t getBirthMonth() + uint8_t getBirthMonth() const { return m_birthMonth; } - uint8_t getVoice() + uint8_t getVoice() const { return m_birthMonth; } @@ -125,12 +125,12 @@ namespace Core { m_voice = voice; } - uint32_t getZoneId() + uint32_t getZoneId() const { return m_zoneId; } - uint32_t getTribe() + uint32_t getTribe() const { return m_tribe; } @@ -140,9 +140,9 @@ namespace Core { m_tribe = tribe; } - uint8_t getGmRank() + uint8_t getGmRank() const { - return m_birthMonth; + return m_gmRank; } void setGmRank( uint8_t rank ) diff --git a/src/servers/Server_REST/SapphireAPI.cpp b/src/servers/Server_REST/SapphireAPI.cpp index 38dd0bb7..bf415fbb 100644 --- a/src/servers/Server_REST/SapphireAPI.cpp +++ b/src/servers/Server_REST/SapphireAPI.cpp @@ -277,7 +277,7 @@ uint64_t Core::Network::SapphireAPI::getNextContentId() return 0x0040000001000001; } - contentId = pQR->fetch()[0].get< uint64_t >() + 1; + contentId = pQR->fetch()[0].getUInt64() + 1; if( contentId < 0x0040000001000001 ) { return 0x0040000001000001; diff --git a/src/servers/Server_Zone/Action/ActionCast.cpp b/src/servers/Server_Zone/Action/ActionCast.cpp index b22ab5d8..16d07d8b 100644 --- a/src/servers/Server_Zone/Action/ActionCast.cpp +++ b/src/servers/Server_Zone/Action/ActionCast.cpp @@ -8,6 +8,7 @@ #include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h" #include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h" +#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket144.h" #include "src/servers/Server_Zone/Actor/Player.h" #include "src/servers/Server_Zone/Script/ScriptManager.h" @@ -30,7 +31,7 @@ Core::Action::ActionCast::ActionCast( Entity::ActorPtr pActor, Entity::ActorPtr m_startTime = 0; m_id = actionId; m_handleActionType = HandleActionType::Spell; - m_castTime = g_exdData.m_actionInfoMap[actionId].cast_time; // TODO: Add security checks. + m_castTime = g_exdData.getActionInfo( actionId )->cast_time; // TODO: Add security checks. m_pSource = pActor; m_pTarget = pTarget; m_bInterrupt = false; @@ -53,10 +54,11 @@ void Core::Action::ActionCast::onStart() castPacket.data().action_id = m_id; castPacket.data().unknown = 1; - castPacket.data().cast_time = m_castTime / 1000; // This is used for the cast bar above the target bar of the caster. + castPacket.data().unknown_1 = m_id; + castPacket.data().cast_time = static_cast< float >( m_castTime / 1000 ); // This is used for the cast bar above the target bar of the caster. castPacket.data().target_id = m_pTarget->getId(); - m_pSource->sendToInRangeSet( castPacket, false ); + m_pSource->sendToInRangeSet( castPacket, true ); m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::Casting ); m_pSource->getAsPlayer()->sendStateFlags(); @@ -73,6 +75,10 @@ void Core::Action::ActionCast::onFinish() pPlayer->unsetStateFlag( PlayerStateFlag::Casting ); pPlayer->sendStateFlags(); + /*auto control = ActorControlPacket143( m_pTarget->getId(), ActorControlType::Unk7, + 0x219, m_id, m_id, m_id, m_id ); + m_pSource->sendToInRangeSet( control, true );*/ + g_scriptMgr.onCastFinish( pPlayer, m_pTarget, m_id ); } @@ -86,7 +92,7 @@ void Core::Action::ActionCast::onInterrupt() m_pSource->getAsPlayer()->sendStateFlags(); auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, - 0x219, 0x04, m_id, 1 ); + 0x219, 1, m_id, 1 ); m_pSource->sendToInRangeSet( control, true ); } diff --git a/src/servers/Server_Zone/Action/ActionTeleport.cpp b/src/servers/Server_Zone/Action/ActionTeleport.cpp index 06207db0..22705d71 100644 --- a/src/servers/Server_Zone/Action/ActionTeleport.cpp +++ b/src/servers/Server_Zone/Action/ActionTeleport.cpp @@ -26,7 +26,7 @@ Core::Action::ActionTeleport::ActionTeleport( Entity::ActorPtr pActor, uint16_t m_startTime = 0; m_id = 5; m_handleActionType = HandleActionType::Teleport; - m_castTime = g_exdData.m_actionInfoMap[5].cast_time; // TODO: Add security checks. + m_castTime = g_exdData.getActionInfo(5)->cast_time; // TODO: Add security checks. m_pSource = pActor; m_bInterrupt = false; m_targetAetheryte = targetZone; diff --git a/src/servers/Server_Zone/Actor/Actor.cpp b/src/servers/Server_Zone/Actor/Actor.cpp index 65053d30..1b4e3c38 100644 --- a/src/servers/Server_Zone/Actor/Actor.cpp +++ b/src/servers/Server_Zone/Actor/Actor.cpp @@ -595,7 +595,7 @@ void Core::Entity::Actor::autoAttack( ActorPtr pTarget ) srand( static_cast< uint32_t >( tick ) ); uint32_t damage = 10 + rand() % 12; - uint32_t variation = 0 + rand() % 3; + uint32_t variation = 0 + rand() % 4; GamePacketNew< FFXIVIpcEffect, ServerZoneIpcType > effectPacket( getId() ); effectPacket.data().targetId = pTarget->getId(); @@ -606,9 +606,9 @@ void Core::Entity::Actor::autoAttack( ActorPtr pTarget ) effectPacket.data().numEffects = 1; effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() ); effectPacket.data().effectTarget = pTarget->getId(); - effectPacket.data().effects[0].param1 = damage; - effectPacket.data().effects[0].unknown_1 = 3; - effectPacket.data().effects[0].unknown_2 = 1; + effectPacket.data().effects[0].value = damage; + effectPacket.data().effects[0].effectType = ActionEffectType::Damage; + effectPacket.data().effects[0].hitSeverity = static_cast< ActionHitSeverityType >( variation ); effectPacket.data().effects[0].unknown_3 = 7; sendToInRangeSet( effectPacket ); @@ -627,26 +627,26 @@ void Core::Entity::Actor::addStatusEffect( StatusEffect::StatusEffectPtr pEffect } /*! \param StatusEffectPtr to be applied to the actor */ -void Core::Entity::Actor::addStatusEffectById( int32_t id, int32_t duration, uint16_t param ) +void Core::Entity::Actor::addStatusEffectById( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param ) { - StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, shared_from_this(), shared_from_this(), duration, 3000 ) ); + StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, pSource.shared_from_this(), shared_from_this(), duration, 3000 ) ); effect->setParam( param ); addStatusEffect( effect ); } /*! \param StatusEffectPtr to be applied to the actor */ -void Core::Entity::Actor::addStatusEffectByIdIfNotExist( int32_t id, int32_t duration, uint16_t param ) +void Core::Entity::Actor::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param ) { if( !m_pStatusEffectContainer->hasStatusEffect( id ) ) { - StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, shared_from_this(), shared_from_this(), duration, 3000 ) ); + StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, pSource.shared_from_this(), shared_from_this(), duration, 3000 ) ); effect->setParam( param ); addStatusEffect( effect ); } } /*! \param Status that should be removed, based on its ID. */ -void Core::Entity::Actor::removeSingleStatusEffectFromId( int32_t id ) +void Core::Entity::Actor::removeSingleStatusEffectFromId( uint32_t id ) { m_pStatusEffectContainer->removeSingleStatusEffectFromId( id ); } diff --git a/src/servers/Server_Zone/Actor/Actor.h b/src/servers/Server_Zone/Actor/Actor.h index e975d9a3..de6b9118 100644 --- a/src/servers/Server_Zone/Actor/Actor.h +++ b/src/servers/Server_Zone/Actor/Actor.h @@ -293,13 +293,13 @@ public: void addStatusEffect( StatusEffect::StatusEffectPtr pEffect ); // add a status effect by id - void addStatusEffectById( int32_t id, int32_t duration, uint16_t param = 0 ); + void addStatusEffectById( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param = 0 ); // add a status effect by id if it doesn't exist - void addStatusEffectByIdIfNotExist( int32_t id, int32_t duration, uint16_t param = 0 ); + void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param = 0 ); // remove a status effect by id - void removeSingleStatusEffectFromId( int32_t id ); + void removeSingleStatusEffectFromId( uint32_t id ); //get the status effect container StatusEffect::StatusEffectContainerPtr getStatusEffectContainer() const; diff --git a/src/servers/Server_Zone/Actor/BattleNpc.cpp b/src/servers/Server_Zone/Actor/BattleNpc.cpp index 436e072f..b9891203 100644 --- a/src/servers/Server_Zone/Actor/BattleNpc.cpp +++ b/src/servers/Server_Zone/Actor/BattleNpc.cpp @@ -425,7 +425,7 @@ void Core::Entity::BattleNpc::onDeath() // todo: check for companion if( pHateEntry->m_pActor->isPlayer() ) // && pHateEntry->m_hateAmount >= plsBeHatedThisMuchAtLeast ) { - auto level = pHateEntry->m_pActor->getLevel(); + uint8_t level = pHateEntry->m_pActor->getLevel(); auto levelDiff = (int)this->m_level - (int)level; auto cappedLevelDiff = Math::Util::clamp( levelDiff, 1, 6 ); diff --git a/src/servers/Server_Zone/Actor/CalcBattle.cpp b/src/servers/Server_Zone/Actor/CalcBattle.cpp index fd7f84f4..f33c2e5c 100644 --- a/src/servers/Server_Zone/Actor/CalcBattle.cpp +++ b/src/servers/Server_Zone/Actor/CalcBattle.cpp @@ -29,7 +29,7 @@ extern Core::Data::ExdData g_exdData; // 3 Versions. SB and HW are linear, ARR is polynomial. // Originally from Player.cpp, calculateStats(). -uint32_t CalcBattle::calculateBaseStat( PlayerPtr pPlayer ) +float CalcBattle::calculateBaseStat( PlayerPtr pPlayer ) { float base = 0.0f; uint8_t level = pPlayer->getLevel(); @@ -37,7 +37,7 @@ uint32_t CalcBattle::calculateBaseStat( PlayerPtr pPlayer ) // SB Base Stat Formula (Aligned) if ( level > 60 ) { - base = ( ( ( level == 61) ? 224 : 220 ) + ( level - 61 ) * 8); + base = ( ( ( level == 61 ) ? 224 : 220 ) + ( level - 61 ) * 8); } // HW Base Stat Formula (Aligned) else if ( level > 50 ) @@ -85,7 +85,7 @@ uint32_t CalcBattle::calculateMaxHp( PlayerPtr pPlayer ) else approxBaseHp = paramGrowthInfoIt->second.mp_const * 0.7596f; - uint16_t result = floor( jobModHp * ( approxBaseHp / 100.0f ) ) + floor( hpMod / 100.0f * ( vitStat - baseStat ) ); + uint16_t result = static_cast< uint16_t >( floor( jobModHp * ( approxBaseHp / 100.0f ) ) + floor( hpMod / 100.0f * ( vitStat - baseStat ) ) ); return result; } @@ -108,7 +108,7 @@ uint32_t CalcBattle::calculateMaxMp( PlayerPtr pPlayer ) uint16_t jobModMp = classInfoIt->second.mod_mpcpgp; uint16_t baseMp = paramGrowthInfoIt->second.mp_const; - uint16_t result = floor( floor( piety - baseStat ) * ( pietyScalar / 100 ) + baseMp ) * jobModMp / 100; + uint16_t result = static_cast< uint16_t >( floor( floor( piety - baseStat ) * ( pietyScalar / 100 ) + baseMp ) * jobModMp / 100 ); return result; } diff --git a/src/servers/Server_Zone/Actor/CalcBattle.h b/src/servers/Server_Zone/Actor/CalcBattle.h index 9d0cdcb1..f4885725 100644 --- a/src/servers/Server_Zone/Actor/CalcBattle.h +++ b/src/servers/Server_Zone/Actor/CalcBattle.h @@ -12,7 +12,7 @@ namespace Entity { { public: - static uint32_t calculateBaseStat( PlayerPtr pPlayer ); + static float calculateBaseStat( PlayerPtr pPlayer ); static uint32_t calculateMaxMp( PlayerPtr pPlayer ); static uint32_t calculateMaxHp( PlayerPtr pPlayer ); static uint32_t calculateHealValue( PlayerPtr pPlayer, uint32_t potency ); diff --git a/src/servers/Server_Zone/Actor/Player.cpp b/src/servers/Server_Zone/Actor/Player.cpp index 07436ae4..49bc2ad3 100644 --- a/src/servers/Server_Zone/Actor/Player.cpp +++ b/src/servers/Server_Zone/Actor/Player.cpp @@ -218,12 +218,12 @@ void Core::Entity::Player::calculateStats() // TODO: put formula somewhere else... float base = CalcBattle::calculateBaseStat( getAsPlayer() ); - m_baseStats.str = base * ( static_cast< float >( classInfo.mod_str ) / 100 ) + tribeInfo.mod_str; - m_baseStats.dex = base * ( static_cast< float >( classInfo.mod_dex ) / 100 ) + tribeInfo.mod_dex; - m_baseStats.vit = base * ( static_cast< float >( classInfo.mod_vit ) / 100 ) + tribeInfo.mod_vit; - m_baseStats.inte = base * ( static_cast< float >( classInfo.mod_int ) / 100 ) + tribeInfo.mod_int; - m_baseStats.mnd = base * ( static_cast< float >( classInfo.mod_mnd ) / 100 ) + tribeInfo.mod_mnd; - m_baseStats.pie = base * ( static_cast< float >( classInfo.mod_pie ) / 100 ) + tribeInfo.mod_pie; + m_baseStats.str = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_str ) / 100 ) + tribeInfo.mod_str ); + m_baseStats.dex = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_dex ) / 100 ) + tribeInfo.mod_dex ); + m_baseStats.vit = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_vit ) / 100 ) + tribeInfo.mod_vit ); + m_baseStats.inte = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_int ) / 100 ) + tribeInfo.mod_int ); + m_baseStats.mnd = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_mnd ) / 100 ) + tribeInfo.mod_mnd ); + m_baseStats.pie = static_cast< uint32_t >( base * ( static_cast< float >( classInfo.mod_pie ) / 100 ) + tribeInfo.mod_pie ); m_baseStats.skillSpeed = paramGrowthInfo.base_secondary; m_baseStats.spellSpeed = paramGrowthInfo.base_secondary; @@ -243,7 +243,7 @@ void Core::Entity::Player::calculateStats() m_hp = m_baseStats.max_hp; - m_baseStats.determination = base; + m_baseStats.determination = static_cast< uint32_t >( base ); } @@ -513,7 +513,7 @@ bool Core::Entity::Player::isAetheryteRegistered( uint8_t aetheryteId ) const uint8_t value; Util::valueToFlagByteIndexValue( aetheryteId, value, index ); - return m_aetheryte[index] & value; + return ( m_aetheryte[index] & value ) != 0; } uint8_t * Core::Entity::Player::getDiscoveryBitmask() @@ -608,7 +608,7 @@ bool Core::Entity::Player::isActionLearned( uint8_t actionId ) const uint8_t value; Util::valueToFlagByteIndexValue( actionId, value, index ); - return m_unlocks[index] & value; + return ( m_unlocks[index] & value ) != 0; } void Core::Entity::Player::gainExp( uint32_t amount ) @@ -980,10 +980,11 @@ const uint8_t * Core::Entity::Player::getStateFlags() const bool Core::Entity::Player::actionHasCastTime( uint32_t actionId ) //TODO: Add logic for special cases { - if( g_exdData.m_actionInfoMap[actionId].is_instant ) + auto actionInfoPtr = g_exdData.getActionInfo( actionId ); + if( actionInfoPtr->is_instant ) return false; - if( g_exdData.m_actionInfoMap[actionId].cast_time == 0 ) + if( actionInfoPtr->cast_time == 0 ) return false; return true; @@ -997,7 +998,7 @@ bool Core::Entity::Player::hasStateFlag( Core::Common::PlayerStateFlag flag ) co uint8_t value; Util::valueToFlagByteIndexValue( iFlag, value, index ); - return m_stateFlags[index] & value; + return ( m_stateFlags[index] & value ) != 0; } void Core::Entity::Player::setStateFlag( Core::Common::PlayerStateFlag flag ) @@ -1463,7 +1464,7 @@ void Core::Entity::Player::autoAttack( ActorPtr pTarget ) //uint64_t tick = Util::getTimeMs(); //srand(static_cast< uint32_t >(tick)); - uint32_t damage = mainWeap->getAutoAttackDmg(); + uint32_t damage = static_cast< uint32_t >( mainWeap->getAutoAttackDmg() ); uint32_t variation = 0 + rand() % 3; if ( getClass() == JOB_MACHINIST || @@ -1481,9 +1482,9 @@ void Core::Entity::Player::autoAttack( ActorPtr pTarget ) effectPacket.data().rotation = Math::Util::floatToUInt16Rot(getRotation()); effectPacket.data().effectTargetId = pTarget->getId(); effectPacket.data().effectTarget = pTarget->getId(); - effectPacket.data().effects[0].param1 = damage; - effectPacket.data().effects[0].unknown_1 = 3; - effectPacket.data().effects[0].unknown_2 = 1; + effectPacket.data().effects[0].value = damage; + effectPacket.data().effects[0].effectType = Common::ActionEffectType::Damage; + effectPacket.data().effects[0].hitSeverity = Common::ActionHitSeverityType::NormalDamage; effectPacket.data().effects[0].unknown_3 = 7; sendToInRangeSet(effectPacket, true); @@ -1501,9 +1502,9 @@ void Core::Entity::Player::autoAttack( ActorPtr pTarget ) effectPacket.data().actionTextId = 7; effectPacket.data().rotation = Math::Util::floatToUInt16Rot(getRotation()); effectPacket.data().effectTarget = pTarget->getId(); - effectPacket.data().effects[0].param1 = damage; - effectPacket.data().effects[0].unknown_1 = 3; - effectPacket.data().effects[0].unknown_2 = 2; + effectPacket.data().effects[0].value = damage; + effectPacket.data().effects[0].effectType = Common::ActionEffectType::Damage; + effectPacket.data().effects[0].hitSeverity = Common::ActionHitSeverityType::NormalDamage; effectPacket.data().effects[0].unknown_3 = 71; sendToInRangeSet(effectPacket, true); @@ -1517,6 +1518,9 @@ void Core::Entity::Player::handleScriptSkill( uint32_t type, uint32_t actionId, { sendDebug( std::to_string( pTarget.getId() ) ); sendDebug( "Handle script skill type: " + std::to_string( type ) ); + + auto actionInfoPtr = g_exdData.getActionInfo( actionId ); + switch( type ) { @@ -1534,9 +1538,9 @@ void Core::Entity::Player::handleScriptSkill( uint32_t type, uint32_t actionId, effectPacket.data().numEffects = 1; effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() ); effectPacket.data().effectTarget = pTarget.getId(); - effectPacket.data().effects[0].param1 = param1; - effectPacket.data().effects[0].unknown_1 = 3; - effectPacket.data().effects[0].unknown_2 = 1; + effectPacket.data().effects[0].value = static_cast< int16_t >( param1 ); + effectPacket.data().effects[0].effectType = ActionEffectType::Damage; + effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalDamage; effectPacket.data().effects[0].unknown_3 = 7; sendToInRangeSet( effectPacket, true ); @@ -1544,14 +1548,14 @@ void Core::Entity::Player::handleScriptSkill( uint32_t type, uint32_t actionId, if ( !pTarget.isAlive() ) break; - pTarget.takeDamage( param1 ); + pTarget.takeDamage( static_cast< uint32_t >( param1 ) ); pTarget.onActionHostile( shared_from_this() ); break; } case Core::Common::HandleSkillType::StdHeal: { - uint32_t calculatedHeal = CalcBattle::calculateHealValue( getAsPlayer(), param1 ); + uint32_t calculatedHeal = CalcBattle::calculateHealValue( getAsPlayer(), static_cast< uint32_t >( param1 ) ); sendDebug( "STD_HEAL" ); @@ -1564,9 +1568,9 @@ void Core::Entity::Player::handleScriptSkill( uint32_t type, uint32_t actionId, effectPacket.data().numEffects = 1; effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() ); effectPacket.data().effectTarget = pTarget.getId(); - effectPacket.data().effects[0].param1 = calculatedHeal; - effectPacket.data().effects[0].unknown_1 = 4; - effectPacket.data().effects[0].unknown_2 = 1; + effectPacket.data().effects[0].value = calculatedHeal; + effectPacket.data().effects[0].effectType = ActionEffectType::Heal; + effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalHeal; effectPacket.data().effects[0].unknown_3 = 7; sendToInRangeSet( effectPacket, true ); @@ -1574,6 +1578,41 @@ void Core::Entity::Player::handleScriptSkill( uint32_t type, uint32_t actionId, if ( !pTarget.isAlive() ) break; + // todo: get proper packets: the following was just kind of thrown together from what we know + // also toss AoE to another spot and make it generic + + if ( actionInfoPtr->is_aoe ) + { + for ( auto pCurAct : m_inRangePlayers ) + { + assert( pCurAct ); + if ( !pCurAct->isAlive() ) + break; + + if ( Math::Util::distance( pTarget.getPos().x, pTarget.getPos().y, pTarget.getPos().z, pCurAct->getPos().x, pCurAct->getPos().y, pCurAct->getPos().z ) <= actionInfoPtr->radius ) + { + GamePacketNew< FFXIVIpcEffect, ServerZoneIpcType > effectPacket( pCurAct->getId() ); + effectPacket.data().targetId = pCurAct->getId(); + effectPacket.data().unknown_1 = 1; // the magic trick for getting it to work + effectPacket.data().unknown_2 = 1; + effectPacket.data().unknown_8 = 1; + effectPacket.data().unknown_5 = 1; + effectPacket.data().actionAnimationId = actionId; + effectPacket.data().actionTextId = 0; + effectPacket.data().numEffects = 1; + effectPacket.data().effectTarget = pCurAct->getId(); + effectPacket.data().effects[0].value = calculatedHeal; + effectPacket.data().effects[0].effectType = ActionEffectType::Heal; + effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalHeal; + effectPacket.data().effects[0].unknown_3 = 7; + + pCurAct->sendToInRangeSet( effectPacket, true ); + pCurAct->heal( calculatedHeal ); + sendDebug( "AoE hit actor " + pCurAct->getName() ); + } + } + } + pTarget.heal( calculatedHeal ); break; } @@ -1628,4 +1667,15 @@ void Core::Entity::Player::setOpeningSequence( uint8_t seq ) { setSyncFlag( OpeningSeq ); m_openingSequence = seq; -} \ No newline at end of file +} + +/// Tells client to offset their eorzean time by given timestamp. +void Core::Entity::Player::setEorzeaTimeOffset( uint64_t timestamp ) +{ + // TODO: maybe change to persistent? + GamePacketNew< FFXIVIpcEorzeaTimeOffset, ServerZoneIpcType > packet ( getId() ); + packet.data().timestamp = timestamp; + + // Send to single player + queuePacket( packet ); +} diff --git a/src/servers/Server_Zone/Actor/Player.h b/src/servers/Server_Zone/Actor/Player.h index a34d8a46..907a5916 100644 --- a/src/servers/Server_Zone/Actor/Player.h +++ b/src/servers/Server_Zone/Actor/Player.h @@ -499,6 +499,10 @@ public: uint32_t getCFPenaltyMinutes() const; void setCFPenaltyMinutes( uint32_t minutes ); + + void setEorzeaTimeOffset( uint64_t timestamp ); + + private: uint32_t m_lastWrite; uint32_t m_lastPing; diff --git a/src/servers/Server_Zone/Actor/PlayerEvent.cpp b/src/servers/Server_Zone/Actor/PlayerEvent.cpp index 1240c800..f0bf77fe 100644 --- a/src/servers/Server_Zone/Actor/PlayerEvent.cpp +++ b/src/servers/Server_Zone/Actor/PlayerEvent.cpp @@ -264,14 +264,14 @@ void Core::Entity::Player::onTick() if( !isAlive() || !isLoadingComplete() ) return; - int32_t addHp = getMaxHp() * 0.1f + 1; - int32_t addMp = getMaxMp() * 0.06f + 1; - int32_t addTp = 100; + uint32_t addHp = static_cast< uint32_t >( getMaxHp() * 0.1f + 1 ); + uint32_t addMp = static_cast< uint32_t >( getMaxMp() * 0.06f + 1 ); + uint32_t addTp = 100; if( !m_actorIdTohateSlotMap.empty() ) { - addHp = getMaxHp() * 0.01f + 1; - addMp = getMaxHp() * 0.02f + 1; + addHp = static_cast< uint32_t >( getMaxHp() * 0.01f + 1 ); + addMp = static_cast< uint32_t >( getMaxMp() * 0.02f + 1 ); addTp = 60; } diff --git a/src/servers/Server_Zone/Actor/PlayerQuest.cpp b/src/servers/Server_Zone/Actor/PlayerQuest.cpp index e1965c8a..c6038f61 100644 --- a/src/servers/Server_Zone/Actor/PlayerQuest.cpp +++ b/src/servers/Server_Zone/Actor/PlayerQuest.cpp @@ -74,7 +74,7 @@ bool Core::Entity::Player::loadActiveQuests() void Core::Entity::Player::finishQuest( uint16_t questId ) { - int8_t idx = getQuestIndex( questId ); + int8_t idx = getQuestIndex( static_cast< uint16_t >( questId ) ); if( ( idx != -1 ) && ( m_activeQuests[idx] != nullptr ) ) { @@ -123,7 +123,7 @@ void Core::Entity::Player::unfinishQuest( uint16_t questId ) void Core::Entity::Player::removeQuest( uint16_t questId ) { - int8_t idx = getQuestIndex( questId ); + int8_t idx = getQuestIndex( static_cast< uint16_t >( questId ) ); if( ( idx != -1 ) && ( m_activeQuests[idx] != nullptr ) ) { diff --git a/src/servers/Server_Zone/Actor/PlayerSql.cpp b/src/servers/Server_Zone/Actor/PlayerSql.cpp index 4de7d019..7d5db611 100644 --- a/src/servers/Server_Zone/Actor/PlayerSql.cpp +++ b/src/servers/Server_Zone/Actor/PlayerSql.cpp @@ -131,7 +131,7 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession ) field[11].getBinary( reinterpret_cast< char* >( m_customize ), sizeof( m_customize ) ); - m_modelMainWeapon = field[12].get< uint64_t >(); + m_modelMainWeapon = field[12].getUInt64(); field[14].getBinary( reinterpret_cast< char* >( m_modelEquip ), sizeof( m_modelEquip ) ); @@ -144,7 +144,7 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession ) field[21].getBinary( reinterpret_cast< char* >( m_howTo ), sizeof( m_howTo ) ); - m_contentId = field[22].get< uint64_t >(); + m_contentId = field[22].getUInt64(); m_voice = field[23].get< uint32_t >(); diff --git a/src/servers/Server_Zone/DebugCommand/DebugCommand.h b/src/servers/Server_Zone/DebugCommand/DebugCommand.h index a35e72f1..082995fa 100644 --- a/src/servers/Server_Zone/DebugCommand/DebugCommand.h +++ b/src/servers/Server_Zone/DebugCommand/DebugCommand.h @@ -29,14 +29,14 @@ namespace Core { std::string m_helpText; // userlevel needed to execute the command - Common::UserLevel m_userLevel; + uint8_t m_gmLevel; - DebugCommand( const std::string& n, pFunc functionPtr, const std::string& hText, Common::UserLevel uLevel ) + DebugCommand( const std::string& n, pFunc functionPtr, const std::string& hText, uint8_t uLevel ) { m_commandName = n; m_pFunc = functionPtr; m_helpText = hText; - m_userLevel = uLevel; + m_gmLevel = uLevel; } ~DebugCommand() @@ -54,9 +54,9 @@ namespace Core { return m_helpText; } - Common::UserLevel getUserLevel() const + uint8_t getRequiredGmLevel() const { - return m_userLevel; + return m_gmLevel; } }; diff --git a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp index eaf9c731..6a4f6e84 100644 --- a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -39,16 +40,15 @@ extern Core::ServerZone g_serverZone; // instanciate and initialize commands Core::DebugCommandHandler::DebugCommandHandler() { - - // Push all commands onto the register map - registerCommand( "set", &DebugCommandHandler::set, "Loads and injects a premade Packet.", Common::UserLevel::all ); - registerCommand( "get", &DebugCommandHandler::get, "Loads and injects a premade Packet.", Common::UserLevel::all ); - registerCommand( "add", &DebugCommandHandler::add, "Loads and injects a premade Packet.", Common::UserLevel::all ); - //registerCommand( "debug", &DebugCommandHandler::debug, "Loads and injects a premade Packet.", Common::UserLevel::all ); - registerCommand( "inject", &DebugCommandHandler::injectPacket, "Loads and injects a premade Packet.", Common::UserLevel::all ); - registerCommand( "injectc", &DebugCommandHandler::injectChatPacket, "Loads and injects a premade Packet.", Common::UserLevel::all ); - registerCommand( "script_reload", &DebugCommandHandler::scriptReload, "Loads and injects a premade Packet.", Common::UserLevel::all ); - registerCommand( "nudge", &DebugCommandHandler::nudge, "Nudges you forward/up/down", Common::UserLevel::all ); + // Push all commands onto the register map ( command name - function - description - required GM level ) + registerCommand( "set", &DebugCommandHandler::set, "Loads and injects a premade Packet.", 1 ); + registerCommand( "get", &DebugCommandHandler::get, "Loads and injects a premade Packet.", 1 ); + registerCommand( "add", &DebugCommandHandler::add, "Loads and injects a premade Packet.", 1 ); + registerCommand( "inject", &DebugCommandHandler::injectPacket, "Loads and injects a premade Packet.", 1 ); + registerCommand( "injectc", &DebugCommandHandler::injectChatPacket, "Loads and injects a premade Packet.", 1 ); + registerCommand( "script_reload", &DebugCommandHandler::scriptReload, "Loads and injects a premade Packet.", 1 ); + registerCommand( "nudge", &DebugCommandHandler::nudge, "Nudges you forward/up/down", 1 ); + registerCommand( "info", &DebugCommandHandler::serverInfo, "Send server info", 0 ); } @@ -61,7 +61,7 @@ Core::DebugCommandHandler::~DebugCommandHandler() // add a command set to the register map void Core::DebugCommandHandler::registerCommand( const std::string& n, Core::DebugCommand::pFunc functionPtr, - const std::string& hText, Core::Common::UserLevel uLevel ) + const std::string& hText, uint8_t uLevel ) { m_commandMap[std::string( n )] = boost::make_shared( n, functionPtr, hText, uLevel ); } @@ -70,12 +70,6 @@ void Core::DebugCommandHandler::registerCommand( const std::string& n, Core::Deb void Core::DebugCommandHandler::execCommand( char * data, Core::Entity::PlayerPtr pPlayer ) { - if( pPlayer->getGmRank() <= 0 ) - { - pPlayer->sendUrgent( "You are not allowed to use debug commands." ); - return; - } - // define callback pointer void ( DebugCommandHandler::*pf )( char *, Entity::PlayerPtr, boost::shared_ptr< DebugCommand > ); @@ -98,9 +92,14 @@ void Core::DebugCommandHandler::execCommand( char * data, Core::Entity::PlayerPt if( it == m_commandMap.end() ) // no command found, do something... or not pPlayer->sendUrgent( "Command not found." ); - // TODO Notify the client of the failed command else { + if( pPlayer->getGmRank() < it->second->getRequiredGmLevel() ) + { + pPlayer->sendUrgent( "You are not allowed to use this command." ); + return; + } + // command found, call the callback function and pass parameters if present. pf = ( *it ).second->m_pFunc; ( this->*pf )( data, pPlayer, ( *it ).second ); @@ -176,33 +175,6 @@ void Core::DebugCommandHandler::set( char * data, Core::Entity::PlayerPtr pPlaye pPlayer->queuePacket( setActorPosPacket ); } - else if( ( subCommand == "zone" ) && ( params != "" ) ) - { - int32_t zoneId; - sscanf( params.c_str(), "%i", &zoneId ); - - if( zoneId < 1 ) - pPlayer->sendUrgent( "Zone id out of range." ); - else - { - pPlayer->setPosition( pPlayer->getPos() ); - pPlayer->performZoning( zoneId, pPlayer->getPos(), 0); - } - - } - else if( ( subCommand == "hp" ) && ( params != "" ) ) - { - int32_t hp; - sscanf( params.c_str(), "%i", &hp ); - - pPlayer->setHp( hp ); - - auto control = Network::Packets::Server::ActorControlPacket142( pPlayer->getId(), Common::ActorControlType::HpSetStat, 1, pPlayer->getHp() ); - - pPlayer->sendToInRangeSet( control, true ); - - } - else if( ( subCommand == "tele" ) && ( params != "" ) ) { int32_t aetheryteId; @@ -213,8 +185,8 @@ void Core::DebugCommandHandler::set( char * data, Core::Entity::PlayerPtr pPlaye else if( ( subCommand == "unlockaetheryte" ) && ( params != "" ) ) { - for( uint8_t i = 0; i < 255; i++ ) - pPlayer->registerAetheryte( i ); + for( uint8_t i = 0; i < 255; i++ ) + pPlayer->registerAetheryte( i ); } else if( ( subCommand == "discovery" ) && ( params != "" ) ) @@ -282,18 +254,25 @@ void Core::DebugCommandHandler::set( char * data, Core::Entity::PlayerPtr pPlaye else if( subCommand == "aaah" ) { int32_t id; - sscanf( params.c_str(), "%d", &id ); + pPlayer->sendDebug( std::to_string( pPlayer->actionHasCastTime( id ) ) ); } else if ( subCommand == "cfpenalty" ) { int32_t minutes; - sscanf( params.c_str(), "%d", &minutes ); pPlayer->setCFPenaltyMinutes( minutes ); } + else if ( subCommand == "eorzeatime" ) + { + uint64_t timestamp; + sscanf( params.c_str(), "%llu", ×tamp ); + + pPlayer->setEorzeaTimeOffset( timestamp ); + pPlayer->sendNotice( "Eorzea time offset: " + std::to_string( timestamp ) ); + } } @@ -324,37 +303,7 @@ void Core::DebugCommandHandler::add( char * data, Core::Entity::PlayerPtr pPlaye "subCommand " + subCommand + " params: " + params ); - if( ( subCommand == "item" ) && ( params != "" ) ) - { - int32_t catalogId; - int32_t amount; - - sscanf( params.c_str(), "%d %d", &catalogId, &amount ); - - if( amount < 1 || amount > 99 ) - { - amount = 1; - } - - if( ( catalogId == 0xcccccccc ) ) - { - pPlayer->sendUrgent( "Syntaxerror." ); - return; - } - - if( !pPlayer->addItem( -1, catalogId, amount ) ) - pPlayer->sendUrgent( "Item " + std::to_string( catalogId ) + " not found..." ); - - } - else if( subCommand == "exp" ) - { - int32_t amount; - - sscanf( params.c_str(), "%d", &amount ); - - pPlayer->gainExp( amount ); - } - else if( subCommand == "status" ) + if( subCommand == "status" ) { int32_t id; int32_t duration; @@ -534,3 +483,9 @@ void Core::DebugCommandHandler::nudge( char * data, Entity::PlayerPtr pPlayer, b pPlayer->queuePacket( setActorPosPacket ); } } + +void Core::DebugCommandHandler::serverInfo( char * data, Core::Entity::PlayerPtr pPlayer, boost::shared_ptr< Core::DebugCommand > command ) +{ + pPlayer->sendDebug( "SapphireServer " + Version::VERSION + " - " + Version::GIT_HASH ); + pPlayer->sendDebug( "Sessions: " + std::to_string( g_serverZone.getSessionCount() ) ); +} diff --git a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.h b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.h index 69ef7c4a..12ff13b3 100644 --- a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.h +++ b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.h @@ -22,7 +22,7 @@ public: ~DebugCommandHandler(); // register command to command map - void registerCommand( const std::string& n, DebugCommand::pFunc, const std::string& hText, Common::UserLevel uLevel ); + void registerCommand( const std::string& n, DebugCommand::pFunc, const std::string& hText, uint8_t uLevel ); // execute command if registered void execCommand( char * data, Entity::PlayerPtr pPlayer ); @@ -37,6 +37,7 @@ public: void injectPacket( char * data, Entity::PlayerPtr pPlayer, boost::shared_ptr command ); void injectChatPacket( char * data, Entity::PlayerPtr pPlayer, boost::shared_ptr command ); void nudge( char* data, Entity::PlayerPtr pPlayer, boost::shared_ptr command ); + void serverInfo( char * data, Entity::PlayerPtr pPlayer, boost::shared_ptr command ); }; diff --git a/src/servers/Server_Zone/Inventory/Inventory.cpp b/src/servers/Server_Zone/Inventory/Inventory.cpp index eda20ba1..bffe043b 100644 --- a/src/servers/Server_Zone/Inventory/Inventory.cpp +++ b/src/servers/Server_Zone/Inventory/Inventory.cpp @@ -673,7 +673,7 @@ bool Core::Inventory::load() for( int32_t i = 1; i <= 14; i++ ) { - uint64_t uItemId = field[i].get< uint64_t >(); + uint64_t uItemId = field[i].getUInt64(); if( uItemId == 0 ) continue; @@ -710,7 +710,7 @@ bool Core::Inventory::load() uint16_t storageId = bagField[0].get< uint16_t >(); for( int32_t i = 1; i <= 25; i++ ) { - uint64_t uItemId = bagField[i].get< uint64_t >(); + uint64_t uItemId = bagField[i].getUInt64(); if( uItemId == 0 ) continue; @@ -743,7 +743,7 @@ bool Core::Inventory::load() uint16_t storageId = curField[0].get< uint16_t >(); for( int32_t i = 1; i <= 12; i++ ) { - uint64_t uItemId = curField[i].get< uint64_t >(); + uint64_t uItemId = curField[i].getUInt64(); if( uItemId == 0 ) continue; @@ -777,7 +777,7 @@ bool Core::Inventory::load() uint16_t storageId = crystalField[0].get< uint16_t >(); for( int32_t i = 1; i <= 17; i++ ) { - uint64_t uItemId = crystalField[i].get< uint64_t >(); + uint64_t uItemId = crystalField[i].getUInt64(); if( uItemId == 0 ) continue; diff --git a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp index d8fbfc62..01f2e024 100644 --- a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp @@ -109,7 +109,7 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in case 0x68: // Remove status (clicking it off) { // todo: check if status can be removed by client from exd - pPlayer->removeSingleStatusEffectFromId( param1 ); + pPlayer->removeSingleStatusEffectFromId( static_cast< uint32_t >( param1 ) ); break; } case 0x69: // Cancel cast diff --git a/src/servers/Server_Zone/Network/Handlers/GMCommandHandlers.cpp b/src/servers/Server_Zone/Network/Handlers/GMCommandHandlers.cpp index f51c776f..973b4bb1 100644 --- a/src/servers/Server_Zone/Network/Handlers/GMCommandHandlers.cpp +++ b/src/servers/Server_Zone/Network/Handlers/GMCommandHandlers.cpp @@ -69,6 +69,7 @@ enum GmCommand Mp = 0x0065, Tp = 0x0066, Gp = 0x0067, + Exp = 0x0068, Item = 0x00C8, Gil = 0x00C9, @@ -82,6 +83,7 @@ enum GmCommand QuestInspect = 0x0131, GC = 0x0154, GCRank = 0x0155, + Teri = 0x0258, TeriInfo = 0x025D, Jump = 0x025E, JumpNpc = 0x025F, @@ -189,6 +191,12 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac pPlayer->sendNotice( "Gp for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); break; } + case GmCommand::Exp: + { + targetPlayer->gainExp( param1 ); + pPlayer->sendNotice( std::to_string( param1 ) + " Exp was added to " + targetPlayer->getName() ); + break; + } case GmCommand::Sex: { targetPlayer->setLookAt( CharaLook::Gender, param1 ); @@ -245,6 +253,12 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac pPlayer->sendUrgent( "Item " + std::to_string( param1 ) + " not found..." ); break; } + case GmCommand::Time: + { + pPlayer->setEorzeaTimeOffset( param2 ); + pPlayer->sendNotice( "Eorzea time offset: " + std::to_string( param2 ) ); + break; + } case GmCommand::Weather: { targetPlayer->getCurrentZone()->setWeatherOverride( param1 ); @@ -262,6 +276,18 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac "\nNextWeather:" + std::to_string( pPlayer->getCurrentZone()->getNextWeather() ) ); break; } + case GmCommand::Teri: + { + if( param1 < 128 ) + pPlayer->sendUrgent( "Zone ID out of range." ); + else + { + targetPlayer->setPosition( targetPlayer->getPos() ); + targetPlayer->performZoning( param1, targetPlayer->getPos(), 0 ); + pPlayer->sendNotice( targetPlayer->getName() + " was warped to Zone " + std::to_string( param1 ) ); + } + break; + } case GmCommand::Jump: { diff --git a/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp b/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp index 453fa8bf..8a438e39 100644 --- a/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp @@ -493,7 +493,7 @@ void Core::Network::GameConnection::chatHandler( const Packets::GamePacket& inPa uint32_t sourceId = inPacket.getValAt< uint32_t >( 0x24 ); - if( chatString.at( 0 ) == '@' ) + if( chatString.at( 0 ) == '!' ) { // execute game console command g_gameCommandMgr.execCommand( const_cast< char * >( chatString.c_str() ) + 1, pPlayer ); @@ -597,4 +597,4 @@ void Core::Network::GameConnection::tellHandler( const Packets::GamePacket& inPa //tellPacket.data().u2b = 0x40; pTargetPlayer->queueChatPacket( tellPacket ); -} \ No newline at end of file +} diff --git a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp index d08b6db0..457aa855 100644 --- a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp @@ -52,7 +52,7 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP std::string actionIdStr = boost::str( boost::format( "%|04X|" ) % action ); pPlayer->sendDebug( "---------------------------------------" ); pPlayer->sendDebug( "ActionHandler ( " + actionIdStr + " | " + - g_exdData.m_actionInfoMap[action].name + + g_exdData.getActionInfo( action )->name + " | " + std::to_string( targetId ) + " )" ); pPlayer->queuePacket( ActorControlPacket142( pPlayer->getId(), ActorControlType::ActionStart, 0x01, action ) ); diff --git a/src/servers/Server_Zone/Script/ScriptManager.cpp b/src/servers/Server_Zone/Script/ScriptManager.cpp index 3a71c367..61c331bd 100644 --- a/src/servers/Server_Zone/Script/ScriptManager.cpp +++ b/src/servers/Server_Zone/Script/ScriptManager.cpp @@ -346,7 +346,7 @@ bool Core::Scripting::ScriptManager::onMobKill( Entity::PlayerPtr pPlayer, uint1 // loop through all active quests and try to call available onMobKill callbacks for( size_t i = 0; i < 30; i++ ) { - auto activeQuests = pPlayer->getQuestActive( i ); + auto activeQuests = pPlayer->getQuestActive( static_cast< uint16_t >( i ) ); if( !activeQuests ) continue; diff --git a/src/servers/Server_Zone/ServerZone.cpp b/src/servers/Server_Zone/ServerZone.cpp index d8051a14..270d472c 100644 --- a/src/servers/Server_Zone/ServerZone.cpp +++ b/src/servers/Server_Zone/ServerZone.cpp @@ -62,6 +62,11 @@ Core::XMLConfigPtr Core::ServerZone::getConfig() const return m_pConfig; } +size_t Core::ServerZone::getSessionCount() const +{ + return m_sessionMap.size(); +} + bool Core::ServerZone::registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId, uint32_t bnpcNameId, uint32_t modelId, std::string aiName ) { @@ -101,7 +106,7 @@ bool Core::ServerZone::loadSettings( int32_t argc, char* argv[] ) } std::vector args( argv + 1, argv + argc ); - for( auto i = 0; i + 1 < args.size(); i += 2 ) + for( uint32_t i = 0; i + 1 < args.size(); i += 2 ) { std::string arg( "" ); std::string val( "" ); diff --git a/src/servers/Server_Zone/ServerZone.h b/src/servers/Server_Zone/ServerZone.h index b6878c5a..2472c487 100644 --- a/src/servers/Server_Zone/ServerZone.h +++ b/src/servers/Server_Zone/ServerZone.h @@ -33,6 +33,8 @@ namespace Core { XMLConfigPtr getConfig() const; + size_t getSessionCount() const; + bool registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId, uint32_t bnpcNameId, uint32_t modelId, std::string aiName ); diff --git a/src/servers/Server_Zone/StatusEffect/StatusEffectContainer.cpp b/src/servers/Server_Zone/StatusEffect/StatusEffectContainer.cpp index 9e2e1e74..e842d0dc 100644 --- a/src/servers/Server_Zone/StatusEffect/StatusEffectContainer.cpp +++ b/src/servers/Server_Zone/StatusEffect/StatusEffectContainer.cpp @@ -57,8 +57,8 @@ void Core::StatusEffect::StatusEffectContainer::addStatusEffect( StatusEffectPtr m_effectMap[nextSlot] = pEffect; GamePacketNew< Server::FFXIVIpcAddStatusEffect, ServerZoneIpcType > statusEffectAdd( m_pOwner->getId() ); - statusEffectAdd.data().actor_id = m_pOwner->getId(); - statusEffectAdd.data().actor_id1 = m_pOwner->getId(); + statusEffectAdd.data().actor_id = pEffect->getTargetActorId(); + statusEffectAdd.data().actor_id1 = pEffect->getSrcActorId(); statusEffectAdd.data().current_hp = m_pOwner->getHp(); statusEffectAdd.data().current_mp = m_pOwner->getMp(); statusEffectAdd.data().current_tp = m_pOwner->getTp(); @@ -71,6 +71,7 @@ void Core::StatusEffect::StatusEffectContainer::addStatusEffect( StatusEffectPtr //statusEffectAdd.data().unknown2 = 28; statusEffectAdd.data().param = pEffect->getParam(); + bool sendToSelf = m_pOwner->isPlayer() ? true : false; m_pOwner->sendToInRangeSet( statusEffectAdd, sendToSelf ); @@ -142,8 +143,8 @@ void Core::StatusEffect::StatusEffectContainer::update() { uint64_t currentTimeMs = Util::getTimeMs(); - uint64_t thisTickDmg = 0; - uint64_t thisTickHeal = 0; + uint32_t thisTickDmg = 0; + uint32_t thisTickHeal = 0; for( auto effectIt : m_effectMap ) { diff --git a/src/servers/Server_Zone/Zone/Zone.cpp b/src/servers/Server_Zone/Zone/Zone.cpp index 522dc9a8..b03abde8 100644 --- a/src/servers/Server_Zone/Zone/Zone.cpp +++ b/src/servers/Server_Zone/Zone/Zone.cpp @@ -189,7 +189,7 @@ void Zone::loadCellCache() Entity::BattleNpcPtr pBNpc( new Entity::BattleNpc( modelId, nameId, pos, sizeId, type, level, behaviour, mobType ) ); - pBNpc->setRotation( rotation ); + pBNpc->setRotation( static_cast< float >( rotation ) ); cache.push_back( pBNpc ); //pushActor( pBNpc );