mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-30 08:07:46 +00:00
Merge https://github.com/SapphireMordred/Sapphire into SQL_REWRITE_OWN
This commit is contained in:
commit
14c8d674cc
49 changed files with 652 additions and 238 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -97,3 +97,5 @@ src/libraries/external/boost_*
|
|||
*.iobj
|
||||
*.filters
|
||||
|
||||
# sapphire version
|
||||
src/servers/Server_Common/Version\.cpp
|
||||
|
|
|
@ -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/")
|
||||
|
|
30
README.md
30
README.md
|
@ -1,40 +1,42 @@
|
|||
# Sapphire - FINAL FANTASY XIV Server Emulator
|
||||
[](https://discord.gg/KfrZCkx)
|
||||
[](https://travis-ci.org/SapphireMordred/Sapphire)
|
||||
[](https://travis-ci.org/SapphireMordred/Sapphire)
|
||||
[](https://ci.appveyor.com/project/SapphireMordred/Sapphire)
|
||||

|
||||
|
||||
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
|
||||
|
||||
|
|
168
cmake/GetGitRevisionDescription.cmake
Normal file
168
cmake/GetGitRevisionDescription.cmake
Normal file
|
@ -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(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to 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(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# 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(<var>)
|
||||
#
|
||||
# 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 <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# 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()
|
41
cmake/GetGitRevisionDescription.cmake.in
Normal file
41
cmake/GetGitRevisionDescription.cmake.in
Normal file
|
@ -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 <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# 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()
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
18
scripts/chai/skill/cnj/skillDef_124.chai
Normal file
18
scripts/chai/skill/cnj/skillDef_124.chai
Normal file
|
@ -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();
|
|
@ -10,7 +10,7 @@ class skillDef_125Def
|
|||
|
||||
def onFinish( player, target )
|
||||
{
|
||||
target.addStatusEffectByIdIfNotExist( 148, 60000, 0 );
|
||||
target.addStatusEffectByIdIfNotExist( 148, 60000, player, 0 );
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ class skillDef_128Def
|
|||
|
||||
def onFinish( player, target )
|
||||
{
|
||||
target.addStatusEffectByIdIfNotExist(3, 30000, 0);
|
||||
target.addStatusEffectByIdIfNotExist( 3, 30000, player, 0 );
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
};
|
||||
|
|
19
scripts/chai/skill/cnj/skillDef_133.chai
Normal file
19
scripts/chai/skill/cnj/skillDef_133.chai
Normal file
|
@ -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();
|
|
@ -10,7 +10,7 @@ class skillDef_3Def
|
|||
|
||||
def onFinish( player, target )
|
||||
{
|
||||
player.addStatusEffectById(50, 20000, 30);
|
||||
player.addStatusEffectById(50, 20000, player, 30);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -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, '') */;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -34,6 +34,25 @@ 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:
|
||||
|
|
|
@ -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 )
|
||||
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -299,7 +299,7 @@ namespace Core {
|
|||
std::map<uint8_t, ClassJobInfo> m_classJobInfoMap;
|
||||
std::map<uint32_t, ParamGrowthInfo> m_paramGrowthInfoMap;
|
||||
std::map<uint16_t, EventActionInfo> m_EventActionInfoMap;
|
||||
std::map<uint16_t, ActionInfo> m_actionInfoMap;
|
||||
std::map<uint16_t, boost::shared_ptr< ActionInfo > > m_actionInfoMap;
|
||||
std::map<uint16_t, StatusEffectInfo> m_statusEffectInfoMap;
|
||||
std::map<uint32_t, boost::shared_ptr< AetheryteInfo > > m_aetheryteInfoMap;
|
||||
std::map<uint32_t, TribeInfo > 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 );
|
||||
|
|
|
@ -116,6 +116,7 @@ namespace Packets {
|
|||
WeatherChange = 0x01AF, // updated for sb
|
||||
Discovery = 0x01B2, // updated for sb
|
||||
|
||||
EorzeaTimeOffset = 0x01B4,
|
||||
|
||||
CFAvailableContents = 0x01CF,
|
||||
|
||||
|
|
|
@ -301,12 +301,12 @@ struct FFXIVIpcUpdateHpMpTp : FFXIVIpcBasePacket<UpdateHpMpTp>
|
|||
*/
|
||||
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<CFMemberStatus>
|
|||
uint32_t unknown3;
|
||||
};
|
||||
|
||||
struct FFXIVIpcEorzeaTimeOffset : FFXIVIpcBasePacket<EorzeaTimeOffset>
|
||||
{
|
||||
uint64_t timestamp;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} /* Server */
|
||||
|
|
10
src/servers/Server_Common/Version.cpp.in
Normal file
10
src/servers/Server_Common/Version.cpp.in
Normal file
|
@ -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 */
|
15
src/servers/Server_Common/Version.h
Normal file
15
src/servers/Server_Common/Version.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef _VERSION_H
|
||||
#define _VERSION_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Core {
|
||||
namespace Version {
|
||||
|
||||
extern const std::string GIT_HASH;
|
||||
extern const std::string VERSION;
|
||||
|
||||
} /* Version */
|
||||
} /* Core */
|
||||
|
||||
#endif
|
|
@ -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 ) + ";" );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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);
|
||||
|
@ -1518,6 +1519,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;
|
||||
}
|
||||
|
@ -1629,3 +1668,14 @@ void Core::Entity::Player::setOpeningSequence( uint8_t seq )
|
|||
setSyncFlag( OpeningSeq );
|
||||
m_openingSequence = seq;
|
||||
}
|
||||
|
||||
/// 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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ) )
|
||||
{
|
||||
|
|
|
@ -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 >();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <src/servers/Server_Common/Common.h>
|
||||
#include <src/servers/Server_Common/Version.h>
|
||||
#include <src/servers/Server_Common/Database/Database.h>
|
||||
#include <src/servers/Server_Common/Network/GamePacketNew.h>
|
||||
#include <src/servers/Server_Common/Network/CommonNetwork.h>
|
||||
|
@ -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<DebugCommand>( 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;
|
||||
|
@ -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() ) );
|
||||
}
|
||||
|
|
|
@ -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<DebugCommand> command );
|
||||
void injectChatPacket( char * data, Entity::PlayerPtr pPlayer, boost::shared_ptr<DebugCommand> command );
|
||||
void nudge( char* data, Entity::PlayerPtr pPlayer, boost::shared_ptr<DebugCommand> command );
|
||||
void serverInfo( char * data, Entity::PlayerPtr pPlayer, boost::shared_ptr<DebugCommand> command );
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
{
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 ) );
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<std::string> 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( "" );
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Add table
Reference in a new issue