merge changeset from remote

This commit is contained in:
sfb 2012-03-21 07:55:14 -05:00
commit 12073be970
147 changed files with 6953 additions and 1127 deletions

View file

@ -91,6 +91,7 @@ NL_CONFIGURE_CHECKS()
#Platform specifics
SETUP_EXTERNAL()
NL_GEN_REVISION_H()
IF(WIN32)
SET(WINSOCK2_LIB ws2_32.lib)

View file

@ -57,6 +57,13 @@ FIND_LIBRARY(FREETYPE_LIBRARY
IF(FREETYPE_LIBRARY AND FREETYPE_INCLUDE_DIRS)
SET(FREETYPE_FOUND "YES")
IF(WITH_STATIC_EXTERNAL AND APPLE)
FIND_PACKAGE(BZip2)
IF(BZIP2_FOUND)
SET(FREETYPE_INCLUDE_DIRS ${FREETYPE_INCLUDE_DIRS} ${BZIP2_INCLUDE_DIR})
SET(FREETYPE_LIBRARY ${FREETYPE_LIBRARY} ${BZIP2_LIBRARIES})
ENDIF(BZIP2_FOUND)
ENDIF(WITH_STATIC_EXTERNAL AND APPLE)
IF(NOT FREETYPE_FIND_QUIETLY)
MESSAGE(STATUS "Found FreeType: ${FREETYPE_LIBRARY}")
ENDIF(NOT FREETYPE_FIND_QUIETLY)

View file

@ -0,0 +1,108 @@
# - Extract information from a subversion working copy
# The module defines the following variables:
# Mercurial_HG_EXECUTABLE - path to hg command line client
# Mercurial_VERSION_HG - version of hg command line client
# Mercurial_FOUND - true if the command line client was found
# MERCURIAL_FOUND - same as Mercurial_FOUND, set for compatiblity reasons
#
# The minimum required version of Mercurial can be specified using the
# standard syntax, e.g. FIND_PACKAGE(Mercurial 1.4)
#
# If the command line client executable is found two macros are defined:
# Mercurial_WC_INFO(<dir> <var-prefix>)
# Mercurial_WC_LOG(<dir> <var-prefix>)
# Mercurial_WC_INFO extracts information of a subversion working copy at
# a given location. This macro defines the following variables:
# <var-prefix>_WC_URL - url of the repository (at <dir>)
# <var-prefix>_WC_ROOT - root url of the repository
# <var-prefix>_WC_REVISION - current revision
# <var-prefix>_WC_LAST_CHANGED_AUTHOR - author of last commit
# <var-prefix>_WC_LAST_CHANGED_DATE - date of last commit
# <var-prefix>_WC_LAST_CHANGED_REV - revision of last commit
# <var-prefix>_WC_INFO - output of command `hg info <dir>'
# Mercurial_WC_LOG retrieves the log message of the base revision of a
# subversion working copy at a given location. This macro defines the
# variable:
# <var-prefix>_LAST_CHANGED_LOG - last log of base revision
# Example usage:
# FIND_PACKAGE(Mercurial)
# IF(MERCURIAL_FOUND)
# Mercurial_WC_INFO(${PROJECT_SOURCE_DIR} Project)
# MESSAGE("Current revision is ${Project_WC_REVISION}")
# Mercurial_WC_LOG(${PROJECT_SOURCE_DIR} Project)
# MESSAGE("Last changed log is ${Project_LAST_CHANGED_LOG}")
# ENDIF(MERCURIAL_FOUND)
#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
# Copyright 2006 Tristan Carel
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
FIND_PROGRAM(Mercurial_HG_EXECUTABLE hg
DOC "mercurial command line client")
MARK_AS_ADVANCED(Mercurial_HG_EXECUTABLE)
IF(Mercurial_HG_EXECUTABLE)
EXECUTE_PROCESS(COMMAND ${Mercurial_HG_EXECUTABLE} --version
OUTPUT_VARIABLE Mercurial_VERSION_HG
OUTPUT_STRIP_TRAILING_WHITESPACE)
STRING(REGEX REPLACE ".*version ([\\.0-9]+).*"
"\\1" Mercurial_VERSION_HG "${Mercurial_VERSION_HG}")
MACRO(Mercurial_WC_INFO dir prefix)
EXECUTE_PROCESS(COMMAND ${Mercurial_HG_EXECUTABLE} tip
WORKING_DIRECTORY ${dir}
OUTPUT_VARIABLE ${prefix}_WC_INFO
ERROR_VARIABLE Mercurial_hg_info_error
RESULT_VARIABLE Mercurial_hg_info_result
OUTPUT_STRIP_TRAILING_WHITESPACE)
IF(NOT ${Mercurial_hg_info_result} EQUAL 0)
MESSAGE(SEND_ERROR "Command \"${Mercurial_HG_EXECUTABLE} tip\" failed with output:\n${Mercurial_hg_info_error}")
ELSE(NOT ${Mercurial_hg_info_result} EQUAL 0)
STRING(REGEX REPLACE "^(.*\n)?Repository Root: ([^\n]+).*"
"\\2" ${prefix}_WC_ROOT "${${prefix}_WC_INFO}")
STRING(REGEX REPLACE "^(.*\n)?changeset: *([0-9]+).*"
"\\2" ${prefix}_WC_REVISION "${${prefix}_WC_INFO}")
STRING(REGEX REPLACE "^(.*\n)?Last Changed Author: ([^\n]+).*"
"\\2" ${prefix}_WC_LAST_CHANGED_AUTHOR "${${prefix}_WC_INFO}")
STRING(REGEX REPLACE "^(.*\n)?Last Changed Rev: ([^\n]+).*"
"\\2" ${prefix}_WC_LAST_CHANGED_REV "${${prefix}_WC_INFO}")
STRING(REGEX REPLACE "^(.*\n)?Last Changed Date: ([^\n]+).*"
"\\2" ${prefix}_WC_LAST_CHANGED_DATE "${${prefix}_WC_INFO}")
ENDIF(NOT ${Mercurial_hg_info_result} EQUAL 0)
ENDMACRO(Mercurial_WC_INFO)
MACRO(Mercurial_WC_LOG dir prefix)
# This macro can block if the certificate is not signed:
# hg ask you to accept the certificate and wait for your answer
# This macro requires a hg server network access (Internet most of the time)
# and can also be slow since it access the hg server
EXECUTE_PROCESS(COMMAND
${Mercurial_HG_EXECUTABLE} --non-interactive log -r BASE ${dir}
OUTPUT_VARIABLE ${prefix}_LAST_CHANGED_LOG
ERROR_VARIABLE Mercurial_hg_log_error
RESULT_VARIABLE Mercurial_hg_log_result
OUTPUT_STRIP_TRAILING_WHITESPACE)
IF(NOT ${Mercurial_hg_log_result} EQUAL 0)
MESSAGE(SEND_ERROR "Command \"${Mercurial_HG_EXECUTABLE} log -r BASE ${dir}\" failed with output:\n${Mercurial_hg_log_error}")
ENDIF(NOT ${Mercurial_hg_log_result} EQUAL 0)
ENDMACRO(Mercurial_WC_LOG)
ENDIF(Mercurial_HG_EXECUTABLE)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Mercurial DEFAULT_MSG Mercurial_HG_EXECUTABLE)

View file

@ -0,0 +1,59 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3)
# ROOT_DIR should be set to root of the repository (where to find the .svn or .hg directory)
# SOURCE_DIR should be set to root of your code (where to find CMakeLists.txt)
# Replace spaces by semi-columns
IF(CMAKE_MODULE_PATH)
STRING(REPLACE " " ";" CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH})
ENDIF(CMAKE_MODULE_PATH)
SET(CMAKE_MODULE_PATH ${SOURCE_DIR}/CMakeModules ${CMAKE_MODULE_PATH})
IF(NOT ROOT_DIR AND SOURCE_DIR)
SET(ROOT_DIR ${SOURCE_DIR})
ENDIF(NOT ROOT_DIR AND SOURCE_DIR)
IF(NOT SOURCE_DIR AND ROOT_DIR)
SET(SOURCE_DIR ${ROOT_DIR})
ENDIF(NOT SOURCE_DIR AND ROOT_DIR)
MACRO(NOW RESULT)
IF (WIN32)
EXECUTE_PROCESS(COMMAND "wmic" "os" "get" "localdatetime" OUTPUT_VARIABLE DATETIME)
IF(NOT DATETIME MATCHES "ERROR")
STRING(REGEX REPLACE ".*\n([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9]).*" "\\1-\\2-\\3 \\4:\\5:\\6" ${RESULT} "${DATETIME}")
ENDIF(NOT DATETIME MATCHES "ERROR")
ELSEIF(UNIX)
EXECUTE_PROCESS(COMMAND "date" "+'%Y-%m-%d %H:%M:%S'" OUTPUT_VARIABLE ${RESULT})
ELSE (WIN32)
MESSAGE(SEND_ERROR "date not implemented")
SET(${RESULT} "0000-00-00 00:00:00")
ENDIF (WIN32)
ENDMACRO(NOW)
IF(EXISTS "${ROOT_DIR}/.svn/")
FIND_PACKAGE(Subversion)
IF(SUBVERSION_FOUND)
Subversion_WC_INFO(${ROOT_DIR} ER)
SET(REVISION ${ER_WC_REVISION})
ENDIF(SUBVERSION_FOUND)
ENDIF(EXISTS "${ROOT_DIR}/.svn/")
IF(EXISTS "${ROOT_DIR}/.hg/")
FIND_PACKAGE(Mercurial)
IF(MERCURIAL_FOUND)
Mercurial_WC_INFO(${ROOT_DIR} ER)
SET(REVISION ${ER_WC_REVISION})
ENDIF(MERCURIAL_FOUND)
ENDIF(EXISTS "${ROOT_DIR}/.hg/")
IF(REVISION)
IF(EXISTS ${SOURCE_DIR}/revision.h.in)
NOW(BUILD_DATE)
CONFIGURE_FILE(${SOURCE_DIR}/revision.h.in revision.h.txt)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy revision.h.txt revision.h) # copy_if_different
ENDIF(EXISTS ${SOURCE_DIR}/revision.h.in)
ENDIF(REVISION)

View file

@ -8,10 +8,12 @@
# ADD_PRECOMPILED_HEADER_TO_TARGET _targetName _input _pch_output_to_use
# ADD_NATIVE_PRECOMPILED_HEADER _targetName _inputh _inputcpp
IF(CMAKE_COMPILER_IS_GNUCXX)
EXEC_PROGRAM(
${CMAKE_CXX_COMPILER}
IF(MSVC)
SET(PCHSupport_FOUND TRUE)
SET(_PCH_include_prefix "/I")
ELSE(MSVC)
IF(CMAKE_COMPILER_IS_GNUCXX)
EXEC_PROGRAM(${CMAKE_CXX_COMPILER}
ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion
OUTPUT_VARIABLE gcc_compiler_version)
@ -22,30 +24,24 @@ IF(CMAKE_COMPILER_IS_GNUCXX)
SET(PCHSupport_FOUND TRUE)
ENDIF(gcc_compiler_version MATCHES "3\\.4\\.[0-9]")
ENDIF(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]")
ELSE(CMAKE_COMPILER_IS_GNUCXX)
# TODO: make tests for other compilers than GCC
SET(PCHSupport_FOUND TRUE)
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
SET(_PCH_include_prefix "-I")
ELSE(CMAKE_COMPILER_IS_GNUCXX)
IF(WIN32)
SET(PCHSupport_FOUND TRUE) # for experimental msvc support
SET(_PCH_include_prefix "/I")
ELSE(WIN32)
SET(PCHSupport_FOUND FALSE)
ENDIF(WIN32)
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
ENDIF(MSVC)
MACRO(_PCH_GET_COMPILE_FLAGS _out_compile_flags)
STRING(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" _flags_var_name)
SET(${_out_compile_flags} ${${_flags_var_name}} )
IF(CMAKE_COMPILER_IS_GNUCXX)
IF(NOT MSVC)
GET_TARGET_PROPERTY(_targetType ${_PCH_current_target} TYPE)
IF(${_targetType} STREQUAL SHARED_LIBRARY OR ${_targetType} STREQUAL MODULE_LIBRARY)
LIST(APPEND ${_out_compile_flags} "-fPIC")
ENDIF(${_targetType} STREQUAL SHARED_LIBRARY OR ${_targetType} STREQUAL MODULE_LIBRARY)
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
ENDIF(NOT MSVC)
GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES )
FOREACH(item ${DIRINC})
@ -100,17 +96,13 @@ MACRO(_PCH_GET_COMPILE_COMMAND out_command _input _inputcpp _output)
SET(pchsupport_compiler_cxx_arg1 "")
ENDIF(CMAKE_CXX_COMPILER_ARG1)
IF(CMAKE_COMPILER_IS_GNUCXX)
SET(${out_command}
${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} -x c++-header -o ${_output} -c ${_input}
)
ELSE(CMAKE_COMPILER_IS_GNUCXX)
IF(MSVC)
_PCH_GET_PDB_FILENAME(PDB_FILE ${_PCH_current_target})
SET(${out_command}
${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} /Yc /Fp\"${_output}\" ${_inputcpp} /c /Fd\"${PDB_FILE}\"
)
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
ENDMACRO(_PCH_GET_COMPILE_COMMAND )
SET(${out_command} ${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} /Yc /Fp\"${_output}\" ${_inputcpp} /c /Fd\"${PDB_FILE}\")
ELSE(MSVC)
SET(${out_command} ${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} -x c++-header -o ${_output} -c ${_input})
ENDIF(MSVC)
ENDMACRO(_PCH_GET_COMPILE_COMMAND)
MACRO(GET_PRECOMPILED_HEADER_OUTPUT _targetName _input _output)
IF(MSVC)
@ -128,7 +120,9 @@ MACRO(ADD_PRECOMPILED_HEADER_TO_TARGET _targetName _input _pch_output_to_use )
SET(oldProps "")
ENDIF(${oldProps} MATCHES NOTFOUND)
IF(CMAKE_COMPILER_IS_GNUCXX)
IF(MSVC)
SET(_target_cflags "${oldProps} /Yu\"${_input}\" /FI\"${_input}\" /Fp\"${_pch_output_to_use}\"")
ELSE(MSVC)
# to do: test whether compiler flags match between target _targetName
# and _pch_output_to_use
FILE(TO_NATIVE_PATH ${_pch_output_to_use} _native_pch_path)
@ -137,11 +131,7 @@ MACRO(ADD_PRECOMPILED_HEADER_TO_TARGET _targetName _input _pch_output_to_use )
# on all remote machines set
# PCH_ADDITIONAL_COMPILER_FLAGS to -fpch-preprocess
SET(_target_cflags "${oldProps} ${PCH_ADDITIONAL_COMPILER_FLAGS}-include ${_input} -Winvalid-pch")
ELSE(CMAKE_COMPILER_IS_GNUCXX)
IF(MSVC)
SET(_target_cflags "${oldProps} /Yu\"${_input}\" /FI\"${_input}\" /Fp\"${_pch_output_to_use}\"")
ENDIF(MSVC)
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
SET_TARGET_PROPERTIES(${_targetName} PROPERTIES COMPILE_FLAGS ${_target_cflags})
IF(oldProps)
@ -184,8 +174,31 @@ MACRO(ADD_PRECOMPILED_HEADER _targetName _inputh _inputcpp)
ADD_PRECOMPILED_HEADER_TO_TARGET(${_targetName} ${_inputh} ${_output})
ENDMACRO(ADD_PRECOMPILED_HEADER)
# Macro to move PCH creation file to the front of files list
MACRO(FIX_PRECOMPILED_HEADER _files _pch)
# Remove .cpp creating PCH from the list
LIST(REMOVE_ITEM ${_files} ${_pch})
# Prepend .cpp creating PCH to the list
LIST(INSERT ${_files} 0 ${_pch})
ENDMACRO(FIX_PRECOMPILED_HEADER)
MACRO(ADD_NATIVE_PRECOMPILED_HEADER _targetName _inputh _inputcpp)
IF(CMAKE_GENERATOR MATCHES Visual*)
SET(PCH_METHOD 0)
# 0 => creating a new target for PCH, works for all makefiles
# 1 => setting PCH for VC++ project, works for VC++ projects
# 2 => setting PCH for XCode project, works for XCode projects
IF(CMAKE_GENERATOR MATCHES "Visual Studio")
SET(PCH_METHOD 1)
ELSEIF(CMAKE_GENERATOR MATCHES "NMake Makefiles" AND MFC_FOUND AND CMAKE_MFC_FLAG)
# To fix a bug with MFC
# Don't forget to use FIX_PRECOMPILED_HEADER before creating the target
# SET(PCH_METHOD 1)
ELSEIF(CMAKE_GENERATOR MATCHES "Xcode")
SET(PCH_METHOD 2)
ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio")
IF(PCH_METHOD EQUAL 1)
# Auto include the precompile (useful for moc processing, since the use of
# precompiled is specified at the target level
# and I don't want to specifiy /F- for each moc/res/ui generated files (using Qt)
@ -200,8 +213,7 @@ MACRO(ADD_NATIVE_PRECOMPILED_HEADER _targetName _inputh _inputcpp)
#also inlude ${oldProps} to have the same compile options
SET_SOURCE_FILES_PROPERTIES(${_inputcpp} PROPERTIES COMPILE_FLAGS "${oldProps} /Yc\"${_inputh}\"")
ELSE(CMAKE_GENERATOR MATCHES Visual*)
IF(CMAKE_GENERATOR MATCHES Xcode)
ELSEIF(PCH_METHOD EQUAL 2)
# For Xcode, cmake needs my patch to process
# GCC_PREFIX_HEADER and GCC_PRECOMPILE_PREFIX_HEADER as target properties
@ -216,10 +228,9 @@ MACRO(ADD_NATIVE_PRECOMPILED_HEADER _targetName _inputh _inputcpp)
SET_TARGET_PROPERTIES(${_targetName} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${fullPath}")
SET_TARGET_PROPERTIES(${_targetName} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES")
ELSE(CMAKE_GENERATOR MATCHES Xcode)
ELSE(PCH_METHOD EQUAL 1)
#Fallback to the "old" precompiled suppport
ADD_PRECOMPILED_HEADER(${_targetName} ${_inputh} ${_inputcpp})
ENDIF(CMAKE_GENERATOR MATCHES Xcode)
ENDIF(CMAKE_GENERATOR MATCHES Visual*)
ENDIF(PCH_METHOD EQUAL 1)
ENDMACRO(ADD_NATIVE_PRECOMPILED_HEADER)

View file

@ -9,6 +9,33 @@ MACRO(NL_GEN_PC name)
ENDIF(NOT WIN32 AND WITH_INSTALL_LIBRARIES)
ENDMACRO(NL_GEN_PC)
###
# Helper macro that generates revision.h from revision.h.in
###
MACRO(NL_GEN_REVISION_H)
IF(EXISTS ${CMAKE_SOURCE_DIR}/revision.h.in)
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
ADD_DEFINITIONS(-DHAVE_REVISION_H)
SET(HAVE_REVISION_H ON)
# a custom target that is always built
ADD_CUSTOM_TARGET(revision ALL
DEPENDS ${CMAKE_BINARY_DIR}/revision.h)
# creates revision.h using cmake script
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_BINARY_DIR}/revision.h
COMMAND ${CMAKE_COMMAND}
-DSOURCE_DIR=${CMAKE_SOURCE_DIR}
-DROOT_DIR=${CMAKE_SOURCE_DIR}/..
-P ${CMAKE_SOURCE_DIR}/CMakeModules/GetRevision.cmake)
# revision.h is a generated file
SET_SOURCE_FILES_PROPERTIES(${CMAKE_BINARY_DIR}/revision.h
PROPERTIES GENERATED TRUE
HEADER_FILE_ONLY TRUE)
ENDIF(EXISTS ${CMAKE_SOURCE_DIR}/revision.h.in)
ENDMACRO(NL_GEN_REVISION_H)
###
#
###
@ -613,13 +640,19 @@ MACRO(SETUP_EXTERNAL)
ENDIF(${CMAKE_MAKE_PROGRAM} MATCHES "Common7")
ENDIF(MSVC10)
ELSE(WIN32)
IF(CMAKE_FIND_LIBRARY_SUFFIXES AND NOT APPLE)
IF(APPLE)
IF(WITH_STATIC_EXTERNAL)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
SET(CMAKE_FIND_LIBRARY_SUFFIXES .a .dylib .so)
ELSE(WITH_STATIC_EXTERNAL)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
SET(CMAKE_FIND_LIBRARY_SUFFIXES .dylib .so .a)
ENDIF(WITH_STATIC_EXTERNAL)
ENDIF(CMAKE_FIND_LIBRARY_SUFFIXES AND NOT APPLE)
ELSE(APPLE)
IF(WITH_STATIC_EXTERNAL)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .a .so)
ELSE(WITH_STATIC_EXTERNAL)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .so .a)
ENDIF(WITH_STATIC_EXTERNAL)
ENDIF(APPLE)
ENDIF(WIN32)
IF(WITH_STLPORT)

View file

@ -78,6 +78,18 @@ Core::IContext *ContextManager::context(const QString &id) const
return 0;
}
void ContextManager::registerUndoStack(QUndoStack *stack)
{
nlassert(stack);
d->m_mainWindow->undoGroup()->addStack(stack);
}
void ContextManager::unregisterUndoStack(QUndoStack *stack)
{
nlassert(stack);
d->m_mainWindow->undoGroup()->removeStack(stack);
}
void ContextManager::activateContext(const QString &id)
{
const int index = indexOf(id);
@ -85,6 +97,11 @@ void ContextManager::activateContext(const QString &id)
d->m_tabWidget->setCurrentIndex(index);
}
void ContextManager::updateCurrentContext()
{
d->m_mainWindow->updateContext(currentContext());
}
void ContextManager::objectAdded(QObject *obj)
{
IContext *context = qobject_cast<IContext *>(obj);

View file

@ -26,6 +26,7 @@
QT_BEGIN_NAMESPACE
class QTabWidget;
class QUndoStack;
QT_END_NAMESPACE
namespace Core
@ -45,12 +46,17 @@ public:
Core::IContext *currentContext() const;
Core::IContext *context(const QString &id) const;
// temporary solution for multiple undo stacks per context
void registerUndoStack(QUndoStack *stack);
void unregisterUndoStack(QUndoStack *stack);
Q_SIGNALS:
// the default argument '=0' is important for connects without the oldContext argument.
void currentContextChanged(Core::IContext *context, Core::IContext *oldContext = 0);
public Q_SLOTS:
void activateContext(const QString &id);
void updateCurrentContext();
private Q_SLOTS:
void objectAdded(QObject *obj);

View file

@ -92,7 +92,7 @@ const char *const SEARCH_PATHS = "SearchPaths";
const char *const RECURSIVE_SEARCH_PATHS = "RecursiveSearchPathes";
const char *const LEVELDESIGN_PATH = "LevelDesignPath";
const char *const PRIMITIVES_PATH = "PrimitivesPath";
const char * const ASSETS_PATH = "AssetsPath";
const char *const ASSETS_PATH = "AssetsPath";
const char *const LIGOCONFIG_FILE = "LigoConfigFile";
const char *const REMAP_EXTENSIONS = "RemapExtensions";

View file

@ -128,6 +128,11 @@ QSettings *MainWindow::settings() const
return m_settings;
}
QUndoGroup *MainWindow::undoGroup() const
{
return m_undoGroup;
}
ExtensionSystem::IPluginManager *MainWindow::pluginManager() const
{
return m_pluginManager;
@ -135,12 +140,16 @@ ExtensionSystem::IPluginManager *MainWindow::pluginManager() const
void MainWindow::addContextObject(IContext *context)
{
m_undoGroup->addStack(context->undoStack());
QUndoStack *stack = context->undoStack();
if (stack)
m_undoGroup->addStack(stack);
}
void MainWindow::removeContextObject(IContext *context)
{
m_undoGroup->removeStack(context->undoStack());
QUndoStack *stack = context->undoStack();
if (stack)
m_undoGroup->removeStack(stack);
}
void MainWindow::open()

View file

@ -52,6 +52,7 @@ public:
MenuManager *menuManager() const;
ContextManager *contextManager() const;
QSettings *settings() const;
QUndoGroup *undoGroup() const;
ExtensionSystem::IPluginManager *pluginManager() const;
@ -62,6 +63,7 @@ public Q_SLOTS:
bool showOptionsDialog(const QString &group = QString(),
const QString &page = QString(),
QWidget *parent = 0);
void updateContext(Core::IContext *context);
private Q_SLOTS:
void open();
@ -77,7 +79,6 @@ private Q_SLOTS:
void gotoPos();
void setFullScreen(bool enabled);
void about();
void updateContext(Core::IContext *context);
protected:
virtual void closeEvent(QCloseEvent *event);

7
code/revision.h.in Normal file
View file

@ -0,0 +1,7 @@
#ifndef REVISION_H
#define REVISION_H
#cmakedefine REVISION "${REVISION}"
#cmakedefine BUILD_DATE "${BUILD_DATE}"
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,190 @@
-- create the webig namespace without reseting if already created in an other file.
if (webig==nil) then
webig= {}
end
if (webig.sheetLists==nil) then
webig.sheetLists = {}
end
function webig:addSheet(dst, sheet, quality, quantity, worned, user_color, rm_class_type, rm_faber_stat_type)
if quality == nil then quality=0 end
if quantity == nil then quantity=0 end
if worned == nil then worned=0 end
if user_color == nil then user_color=0 end
if rm_class_type == nil then rm_class_type=0 end
if rm_faber_stat_type == nil then rm_faber_stat_type=0 end
addDbProp(dst..":SHEET", sheet)
addDbProp(dst..":WORNED", worned)
addDbProp(dst..":QUALITY", quality)
addDbProp(dst..":QUANTITY", quantity)
addDbProp(dst..":USER_COLOR", user_color)
addDbProp(dst..":RM_CLASS_TYPE", rm_class_type)
addDbProp(dst..":RM_FABER_STAT_TYPE", rm_faber_stat_type)
end
function webig:cleanSheets(db)
delDbProp(db)
end
function webig:addSheetList(name, ctrl, db, size)
webig.sheetLists[name] = {}
webig.sheetLists[name].ctrl = ctrl
webig.sheetLists[name].db = db
webig.sheetLists[name].selection = ""
webig.sheetLists[name].size = size
end
function webig:copyItems(src, dst)
addDbProp(dst..":SHEET", getDbProp(src..":SHEET"))
addDbProp(dst..":WORNED", getDbProp(src..":WORNED"))
addDbProp(dst..":QUALITY", getDbProp(src..":QUALITY"))
addDbProp(dst..":QUANTITY", getDbProp(src..":QUANTITY"))
addDbProp(dst..":USER_COLOR", getDbProp(src..":USER_COLOR"))
addDbProp(dst..":RM_CLASS_TYPE", getDbProp(src..":RM_CLASS_TYPE"))
addDbProp(dst..":RM_FABER_STAT_TYPE", getDbProp(src..":RM_FABER_STAT_TYPE"))
end
function webig:swapItems(src, dst)
local sheet = getDbProp(dst..":SHEET")
local worned = getDbProp(dst..":WORNED")
local quality = getDbProp(dst..":QUALITY")
local quantity = getDbProp(dst..":QUANTITY")
local user_color = getDbProp(dst..":USER_COLOR")
local rm_class_type = getDbProp(dst..":RM_CLASS_TYPE")
local rm_faber_stat_type = getDbProp(dst..":RM_FABER_STAT_TYPE")
addDbProp(dst..":SHEET", getDbProp(src..":SHEET"))
addDbProp(dst..":WORNED", getDbProp(src..":WORNED"))
addDbProp(dst..":QUALITY", getDbProp(src..":QUALITY"))
addDbProp(dst..":QUANTITY", getDbProp(src..":QUANTITY"))
addDbProp(dst..":USER_COLOR", getDbProp(src..":USER_COLOR"))
addDbProp(dst..":RM_CLASS_TYPE", getDbProp(src..":RM_CLASS_TYPE"))
addDbProp(dst..":RM_FABER_STAT_TYPE", getDbProp(src..":RM_FABER_STAT_TYPE"))
addDbProp(src..":SHEET", sheet)
addDbProp(src..":WORNED", worned)
addDbProp(src..":QUALITY", quality)
addDbProp(src..":QUANTITY", quantity)
addDbProp(src..":USER_COLOR", user_color)
addDbProp(src..":RM_CLASS_TYPE", rm_class_type)
addDbProp(src..":RM_FABER_STAT_TYPE", rm_faber_stat_type)
end
function webig:deleteItem(src)
addDbProp(src..":SHEET", 0)
addDbProp(src..":WORNED", 0)
addDbProp(src..":QUALITY", 0)
addDbProp(src..":QUANTITY", 0)
addDbProp(src..":USER_COLOR", 0)
addDbProp(src..":RM_CLASS_TYPE", 0)
addDbProp(src..":RM_FABER_STAT_TYPE", 0)
end
function webig:paramDbSheetSlot(sheet_list, ctrl)
local ctrlSheet = webig.sheetLists[sheet_list].ctrl:find("list:"..ctrl)
if ctrlSheet ~= nil then
ctrlSheet.left_click="lua"
ctrlSheet.left_click_params="webig:addOrRemoveDbSheet(\'"..sheet_list.."\', \'"..ctrl.."\')"
ctrlSheet.dragable=true
ctrlSheet.can_drop=true
ctrlSheet.on_drop="lua"
ctrlSheet.on_drop_params="webig:dropDbSheet(\'"..sheet_list.."\', \'"..ctrl.."\', \'%src\')"
ctrlSheet.on_can_drop="lua"
ctrlSheet.on_can_drop_params="webig:canDropDbSheet(\'"..sheet_list.."\', \'"..ctrl.."\', \'%src\')"
end
end
function webig:paramDbSheetSelect(sheet_list, ctrl, lua_function)
local ctrlSheet = webig.sheetLists[sheet_list].ctrl:find("list:"..ctrl)
if ctrlSheet ~= nil then
ctrlSheet.left_click="lua"
ctrlSheet.left_click_params=lua_function.."(\'"..sheet_list.."\', \'"..ctrl.."\')"
ctrlSheet.dragable=false
ctrlSheet.can_drop=false
end
end
function webig:canDropDbSheet(sheet_list, ctrl, src)
webig.sheetLists[sheet_list].ctrl:find("list:"..ctrl).can_drop=true
end
function webig:dropDbSheet(sheet_list, ctrl, src)
local db = webig.sheetLists[sheet_list].db
local sl_id = webig.sheetLists[sheet_list].ctrl.id
if (string.sub(src, 1, string.len(sl_id)) == sl_id) then -- copy from same list sheet
local pos=nil
for i=1, string.len(src) do
if string.sub(src, i, i) == ":" then
pos = i+1
end
end
id = string.sub(src, pos, string.len(src))
webig:swapItems(db..":"..id, db..":"..ctrl)
else
slot = getUI(src)
if slot ~= nil then
id = findReplaceAll(src, slot.parent.id..":", "")
webig:copyItems("LOCAL:INVENTORY:BAG:"..id, db..":"..ctrl)
end
end
end
function webig:addOrRemoveDbSheet(sheet_list, ctrl)
local db = webig.sheetLists[sheet_list].db
if getDbProp(db..":"..ctrl..":SHEET") == 0 then -- Add item
webig:AddDbSheet(sheet_list, ctrl)
else
webig:removeDbSheetQuantity(sheet_list, ctrl)
end
end
function webig:AddDbSheet(sheet_list, ctrl)
runAH(nil, "enter_modal", "group=ui:interface:webig_html_modal")
local whm = getUI("ui:interface:webig_html_modal")
whm.child_resize_h=false
whm.h = 44*webig.sheetLists[sheet_list].size
whm.w = 224
whm = getUI("ui:interface:webig_html_modal:html")
if whm ~= nil then
whm:refresh() -- url need be setted before
end
webig.sheetLists[sheet_list].selection = ctrl
end
function webig:removeDbSheetQuantity(sheet_list, ctrl)
local db = webig.sheetLists[sheet_list].db
webig:copyItems(db..":"..ctrl, "UI:DROP_DESTROY_ITEM:ITEM")
runAH(nil, "set_keyboard_focus", "select_all=true|target=ui:interface:webig_drop_destroy_item_quantity_modal:edit:eb")
getUI("ui:interface:webig_drop_destroy_item_quantity_modal:ok_cancel:ok").onclick_l="lua"
getUI("ui:interface:webig_drop_destroy_item_quantity_modal:ok_cancel:ok").params_l="webig:doRemoveDbSheetQuantity(\'"..sheet_list.."\', \'"..ctrl.."\')"
getUI("ui:interface:webig_drop_destroy_item_quantity_modal:edit:eb").on_enter="lua"
getUI("ui:interface:webig_drop_destroy_item_quantity_modal:edit:eb").on_enter_params="webig:doRemoveDbSheetQuantity(\'"..sheet_list.."\', \'"..ctrl.."\')"
runAH(nil, "enter_modal", "group=ui:interface:webig_drop_destroy_item_quantity_modal")
setDbProp("UI:DROP_DESTROY_ITEM:ITEM:QUANTITY", getDbProp(db..":"..ctrl..":QUANTITY"))
getUI("ui:interface:webig_drop_destroy_item_quantity_modal:edit:eb").input_string=tostring(getDbProp(db..":"..ctrl..":QUANTITY"))
end
function webig:doRemoveDbSheetQuantity(sheet_list, ctrl)
local db = webig.sheetLists[sheet_list].db
runAH(nil, "leave_modal", "group=ui:interface:webig_drop_destroy_item_quantity_modal")
local new_quantity = tonumber(getUI("ui:interface:webig_drop_destroy_item_quantity_modal:edit:eb").input_string)
local current_quantity = getDbProp(db..":"..ctrl..":QUANTITY")
if new_quantity >= current_quantity then
webig:deleteItem(db..":"..ctrl)
else
addDbProp(db..":"..ctrl..":QUANTITY", current_quantity-new_quantity)
end
end
--assert(nil, "RELOADABLE SCRIPT");

View file

@ -0,0 +1,120 @@
<!-- ****************************************** -->
<!-- * WEBIG WIDGETS * -->
<!-- ****************************************** -->
<interface_config>
<root id="interface" x="0" y="0" w="800" h="600" active="true" />
<lua file="webig.lua" />
<!-- //////////// STYLE : webigchat_desc /////////// -->
<style style="webigchat_desc" type="text" fontsize="12" justification="dont_clip_word" color="0 0 0 255" global_color="false" multi_line="true" multi_line_space="0" line_maxw="320" multi_line_maxw_only="true" />
<!-- //////////// STYLE : webigchat_option /////////// -->
<style style="webigchat_option" type="text" format_taged="true" fontsize="10" justification="dont_clip_word" color="0 0 64 255" underlined="true" global_color="false" multi_line="true" multi_line_space="0" line_maxw="320" multi_line_maxw_only="true" />
<!-- //////////// STYLE : webigchat_option_but /////////// -->
<style style="webigchat_option_but" type="button_link" posref="TL TL" x="0" y="0" sizeref="wh" w="0" h="0" onclick_l="proc" params_l="proc_browse_faq" />
<!-- //////////// TEMPLATE : webig_3dbulle_L /////////// -->
<template name="webig_3dbulle_L" id="" keep="true">
<group id="#id" type="in_scene_bubble" header_active="false" options="no_bordure" openable="false" savable="false" resizer="true" movable="false" right_button="false" opened="true" child_resize_w="true" w="0" max_w="512" min_w="48" child_resize_h="true" in_scene_offset_x="-95" win_priority="%win_priority_world_space" posref="BL BR" use_cursor="true">
<group id="header_opened" x="0" y="0" child_resize_w="true" w="0" child_resize_h="true" h="0" max_w="512" min_w="48" max_h="256" min_h="48" posref="TL TL">
<group id="window" x="0" y="0" child_resize_w="true" child_resize_wmargin="10" child_resize_h="true" child_resize_hmargin="10" posref="TL TL">
<group id="back" x="0" y="0" w="0" h="0" sizeref="wh" posref="TL TL">
<view type="bitmap" id="win_M" posref="MM MM" scale="true" sizeref="wh" w="-10" h="-10" texture="Bulle_M.tga" global_color="false" />
<view type="bitmap" id="win_T" posparent="win_M" posref="TL BL" scale="true" sizeref="w" w="0" h="5" texture="Bulle_T.tga" global_color="false" />
<view type="bitmap" id="win_B" posparent="win_M" posref="BL TL" scale="true" sizeref="w" w="0" h="5" texture="Bulle_B.tga" global_color="false" />
<view type="bitmap" id="win_L" posparent="win_M" posref="TL TR" scale="true" sizeref="h" w="5" h="0" texture="Bulle_L.tga" global_color="false" />
<view type="bitmap" id="win_R" posparent="win_M" posref="TR TL" scale="true" sizeref="h" w="5" h="0" texture="Bulle_R.tga" global_color="false" />
<view type="bitmap" id="win_TL" posref="TL TL" texture="Bulle_TL.tga" global_color="false" />
<view type="bitmap" id="win_TR" posref="TR TR" texture="Bulle_TR.tga" global_color="false" />
<view type="bitmap" id="win_BL" posref="BL BL" texture="Bulle_BL.tga" global_color="false" />
<view type="bitmap" id="win_BR" posref="BR BR" texture="Bulle_BR.tga" global_color="false" />
</group>
<view style="webigchat_desc" id="text" posref="TL TL" x="5" y="-24" />
<ctrl type="button" button_type="push_button" tx_normal="Bulle_next.tga" tx_pushed="Bulle_next.tga" tx_over="Bulle_next.tga" color="255 255 255 255" col_over="255 255 255 0" col_pushed="255 255 255 255" global_color_normal="false" global_color_over="false" global_color_pushed="false" tooltip="uiNext" id="but_next" posref="TR TR" x="-5" y="-5" onclick_l="bubble_next" active="false" />
<ctrl type="button" button_type="push_button" tx_normal="Bulle_quit.tga" tx_pushed="Bulle_quit.tga" tx_over="Bulle_quit.tga" color="255 255 255 255" col_over="255 255 255 0" col_pushed="255 255 255 255" global_color_normal="false" global_color_over="false" global_color_pushed="false" tooltip="uiSkip" id="but_skip" posref="TL TR" posparent="but_next" x="-4" y="0" onclick_l="bubble_skip" active="false" />
<!-- Yoyo: Fake to have minimum bubble size -->
<group id="min_w" posparent="text" posref="TL TL" x="0" y="0" w="48" h="14" />
<view style="webigchat_option" id="opt0" posparent="text" posref="BL TL" x="16" y="-4" />
<view style="webigchat_option" id="opt1" posparent="opt0" posref="BL TL" x="0" y="-4" />
<view style="webigchat_option" id="opt2" posparent="opt1" posref="BL TL" x="0" y="-5" />
<view style="webigchat_option" id="opt3" posparent="opt2" posref="BL TL" x="0" y="-5" />
<view style="webigchat_option" id="opt4" posparent="opt3" posref="BL TL" x="0" y="-5" />
<view style="webigchat_option" id="opt5" posparent="opt4" posref="BL TL" x="0" y="-5" />
<view style="webigchat_option" id="opt6" posparent="opt5" posref="BL TL" x="0" y="-5" />
<view style="webigchat_option" id="opt7" posparent="opt6" posref="BL TL" x="0" y="-5" />
<ctrl style="webigchat_option_but" id="optb0" posparent="opt0" params_l="0" />
<ctrl style="webigchat_option_but" id="optb1" posparent="opt1" params_l="1" />
<ctrl style="webigchat_option_but" id="optb2" posparent="opt2" params_l="2" />
<ctrl style="webigchat_option_but" id="optb3" posparent="opt3" params_l="3" />
<ctrl style="webigchat_option_but" id="optb4" posparent="opt4" params_l="4" />
<ctrl style="webigchat_option_but" id="optb5" posparent="opt5" params_l="5" />
<ctrl style="webigchat_option_but" id="optb6" posparent="opt6" params_l="6" />
<ctrl style="webigchat_option_but" id="optb7" posparent="opt7" params_l="7" />
</group>
<view type="bitmap" id="win_talk" posref="BR TR" x="-24" y="2" posparent="window" texture="Bulle_Say_L.tga" global_color="false" />
</group>
</group>
</template>
<!-- //////////// TEMPLATE : webig_modal /////////// -->
<group type="modal" id="webig_html_modal" w="360" posref="TL TL" child_resize_hmargin="8" child_resize_h="true" x="0" y="0" active="false" options="skin_modal" escapable="true" global_color="true">
<group id="html" type="html" posref="MM MM" url="" title_prefix="uiQuickhelpTitle" sizeref="wh" x="0" y="0" w="0" h="0" background_color="0 0 0 0" error_color="255 240 48 255" link_color="240 155 100 255" text_color="210 210 210 255" h1_color="255 255 255 255" h2_color="255 255 255 255" h3_color="255 255 255 255" h4_color="255 255 255 255" h5_color="255 255 255 255" h6_color="255 255 255 255" text_font_size="10" h1_font_size="16" h2_font_size="14" h3_font_size="13" h4_font_size="12" h5_font_size="11" h6_font_size="11" paragraph_begin_space="12" multi_line_space_factor="0.25" td_begin_space="0" li_begin_space="4" ul_begin_space="12" li_indent="-10" ul_indent="30" checkbox_bitmap_normal="patch_off.tga" checkbox_bitmap_pushed="patch_on.tga" checkbox_bitmap_over="" background_bitmap_view="" home="" browse_next_time="false" timeout="0" form_text_area_group="edit_box_widget_multiline" >
<group id="black" posref="BR BR" sizeref="hw" w="-16" h="-12" inherit_gc_alpha="true"/>
<view type="bitmap" id="black2" posparent="black" posref="MM MM" sizeref="wh" w="-2" h="-2" inherit_gc_alpha="true" scale="true" texture="blank.tga" global_color="false"/>
<group type="list" id="text_list" fontsize="9" posref="TL TL" posparent="black" x="2" y="-2" space="0" sizeref="hw" w="-4" h="-4" maxelements="2000"/>
<ctrl style="skin_scroll" id="scroll_bar" />
</group>
</group>
<!-- //////////// MODAL : webig_exchange_choose_in_bag /////////// -->
<group type="modal" id="webig_exchange_choose_in_bag" w="360" child_resize_hmargin="8" child_resize_h="true" x="0" y="0" active="false" options="skin_modal" escapable="true" global_color="true">
<view type="text" id="title" posref="TL TL" x="6" y="-8" color="255 255 255 255" global_color="false" fontsize="10" shadow="true" hardtext="uiBCTitleMPItemType"/>
<group type="list_sheet" id="list" nature="item" posref="TL TL" x="4" y="-20" value="UI:VARIABLES:BOTCHAT:FILTER_ITEM_TYPE_SELECTED" force_item_background_generic="true" wspace="2" hspace="2" array="false" w="350" lmargin="0" rmargin="0" tmargin="2" bmargin="2" child_resize_h="true" onclick_l="confirm_change_botchat_buy_filter_item_type" on_tooltip="botchat_tt_item_type" use_quantity="false" use_quality="false" display_empty_slot="true"/>
<view type="text" id="no_filter" posparent="ctrl" posref="TL MM" x="24" y="-46" fontsize="12" shadow="true" case_mode="%case_upper" global_color="false" hardtext="uiBCNoItemTypeFilter"/>
</group>
<!-- //////////// MODAL : webig_drop_destroy_item_quantity_modal /////////// -->
<group type="modal" id="webig_drop_destroy_item_quantity_modal" exit_click_out="true" posref="TL TL" w="180" h="80" x="-8" y="8" options="skin_modal">
<ctrl type="sheet" id="sheet" value="UI:DROP_DESTROY_ITEM:ITEM" posparent="parent" posref="MM MM" x="-26" y="0"/>
<view type="text" id="x" posparent="sheet" posref="MR MM" x="8" y="0" color="255 255 255 255" fontsize="12" shadow="true" hardtext="X"/>
<instance template="edit_box_widget" entry_type="positive_integer" id="edit" text_ref="TR TR" text_y="-1" fontsize="12" posparent="sheet" posref="MR ML" x="16" text_x="-2" w="32" prompt="" enter_loose_focus="false" multi_line="false" max_num_chars="3" onchange="editbox_number" onchange_params="value=UI:DROP_DESTROY_ITEM:ITEM:QUANTITY|update_text=false" onenter="proc" params="webig_drop_destroy_item_quantity_modal_ok" max_historic="0"/>
<instance template="button_ok_cancel" posref="BR BR" x="-4" y="4" onclick_ok="" onclick_ok_param="" onclick_cancel="leave_modal" onclick_cancel_param=""/>
<link expr="eq(@UI:DROP_DESTROY_ITEM:DROP_MODE,1)" target="drop_text:active"/>
<link expr="ne(@UI:DROP_DESTROY_ITEM:DROP_MODE,1)" target="destroy_text:active"/>
</group>
<!-- //////////// TEMPLATE : webig_list_sheet /////////// -->
<template name="webig_list_sheet" keep="true" db="" w="200" y="-10" x="10">
<group id="list_group" w="#w" y="#y" x="#x" posref="TL TL" child_resize_h="true" >
<group type="list_sheet" nature="item" id="list" posref="TL TL" x="0" y="0" child_resize_h="true" wspace="8" hspace="8" value="#db" array="true" auto_grayed="true" onclick_r="open_item_help" tooltip="uittSelectMp" />
</group>
</template>
<!-- //////////// TEMPLATE : webig_frame_borderless /////////// -->
<template name="webig_frame_borderless" keep="true" w="200" h="200" x="0" y="0" movable="true">
<group id="content" w="#w" h="#h" x="#x" y="#y" posref="MM MM" >
<group id="html" type="html" posref="TL TL" url="" title_prefix="uiQuickhelpTitle" sizeref="wh" x="0" y="0" w="0" h="0" background_color="0 0 0 0" error_color="255 240 48 255" link_color="240 155 100 255" text_color="210 210 210 255" h1_color="255 255 255 255" h2_color="255 255 255 255" h3_color="255 255 255 255" h4_color="255 255 255 255" h5_color="255 255 255 255" h6_color="255 255 255 255" text_font_size="10" h1_font_size="16" h2_font_size="14" h3_font_size="13" h4_font_size="12" h5_font_size="11" h6_font_size="11" paragraph_begin_space="12" multi_line_space_factor="0.25" td_begin_space="0" li_begin_space="4" ul_begin_space="12" li_indent="-10" ul_indent="30" checkbox_bitmap_normal="patch_off.tga" checkbox_bitmap_pushed="patch_on.tga" checkbox_bitmap_over="" background_bitmap_view="" home="" browse_next_time="false" timeout="0" form_text_area_group="edit_box_widget_multiline" >
<group id="black" posref="BR BR" sizeref="hw" w="-16" h="-12" inherit_gc_alpha="true"/>
<view type="bitmap" id="black2" posparent="black" posref="MM MM" sizeref="wh" w="-2" h="-2" inherit_gc_alpha="true" scale="true" texture="blank.tga" global_color="false"/>
<group type="list" id="text_list" fontsize="9" posref="TL TL" posparent="black" x="2" y="-2" space="0" sizeref="hw" w="-4" h="-4" maxelements="2000"/>
<ctrl style="skin_scroll" id="scroll_bar" />
</group>
</group>
</template>
<!-- //////////// TEMPLATE : webig_frame_skin_modal /////////// -->
<template name="webig_frame_skin_modal" keep="true" w="200" h="200" x="0" y="0">
<group id="group" type="container" active="true" w="#w" h="#h" x="#x" y="#y" posref="MM MM" options="skin_modal" opened="true" openable="true" movable="true" header_color="UI:SAVE:WIN:COLORS:COM">
<group id="header_closed" x="0" y="0" w="#w" h="16" posref="TL TL"></group>
<group id="header_opened" x="0" y="0" w="#w" h="16" posref="TL TL"></group>
<group id="content" x="0" y="0" w="0" h="0" posref="TL TL ">
<group id="html" type="html" posref="MM MM" url="" title_prefix="uiQuickhelpTitle" sizeref="wh" x="0" y="0" w="0" h="0" background_color="0 0 0 0" error_color="255 240 48 255" link_color="240 155 100 255" text_color="210 210 210 255" h1_color="255 255 255 255" h2_color="255 255 255 255" h3_color="255 255 255 255" h4_color="255 255 255 255" h5_color="255 255 255 255" h6_color="255 255 255 255" text_font_size="10" h1_font_size="16" h2_font_size="14" h3_font_size="13" h4_font_size="12" h5_font_size="11" h6_font_size="11" paragraph_begin_space="12" multi_line_space_factor="0.25" td_begin_space="0" li_begin_space="4" ul_begin_space="12" li_indent="-10" ul_indent="30" checkbox_bitmap_normal="patch_off.tga" checkbox_bitmap_pushed="patch_on.tga" checkbox_bitmap_over="" background_bitmap_view="" home="" browse_next_time="false" timeout="0" form_text_area_group="edit_box_widget_multiline" >
<group id="black" posref="BR BR" sizeref="hw" w="-16" h="-12" inherit_gc_alpha="true"/>
<view type="bitmap" id="black2" posparent="black" posref="MM MM" sizeref="wh" w="-2" h="-2" inherit_gc_alpha="true" scale="true" texture="blank.tga" global_color="false"/>
<group type="list" id="text_list" fontsize="9" posref="TL TL" posparent="black" x="2" y="-2" space="0" sizeref="hw" w="-4" h="-4" maxelements="2000"/>
<ctrl style="skin_scroll" id="scroll_bar" />
</group>
</group>
</group>
</template>
</interface_config>

View file

@ -1878,6 +1878,8 @@ void CCharacterCL::updateVisualPropertyPvpClan(const NLMISC::TGameCycle &/* game
{
_LeagueId = uint32(prop);
buildInSceneInterface();
if (isUser())
{
uint i;

View file

@ -1347,6 +1347,7 @@ void CClientConfig::setValues()
if (stricmp(mode, "over") == 0) p.Mode = SSysInfoParam::Over;
else if (stricmp(mode, "overonly") == 0) p.Mode = SSysInfoParam::OverOnly;
else if (stricmp(mode, "center") == 0) p.Mode = SSysInfoParam::Center;
else if (stricmp(mode, "centeraround") == 0) p.Mode = SSysInfoParam::CenterAround;
else if (stricmp(mode, "around") == 0) p.Mode = SSysInfoParam::Around;
ClientCfg.SystemInfoParams[toLower(sic->asString(2 * k))] = p;

View file

@ -635,12 +635,15 @@ struct CClientConfig
// Mode is the display settings :
// Normal : just display in the system info window
// Over : must be displayed at bottom of the screen and in system info window
// OverOnly : must be displayed at bottom of the screen
// Center ; must be displayed at the center of the screen and in system info window
// Around ; must be displayed in the around chat window
// CenterAround ; must be displayed at the center of the screen and in around chat window
struct SSysInfoParam
{
CRGBA Color;
std::string SysInfoFxName;
enum TMode { Normal, Over, OverOnly, Center, Around };
enum TMode { Normal, Over, OverOnly, Center, Around, CenterAround };
TMode Mode;
SSysInfoParam()
{

View file

@ -2571,7 +2571,9 @@ class CAHAddShape : public IActionHandler
skel.setPos(CVector((float)x, (float)y, (float)z));
skel.setRotQuat(dir.getRot());
}
} else {
}
else
{
instance.setScale(instance.getScale()*s);
instance.setPos(CVector((float)x, (float)y, (float)z));
instance.setRotQuat(dir.getRot());
@ -3168,7 +3170,6 @@ class CHandlerGameConfigFullscreen : public IActionHandler
// hide frequencies combo
pCB= dynamic_cast<CDBGroupComboBox*>(pIM->getElementFromId( GAME_CONFIG_VIDEO_FREQS_COMBO ));
if (pCB) pCB->setActive(false);
}
// **** dirt the apply button of the DDX

View file

@ -244,6 +244,7 @@ CInterfaceGroup *CInterfaceHelp::activateNextWindow(CDBCtrlSheet *elt, sint forc
i++;
}
bool showSlotAndCreator = false;
// If an active window get the same object, abort, but make it top.
for(i=0;i<_ActiveWindows.size();i++)
{
@ -261,6 +262,8 @@ CInterfaceGroup *CInterfaceHelp::activateNextWindow(CDBCtrlSheet *elt, sint forc
// for items, must also test if they have the same itemSlotId, cause relies also on "ItemInfo system"
if(elt->getType() == CCtrlSheetInfo::SheetType_Item)
{
showSlotAndCreator = true;
CDBCtrlSheet *realCtrlDst= _InfoWindows[_ActiveWindows[i]].CtrlSheet;
if(!realCtrlDst)
ok= false;
@ -344,6 +347,13 @@ CInterfaceGroup *CInterfaceHelp::activateNextWindow(CDBCtrlSheet *elt, sint forc
CInterfaceGroup *group= _InfoWindows[newIndexWindow].Window;
nlassert(group);
CInterfaceElement *ctrl = group->getElement(group->getId()+":content:ctrl_slot");
if (ctrl) ctrl->setActive(showSlotAndCreator);
ctrl = group->getElement(group->getId()+":content:creator");
if (ctrl) ctrl->setActive(showSlotAndCreator);
ctrl = group->getElement(group->getId()+":content:creator_header");
if (ctrl) ctrl->setActive(showSlotAndCreator);
// activate it, set top, copy item watched
group->setActive(true);
pIM->setTopWindow(group);
@ -1217,6 +1227,7 @@ static void setupSkillToTradeHelp(CSheetHelpSetup &setup)
if(setup.DestSheet)
{
setup.SrcSheet->copyAspect(setup.DestSheet);
setup.DestSheet->setActive(true);
}
ucstring skillText;
@ -2278,6 +2289,7 @@ static void setupItemHelp(CSheetHelpSetup &setup)
if(setup.DestSheet)
{
setup.SrcSheet->copyAspect(setup.DestSheet);
setup.DestSheet->setActive(true);
}
// NB: for raw materials only, must do each once only, must not do it at refresh, cause combo reseted
@ -2566,6 +2578,7 @@ static void setupPactHelp(CSheetHelpSetup &setup)
if(setup.DestSheet)
{
setup.SrcSheet->copyAspect(setup.DestSheet);
setup.DestSheet->setActive(true);
}
@ -2603,6 +2616,7 @@ static void setupMissionHelp(CSheetHelpSetup &setup)
if(setup.DestSheet)
{
setup.SrcSheet->copyAspect(setup.DestSheet);
setup.DestSheet->setActive(true);
}
// get detail text id from db
@ -2840,6 +2854,7 @@ void setupOutpostBuildingHelp(CSheetHelpSetup &setup)
if(setup.DestSheet)
{
setup.SrcSheet->copyAspect(setup.DestSheet);
setup.DestSheet->setActive(true);
}
const COutpostBuildingSheet *pOBS = setup.SrcSheet->asOutpostBuildingSheet();
@ -3164,6 +3179,7 @@ void setupSabrinaPhraseHelp(CSheetHelpSetup &setup, const CSPhraseCom &phrase, u
if(setup.DestSheet)
{
setup.SrcSheet->copyAspect(setup.DestSheet);
setup.DestSheet->setActive(true);
}
// **** setup the phrase Text info
@ -3233,6 +3249,7 @@ static void setupSabrinaBrickHelp(CSheetHelpSetup &setup, bool auraDisabled)
if(setup.DestSheet)
{
setup.SrcSheet->copyAspect(setup.DestSheet);
setup.DestSheet->setActive(true);
}

View file

@ -997,7 +997,7 @@ void CBotChatPageTrade::startSellDialog(CDBCtrlSheet *sheet, CCtrlBase * /* pCal
CCtrlTextButton *confirmButton = dynamic_cast<CCtrlTextButton*>(ig->getCtrl("ok"));
if (confirmButton)
{
confirmButton->setActive( sheet->getLockedByOwner() );
confirmButton->setActive( !sheet->getLockedByOwner() );
confirmButton->setText(CI18N::get("uiSellImmediately"));
confirmButton->setDefaultContextHelp(CI18N::get("uittDirectSellButton"));
}

View file

@ -361,7 +361,6 @@ void CGroupHTML::checkDownloads()
CFile::moveFile(file.c_str(), (file+".tmp").c_str());
if (lookupLocalFile (finalUrl, file.c_str(), false))
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
pIM->executeLuaScript(it->luaScript, true);
}

View file

@ -370,8 +370,14 @@ void CGuildManager::update()
{
for (uint j = 0; j < CachedGuildMembers.size(); ++j)
{
if ((CachedGuildMembers[j].Name == _GuildMembers[i].Name) &&
(CachedGuildMembers[j].Online != _GuildMembers[i].Online))
// Status change is from offline to online/abroad online or vice versa.
TCharConnectionState prevState = CachedGuildMembers[j].Online;
TCharConnectionState curState = _GuildMembers[i].Online;
bool showMsg = (prevState != curState) &&
(CachedGuildMembers[j].Name == _GuildMembers[i].Name) &&
(prevState == ccs_offline || curState == ccs_offline);
if (showMsg)
{
ucstring msg = (_GuildMembers[i].Online != ccs_offline) ? onlineMessage : offlineMessage;
strFindReplace(msg, "%s", _GuildMembers[i].Name);

View file

@ -4404,12 +4404,14 @@ void CInterfaceManager::displaySystemInfo(const ucstring &str, const string &cat
}
}
if (mode == CClientConfig::SSysInfoParam::Center || mode == CClientConfig::SSysInfoParam::CenterAround)
InSceneBubbleManager.addMessagePopupCenter(str, color);
// If over popup a string at the bottom of the screen
if ((mode == CClientConfig::SSysInfoParam::Over) || (mode == CClientConfig::SSysInfoParam::OverOnly))
InSceneBubbleManager.addMessagePopup(str, color);
else if (mode == CClientConfig::SSysInfoParam::Center)
InSceneBubbleManager.addMessagePopupCenter(str, color);
else if (mode == CClientConfig::SSysInfoParam::Around && PeopleInterraction.AroundMe.Window)
else if ( (mode == CClientConfig::SSysInfoParam::Around || mode == CClientConfig::SSysInfoParam::CenterAround)
&& PeopleInterraction.AroundMe.Window)
PeopleInterraction.ChatInput.AroundMe.displayMessage(str, color, 2);
}

View file

@ -1420,11 +1420,9 @@ void CPeopleInterraction::updateContactInList(uint32 contactId, TCharConnectionS
sint index = FriendList.getIndexFromContactId(contactId);
if (index != -1)
{
// Only do work if online status has changed
if (FriendList.getOnline(index) != online)
{
// Only do work if online status has changed
FriendList.setOnline(index, online);
CCDBNodeLeaf* node = CInterfaceManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_ONLINE_OFFLINE_NOTIFICATIONS_CB", false);
if (node && node->getValueBool())
{
@ -1441,8 +1439,11 @@ void CPeopleInterraction::updateContactInList(uint32 contactId, TCharConnectionS
}
}
// Player is not in my guild
if (bOnlyFriend)
TCharConnectionState prevState = FriendList.getOnline(index);
bool showMsg = bOnlyFriend && (prevState == ccs_offline || online == ccs_offline);
// Player is not in my guild, and the status change is from offline to online/abroad online or vice versa.
if (showMsg)
{
ucstring msg = (online != ccs_offline) ? CI18N::get("uiPlayerOnline") : CI18N::get("uiPlayerOffline");
strFindReplace(msg, "%s", FriendList.getName(index));
@ -1458,6 +1459,8 @@ void CPeopleInterraction::updateContactInList(uint32 contactId, TCharConnectionS
PeopleInterraction.ChatInput.AroundMe.displayMessage(msg, col, 2, &dummy);
}
}
FriendList.setOnline(index, online);
}
}
}
@ -2088,7 +2091,7 @@ public:
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
{
uint8 teamMember = (uint8) peopleIndex;
out.serialEnum(teamMember);
out.serial(teamMember);
NetMngr.push(out);
//nlinfo("impulseCallBack : %s %d sent", msgName.c_str(), teamMember);
}

View file

@ -1794,6 +1794,7 @@ class CAHOpenURL : public IActionHandler
}
else
{
DWORD ret = 0;
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |

View file

@ -4392,7 +4392,7 @@ bool CEditor::doLuaScript(const char *filename, const char *fileDescText)
return false;
}
if( 0 && FINAL_VERSION == 1) // deactivated for the moment because there are lua file that must be loaded from example
if( 0 && FINAL_VERSION == 1) // disabled for the moment because there are lua file that must be loaded from example
{
const static std::string path = "data_common.bnp@";
const static std::string::size_type len= path.size();

View file

@ -1605,29 +1605,38 @@ const ucchar *CStringManagerClient::getSPhraseLocalizedDescription(NLMISC::CShee
// ***************************************************************************
const ucchar *CStringManagerClient::getTitleLocalizedName(const std::string &titleId, bool women)
{
const ucchar * infos = getSpecialWord(titleId, women);
ucstring infosUC(infos);
vector<ucstring> listInfos;
splitUCString(infosUC, ucstring("#"), listInfos);
if (listInfos.empty())
return infos;
vector<ucstring> listInfos = getTitleInfos(titleId, women);
if (listInfos.size() > 0)
{
_TitleWords.push_back(listInfos[0]);
return _TitleWords.back().c_str();
}
ucstring ucId;
ucId.fromUtf8(titleId);
return ucId.c_str();
}
// ***************************************************************************
vector<ucstring> CStringManagerClient::getTitleInfos(const std::string &titleId, bool women)
{
const ucchar * infos = getSpecialWord(titleId, women);
ucstring infosUC(infos);
ucstring infosUC;
infosUC.fromUtf8(titleId);
vector<ucstring> listInfos;
splitUCString(infosUC, ucstring("#"), listInfos);
if (listInfos.size() > 0)
{
if (titleId[0] != '#')
{
listInfos[0] = getSpecialWord(listInfos[0].toUtf8(), women);
}
}
return listInfos;
}
// ***************************************************************************
const ucchar *CStringManagerClient::getClassificationTypeLocalizedName(EGSPD::CClassificationType::TClassificationType type)
{

View file

@ -108,6 +108,7 @@ public:
// Get the Localized Title name
static const ucchar *getTitleLocalizedName(const std::string &titleId, bool women);
static std::vector<ucstring> getTitleInfos(const std::string &titleId, bool women);
// Get the Localized name of a classification type
static const ucchar *getClassificationTypeLocalizedName(EGSPD::CClassificationType::TClassificationType type);

View file

@ -1,13 +1,32 @@
FILE(GLOB SRC *.cpp time_weather_season/*.cpp)
FILE(GLOB PRIV_H *.h time_weather_season/*.h)
SOURCE_GROUP(headers FILES ${PRIV_H})
FILE(GLOB R2
dms.h dms.cpp
scenario.h scenario.cpp
user_connection_mgr.h user_connection_mgr.cpp
object.h object.cpp
server_animation_module.h server_animation_module.cpp
server_admin_module.h server_admin_module.cpp
server_edition_module.h server_edition_module.cpp
string_mgr_module.h string_mgr_module.cpp
scenario_entry_points.h scenario_entry_points.cpp
small_string_manager.h small_string_manager.cpp
ai_wrapper.h ai_wrapper.cpp
r2_*.h r2_*.cpp
ring_*.h ring_*.cpp)
LIST(REMOVE_ITEM SRC R2)
LIST(REMOVE_ITEM PRIV_H R2)
SOURCE_GROUP("" FILES ${SRC} ${PRIV_H})
SOURCE_GROUP("R2" FILES ${R2})
# Filter out the source files not actually compiled.
LIST(REMOVE_ITEM SRC ${CMAKE_CURRENT_SOURCE_DIR}/enum_template.cpp)
LIST(REMOVE_ITEM PRIV_H ${CMAKE_CURRENT_SOURCE_DIR}/enum_template.h)
NL_TARGET_LIB(ryzom_gameshare ${PRIV_H} ${SRC})
NL_TARGET_LIB(ryzom_gameshare ${PRIV_H} ${SRC} ${R2})
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} ${NEL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})

View file

@ -1108,9 +1108,7 @@ namespace CHARSYNC
void setResult(TCharacterNameResult value)
{
_Result = value;
}
//
uint32 getUserId() const
@ -1120,9 +1118,7 @@ namespace CHARSYNC
void setUserId(uint32 value)
{
_UserId = value;
}
//
uint8 getCharIndex() const
@ -1132,9 +1128,7 @@ namespace CHARSYNC
void setCharIndex(uint8 value)
{
_CharIndex = value;
}
//
const ucstring& getFullName() const
@ -1144,9 +1138,7 @@ namespace CHARSYNC
void setFullName(const ucstring &value)
{
_FullName = value;
}
bool operator == (const CValidateNameResult &other) const
@ -1161,7 +1153,6 @@ namespace CHARSYNC
// constructor
CValidateNameResult()
{
}
void serial(NLMISC::IStream &s)
@ -1170,7 +1161,6 @@ namespace CHARSYNC
s.serial(_UserId);
s.serial(_CharIndex);
s.serial(_FullName);
}

View file

@ -1,6 +1,18 @@
/** \file deployment_configuration.cpp
*
*/
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//-----------------------------------------------------------------------------
// include

View file

@ -1,8 +1,18 @@
/** \file deployment_configuration.h
*
*
*/
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef DEPLOYMENT_CONFIGURATION_H
#define DEPLOYMENT_CONFIGURATION_H

View file

@ -884,6 +884,7 @@ namespace RYMSG
std::vector< NLMISC::CSheetId > _LootList;
//
NLMISC::CSheetId _Outpost;
uint32 _Organization;
//
float _MaxHitRangeForPC;
//
@ -1336,6 +1337,21 @@ namespace RYMSG
_Outpost = value;
}
//
uint32 getOrganization() const
{
return _Organization;
}
void setOrganization(uint32 value)
{
_Organization = value;
}
//
float getMaxHitRangeForPC() const
@ -1431,6 +1447,7 @@ namespace RYMSG
&& _ContextOptions == other._ContextOptions
&& _LootList == other._LootList
&& _Outpost == other._Outpost
&& _Organization == other._Organization
&& _MaxHitRangeForPC == other._MaxHitRangeForPC
&& _UserModelId == other._UserModelId
&& _CustomLootTableId == other._CustomLootTableId
@ -1489,6 +1506,7 @@ namespace RYMSG
s.serialCont(_ContextOptions);
s.serialCont(_LootList);
s.serial(_Outpost);
s.serial(_Organization);
s.serial(_MaxHitRangeForPC);
s.serial(_UserModelId);
s.serial(_CustomLootTableId);

View file

@ -175,6 +175,42 @@
#include "nel/misc/hierarchical_timer.h"
inline uint32 saveGameCycleToSecond(NLMISC::TGameCycle tick)
{
// Evaluate the UTC of this event (with the current date of save). Suppose that 1 second==10 tick
// NB: result should be positive since no event should have been launched before 1970!
if (tick < CTickEventHandler::getGameCycle())
{
NLMISC::TGameCycle tick_dt = CTickEventHandler::getGameCycle() - tick;
uint32 s_dt = tick_dt / 10;
return NLMISC::CTime::getSecondsSince1970() - s_dt;
}
else
{
NLMISC::TGameCycle tick_dt = tick - CTickEventHandler::getGameCycle();
uint32 s_dt = tick_dt / 10;
return NLMISC::CTime::getSecondsSince1970() + s_dt;
}
}
inline NLMISC::TGameCycle loadSecondToGameCycle(uint32 second)
{
if (second < NLMISC::CTime::getSecondsSince1970())
{
uint32 s_dt = NLMISC::CTime::getSecondsSince1970() - second;
NLMISC::TGameCycle tick_dt = s_dt * 10;
return CTickEventHandler::getGameCycle() - tick_dt;
}
else
{
uint32 s_dt = second - NLMISC::CTime::getSecondsSince1970();
NLMISC::TGameCycle tick_dt = s_dt * 10;
return CTickEventHandler::getGameCycle() + tick_dt;
}
}
/*inline uint32 saveGameCycleToSecond(NLMISC::TGameCycle tick)
{
sint32 dt = CTickEventHandler::getGameCycle() - tick;
// Evaluate the UTC of this event (with the current date of save). Suppose that 1 second==10 tick
if (tick < CTickEventHandler::getGameCycle())
return NLMISC::CTime::getSecondsSince1970();
@ -190,7 +226,7 @@ inline NLMISC::TGameCycle loadSecondToGameCycle(uint32 second)
// Convert UTC of the event to game cycle. Suppose that 1 second==10 tick
return CTickEventHandler::getGameCycle() + (second - NLMISC::CTime::getSecondsSince1970())*10;
}
}*/
#endif
// GameCycle property (saved as a UTC of the current game cycle, support server migration)

View file

@ -0,0 +1,174 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef TXT_COMMAND_H
#define TXT_COMMAND_H
//-------------------------------------------------------------------------------------------------
// includes
//-------------------------------------------------------------------------------------------------
#include "nel/misc/types_nl.h"
#include "nel/misc/common.h"
#include "nel/misc/debug.h"
#include "nel/misc/sstring.h"
//-------------------------------------------------------------------------------------------------
// MACRO TXT_COMMAND_SET
//-------------------------------------------------------------------------------------------------
#define TXT_COMMAND_SET(setName,CONTEXT_CLASS)\
class __CTxtCommandSet_##setName: public ITxtCommandSet<CONTEXT_CLASS>\
{\
public:\
static __CTxtCommandSet_##setName* getInstance()\
{\
static __CTxtCommandSet_##setName *p=NULL;\
if (p==NULL) p= new __CTxtCommandSet_##setName;\
return p;\
}\
};\
static CTxtCommandSetPtr<__CTxtCommandSet_##setName> setName;
//-------------------------------------------------------------------------------------------------
// MACRO TXT_COMMAND
//-------------------------------------------------------------------------------------------------
#define TXT_COMMAND(cmdName,setName,CONTEXT_CLASS)\
struct __CTxtCommand_##cmdName: public ITxtCommand<CONTEXT_CLASS>\
{\
static __CTxtCommand_##cmdName* getInstance()\
{\
static __CTxtCommand_##cmdName *p=NULL;\
if (p==NULL) p= new __CTxtCommand_##cmdName;\
return p;\
}\
virtual const char* getName() const {return #cmdName;}\
virtual CTxtCommandResult execute(CONTEXT_CLASS& context,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& fullCmdLine);\
private:\
__CTxtCommand_##cmdName() {}\
};\
static ITxtCommandRegisterer<__CTxtCommand_##cmdName,__CTxtCommandSet_##setName> __CTxtCommand_##cmdName##_Registerer;\
CTxtCommandResult __CTxtCommand_##cmdName::execute(CONTEXT_CLASS& context,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& fullCmdLine)
//-------------------------------------------------------------------------------------------------
// class CTxtCommandResult
//-------------------------------------------------------------------------------------------------
class CTxtCommandResult
{
public:
enum TType
{
SUCCESS, // command execution was successful
SYNTAX_ERROR, // there was a syntax error in the command line
BAD_PERMISSION, // the user doesn't have the right to run the given command
UNKNOWN_COMMAND, // behave as if the command was not recognised
EXECUTION_ERROR // there was an error during execution of the command
};
CTxtCommandResult(const bool& success): _Type(success?SUCCESS:SYNTAX_ERROR) {}
CTxtCommandResult(const TType& type): _Type(type) {}
CTxtCommandResult(const TType& type,const NLMISC::CSString& reason): _Type(type), _Reason(reason) {}
TType getType() const { return _Type; }
const NLMISC::CSString& getReason() const { return _Reason; }
private:
TType _Type;
NLMISC::CSString _Reason;
};
//-------------------------------------------------------------------------------------------------
// class ITxtCommand
//-------------------------------------------------------------------------------------------------
template <class CONTEXT_CLASS> class ITxtCommand
{
public:
virtual const char* getName() const =0;
virtual CTxtCommandResult execute(CONTEXT_CLASS& context,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& fullCmdLine) =0;
};
//-------------------------------------------------------------------------------------------------
// class ITxtCommandRegisterer
//-------------------------------------------------------------------------------------------------
template <class CMD,class SET> struct ITxtCommandRegisterer
{
ITxtCommandRegisterer()
{
SET::getInstance()->registerTxtCommand(CMD::getInstance());
}
};
//-------------------------------------------------------------------------------------------------
// class ITxtCommandSet
//-------------------------------------------------------------------------------------------------
template <class CONTEXT_CLASS> class ITxtCommandSet
{
public:
void registerTxtCommand(ITxtCommand<CONTEXT_CLASS>* txtCommand)
{
nlassert(_TxtCommands.find(txtCommand->getName())==_TxtCommands.end());
_TxtCommands[txtCommand->getName()]= txtCommand;
}
CTxtCommandResult execute(CONTEXT_CLASS& context,const NLMISC::CSString& cmdLine)
{
NLMISC::CSString cmdTail=cmdLine;
NLMISC::CSString keyword=cmdTail.firstWord(true);
typename TTxtCommands::iterator it= _TxtCommands.find(keyword);
if (it==_TxtCommands.end()) return CTxtCommandResult::UNKNOWN_COMMAND;
NLMISC::CVectorSString args;
cmdTail.splitWords(args);
return it->second->execute(context,args,cmdTail,cmdLine);
}
private:
typedef ITxtCommand<CONTEXT_CLASS> TTxtCommand;
typedef std::map<NLMISC::CSString,TTxtCommand*> TTxtCommands;
TTxtCommands _TxtCommands;
};
//-------------------------------------------------------------------------------------------------
// class ITxtCommandRegisterer
//-------------------------------------------------------------------------------------------------
template <class SET> struct CTxtCommandSetPtr
{
CTxtCommandSetPtr()
{
SET::getInstance();
}
SET& operator*()
{
return *SET::getInstance();
}
SET* operator->()
{
return SET::getInstance();
}
};
//-------------------------------------------------------------------------------------------------
#endif

View file

@ -40,6 +40,9 @@ forceTargetToDie :DEV:SGM:GM:EM: // Force entity target to die
getEventFaction :DEV:SGM:GM:EM: // Get the event faction of player: <player name>
giveRespawnPoint :DEV:SGM:GM: // Give a respawn point to a player: <respawn point name>
guildInvite // Send a guild invite to a player character without distance constrainte
setLeague // Create a League
leagueInvite // Send a League invite to a Team Leader character without distance constrainte
leagueKick // Kick a player or team from league
roomInvite // Send a room invite
roomKick // Remove a room invite
guildMOTD // Set the guild message of the day, command effective only for officer and more graded guild members
@ -72,8 +75,6 @@ renameGuild :DEV:SGM:GM:EM: // Rename a guild: <guild name> <new guild name
renamePlayer [SU] :DEV:SGM:GM:EM: // Rename a player: <player name> <new playerName>
renamePlayerForEvent :DEV:SGM:GM:EM:EG: // Rename a player temporarily for an event: <player name> <new playerName>
resetPowerFlags :DEV:SGM:GM:EM: // Reset the ineffective aura and the power flags for given character
respawnAfterDeath // Respawn after death at re-spawn point name, it must be valid (validated by PC and usable): <Respawn idx>
resurrected // Another PC resurrect PC by giving some energy: <Hp> <Sta> <Sap> <Focus>
root :DEV:SGM:GM:EM:VG:SG: // Root a player: <player name> <time in seconds>
saveToPDR :DEV:SGM: // Save a character to a binary PDR file: <file name>
saveToXML :DEV:SGM: // Save a character to an XML file: <file name>
@ -87,6 +88,8 @@ setGuildMessage // Set the guild message of the day: <message>
setItemSapLoad :DEV:SGM:GM:EM: // Set an item sap load: <slot index in bag (starts at 0)> <float value>
setPosFlag :DEV:SGM:GM:EM // Set a position flag: <flag name>
setPvPTag // Set player character PvP tag to true or false
setFamePlayer :DEV:SGM:GM:EM: // Set the fame value of a player in the given faction: <faction> <fame>
resetPVPTimers :DEV:SGM:GM:EM: // Reset the pvp timers of a player: <player name>
setSkillsToMaxValue :DEV:SGM:GM:EM: // Set player skills to max value
showCSR :DEV:SGM:GM:VG:SG:G:EM:EG: // Show CSR title if the player is a CSR
showFBT :DEV:SGM:GM:EM: // Show Focus Beta Tester title if the player is a FBT
@ -100,6 +103,7 @@ connectUserChannel // Connect to User Channel Chat
webExecCommand // Execute web command (need HMAC signature)
webDelCommandsIds // Delete web transactions for web_app
webAddCommandsIds // Add web command transactions for web_app
updateTarget // Update current target
teleport :DEV:SGM:GM:VG:SG:G:OBSERVER:EM:EG: // Teleport the CSR in front of a player: <player name>
tpPosFlag :DEV:SGM:GM:VG:SG:G:EM:EG: // Teleport a player to a position flag: <flag name>
universe :DEV:SGM:GM:EM: // Chat in universe mode: <boolean>
@ -107,7 +111,6 @@ unmute :DEV:SGM:GM:EM:VG:SG: // Unmute a user: <player name>
unmuteUniverse :DEV:SGM:GM:EM:VG:SG: // Unmute the universe channel
unroot :DEV:SGM:GM:EM:VG:SG: // Stop rooting a player: <player name>
updateGuildMembersList :DEV:SGM:GM: // update guild members list on members clients: <guild name>
validateRespawnPoint // Validate re-spawn point: <Re-spawn point idx>
//setPvpClan :DEV: // choose a clan for pvp
summonPet // player can summon it's pet one time only
allowSummonPet :DEV:SGM:GM: // autorize player to summon it's pet one time per pet
@ -121,6 +124,14 @@ farTPReturn :DEV:SGM:GM:VG:SG:EM: // used to tp back to your previous sessio
characterMissionDump :DEV:SGM:GM: //Dump mission list for a character
removeMission :DEV:SGM:GM: //Remove a mission of a character
addMission :DEV:SGM:GM: //add a mission to a character
characterInventoryDump :DEV:SGM:GM:EM: // Dump character inventory info: <inventory> <from slot> <to slot>
deleteInventoryItem :DEV:SGM:GM:EM: // Delete an item from a characters inventory: <inventory> <slot> <sheetname> <quality> <quantity>
lockItem // Lock/unlock item for trading, selling, destruction.
setTeamLeader // Set the team leader
setPetAnimalSatiety :DEV:SGM:GM:EM: // Set the satiety of pet animal (petIndex in 0..3): <petIndex> full|<value> [<nameForAnswer>]
getPetAnimalSatiety :DEV:SGM:GM:EM: // Get the satiety of pet animal (petIndex in 0..3): <petIndex> [<nameForAnswer>]
setPetAnimalName :DEV:SGM:GM:EM:EG: // Set the name of a pet animal (petIndex in 0..3): <petIndex> <name>
setSimplePhrase :DEV:SGM:GM:EM: // Set an IOS phrase: <id> <phrase> [<language code>]
// Variables
//
@ -138,6 +149,7 @@ Name :DEV:SGM:GM:EM: // Name of a player
Position :DEV:SGM:GM:VG:PR:OBSERVER:EM:EG: // Position of a player (in meters) <posx>,<posy>[,<posz>]] | <bot name> | <player name> | home
Priv :DEV: // User privilege
PriviledgePVP :DEV:SGM:GM:EM:EG: // Turns PVP on/off on character (blame coder for typo)
FullPVP :DEV:SGM:GM:EM:EG: // Turns Full PVP on/off on character (blame coder for typo)
RyzomDate :DEV:SGM:GM:EM: // Current ryzom date
RyzomTime :DEV:SGM:GM:EM: // Current ryzom time
@ -160,3 +172,8 @@ eventSetBotFameByKill :DEV:SGM:GM:EM: // Changes the amount of fame earned fo
eventSetBotURL :DEV:SGM:GM:EM: // Set the url of a bot
eventSetBotURLName :DEV:SGM:GM:EM: // Set the url name of a bot
eventSpawnToxic :DEV:SGM:GM:EM: // Add toxic cloud
eventNpcSay :DEV:SGM:GM:EM: // Have an NPC say a text
eventSetBotFacing :DEV:SGM:GM:EM: // Set the direction in which a bot faces
eventGiveControl :DEV:SGM:GM:EM: // Give control of entity A to entity B : <master eid> <slave eid>
eventLeaveControl :DEV:SGM:GM:EM: // Leave control of entity : <master eid>
resetName // Reset player's name; undo a temporary rename

View file

@ -34,7 +34,7 @@ ADD_SUBDIRECTORY(patchman_service)
#ADD_SUBDIRECTORY(ags_test)
#ADD_SUBDIRECTORY(ai_data_service)
#ADD_SUBDIRECTORY(entity_view_service)
#ADD_SUBDIRECTORY(general_utilities_service)
ADD_SUBDIRECTORY(general_utilities_service)
# Not sure, no longer used maybe?
#sabrina

View file

@ -423,6 +423,15 @@ void CAIS::update()
_CreatureChangeHPList.Entities.clear();
_CreatureChangeHPList.DeltaHp.clear();
}
if (!_CreatureChangeMaxHPList.Entities.empty())
{
nlassert(_CreatureChangeMaxHPList.Entities.size()==_CreatureChangeMaxHPList.MaxHp.size());
nlassert(_CreatureChangeMaxHPList.Entities.size()==_CreatureChangeMaxHPList.SetFull.size());
_CreatureChangeMaxHPList.send("EGS");
_CreatureChangeMaxHPList.Entities.clear();
_CreatureChangeMaxHPList.MaxHp.clear();
_CreatureChangeMaxHPList.SetFull.clear();
}
}
//

View file

@ -222,6 +222,11 @@ public:
return _CreatureChangeHPList;
}
CChangeCreatureMaxHPMsg &getCreatureChangeMaxHP()
{
return _CreatureChangeMaxHPList;
}
enum TSearchType
{
AI_INSTANCE = 0,
@ -288,6 +293,7 @@ private:
// Faunas descriptions to be sent each frame
CFaunaBotDescription _FaunaDescriptionList;
CChangeCreatureHPMsg _CreatureChangeHPList;
CChangeCreatureMaxHPMsg _CreatureChangeMaxHPList;
/// The emot identifiers
std::map<std::string, uint32> _EmotNames;

View file

@ -61,7 +61,7 @@ CAIInstance* CSpawnBot::getAIInstance() const
void CSpawnBot::setVisualPropertiesName()
{
CBot& botRef = CSpawnBot::getPersistent();
std::string name = botRef.getName();
ucstring name = botRef.getName();
if (CVisualPropertiesInterface::UseIdForName)
{
@ -403,8 +403,8 @@ std::vector<std::string> CBot::getMultiLineInfoString() const
pushTitle(container, "CBot");
pushEntry(container, "id=" + getIndexString());
container.back() += " eid=" + getEntityIdString();
container.back() += " alias=" + getAliasTreeOwner()->getAliasString();
container.back() += " name=" + getName();
container.back() += " alias=" + getAliasTreeOwner()->getAliasString() + " raw alias=" + NLMISC::toString(getAliasTreeOwner()->getAlias());
pushEntry(container, " name=" + getName());
if (isSheetValid())
container.back() += " sheet=" + NLMISC::CFile::getFilenameWithoutExtension(getSheet()->SheetId().toString());
pushEntry(container, "fullname=" + getFullName());

View file

@ -95,7 +95,7 @@ public:
virtual float getAggroPropagationRadius() const;
//@}
void setVisualPropertiesName();
virtual void setVisualPropertiesName();
// as there not a lot of prop (1 or 2, maybe 3) stores in this comportment, we don't need hash.
bool getProp(size_t Id, uint32& value) const;
@ -241,8 +241,8 @@ public:
NLMISC::CEntityId createEntityId() const;
const std::string& getCustomName() const { return _CustomName; }
void setCustomName(const std::string &name) { _CustomName = name; }
const ucstring& getCustomName() const { return _CustomName; }
void setCustomName(const ucstring &name) { _CustomName = name; }
virtual void setClientSheet(const std::string & clientSheetName);
@ -272,7 +272,7 @@ private:
bool _IgnoreOffensiveActions;
bool _Healer;
bool _BuildingBot;
std::string _CustomName;
ucstring _CustomName;
CTimer _SetSheetTimer;
struct CSetSheetData
{

View file

@ -274,9 +274,12 @@ std::vector<std::string> CSpawnBotNpc::getMultiLineInfoString() const
else
{
vector<uint32> const& missions = _CurrentChatProfile.getMissions();
pushEntry(container, "missions: " + NLMISC::toString("%u", missions[0]));
for (size_t i=1; i<missions.size(); ++i)
container.back() += ", " + NLMISC::toString("%u", missions[i]);
pushEntry(container, "missions:");
for (size_t i=0; i<missions.size(); ++i)
{
string name = getAIInstance()->findMissionName(missions[i]);
pushEntry(container, NLMISC::toString(" %u (%s)", missions[i], name.c_str()));
}
}
pushFooter(container);

View file

@ -16,6 +16,7 @@
#include "stdpch.h"
#include "ai_bot_pet.h"
#include "visual_properties_interface.h"
#include "nel/misc/random.h"
#include "ai_grp_pet.h"
@ -92,3 +93,28 @@ CSpawnGroupPet& CSpawnBotPet::spawnGrp()
{
return static_cast<CSpawnGroupPet&>(CSpawnBot::spawnGrp());
}
void CSpawnBotPet::setVisualPropertiesName()
{
CBotPet& botRef = CSpawnBotPet::getPersistent();
ucstring name = botRef.getName();
if (CVisualPropertiesInterface::UseIdForName)
{
name = NLMISC::toString("AI:%s", botRef.getIndexString().c_str());
}
if (name.empty() && CVisualPropertiesInterface::ForceNames)
{
name = NLMISC::CFile::getFilenameWithoutExtension(botRef.getSheet()->SheetId().toString().c_str());
}
if (!botRef.getCustomName().empty())
name = botRef.getCustomName();
// no name the bot will appear without name on the client.
if (name.empty())
return;
CVisualPropertiesInterface::setName(dataSetRow(), name);
}

View file

@ -66,6 +66,8 @@ public:
uint32 _DeathTime;
void setVisualPropertiesName();
private:
CPathPosition _PathPos;

View file

@ -653,7 +653,7 @@ static float randomAngle()
return val;
}
CGroupNpc* CAIInstance::eventCreateNpcGroup(uint nbBots, NLMISC::CSheetId const& sheetId, CAIVector const& pos, double dispersionRadius, bool spawnBots, double orientation, const std::string &botsName)
CGroupNpc* CAIInstance::eventCreateNpcGroup(uint nbBots, NLMISC::CSheetId const& sheetId, CAIVector const& pos, double dispersionRadius, bool spawnBots, double orientation, const std::string &botsName, const std::string &look)
{
if (!_EventNpcManager)
return NULL;
@ -689,10 +689,13 @@ CGroupNpc* CAIInstance::eventCreateNpcGroup(uint nbBots, NLMISC::CSheetId const&
CBotNpc* const bot = NLMISC::safe_cast<CBotNpc*>(grp->bots()[i]);
bot->setSheet(sheet);
if (!look.empty())
bot->setClientSheet(look);
bot->equipmentInit();
bot->initEnergy(/*groupEnergyCoef()*/0);
CAIVector rpos(pos);
if (i!=0)
// Spawn all randomly except if only 1 bot
if (nbBots > 1)
{
RYAI_MAP_CRUNCH::CWorldMap const& worldMap = CWorldContainer::getWorldMap();
RYAI_MAP_CRUNCH::CWorldPosition wp;
@ -857,6 +860,7 @@ void cbEventCreateNpcGroup( NLNET::CMessage& msgin, const std::string &serviceNa
double dispersionRadius;
bool spawnBots;
std::string botsName;
std::string look;
msgin.serial(messageVersion);
nlassert(messageVersion==1);
msgin.serial(instanceNumber);
@ -869,10 +873,11 @@ void cbEventCreateNpcGroup( NLNET::CMessage& msgin, const std::string &serviceNa
msgin.serial(dispersionRadius);
msgin.serial(spawnBots);
msgin.serial(botsName);
msgin.serial(look);
CAIInstance* instance = CAIS::instance().getAIInstance(instanceNumber);
if (instance)
{
CGroupNpc* npcGroup = instance->eventCreateNpcGroup(nbBots, sheetId, CAIVector((double)x/1000., (double)y/1000.), dispersionRadius, spawnBots, (double)orientation/1000., botsName);
CGroupNpc* npcGroup = instance->eventCreateNpcGroup(nbBots, sheetId, CAIVector((double)x/1000., (double)y/1000.), dispersionRadius, spawnBots, (double)orientation/1000., botsName, look);
if (npcGroup != NULL)
{
_PlayersLastCreatedNpcGroup[playerId] = npcGroup->getName();

View file

@ -207,7 +207,7 @@ public:
return NULL;
}
CGroupNpc* eventCreateNpcGroup(uint nbBots, NLMISC::CSheetId const& sheetId, CAIVector const& pos, double dispersionRadius, bool spawnBots, double orientation, const std::string &botsName);
CGroupNpc* eventCreateNpcGroup(uint nbBots, NLMISC::CSheetId const& sheetId, CAIVector const& pos, double dispersionRadius, bool spawnBots, double orientation, const std::string &botsName, const std::string &look);
/// create a new easter egg
CBotEasterEgg* createEasterEgg(uint32 easterEggId, NLMISC::CSheetId const& sheetId, std::string const& botName, double x, double y, double z, double heading, const std::string& look);

View file

@ -291,6 +291,11 @@ void CPetSpawnMsgImp::callback(std::string const& name, NLNET::TServiceId id)
botPet->setSheet(sheet);
if (!CustomName.empty())
{
botPet->setCustomName(CustomName);
}
if (!botPet->spawn())
{
confirmMsg.SpawnError = CPetSpawnConfirmationMsg::INTERNAL_ERROR;

View file

@ -873,14 +873,20 @@ void COutpost::createSquad(CGroupDesc<COutpostSquadFamily> const* groupDesc, COu
// Attack only the declared ennemies of the outpost
if (side==OUTPOSTENUMS::OutpostOwner)
{
// grp->faction ().addProperty(NLMISC::toString("outpost:%s:defender", getAliasString().c_str()));
// grp->friendFaction().addProperty(NLMISC::toString("outpost:%s:defender", getAliasString().c_str()));
// Bots factions
grp->faction ().addProperty(NLMISC::toString("outpost:%s:bot_defender", getAliasString().c_str()));
grp->friendFaction().addProperty(NLMISC::toString("outpost:%s:bot_defender", getAliasString().c_str()));
grp->ennemyFaction().addProperty(NLMISC::toString("outpost:%s:bot_attacker", getAliasString().c_str()));
// Players faction
grp->ennemyFaction().addProperty(NLMISC::toString("outpost:%s:attacker", getAliasString().c_str()));
}
if (side==OUTPOSTENUMS::OutpostAttacker)
{
// grp->faction ().addProperty(NLMISC::toString("outpost:%s:attacker", getAliasString().c_str()));
// grp->friendFaction().addProperty(NLMISC::toString("outpost:%s:attacker", getAliasString().c_str()));
// Bots factions
grp->faction ().addProperty(NLMISC::toString("outpost:%s:bot_attacker", getAliasString().c_str()));
grp->friendFaction().addProperty(NLMISC::toString("outpost:%s:bot_attacker", getAliasString().c_str()));
grp->ennemyFaction().addProperty(NLMISC::toString("outpost:%s:bot_defender", getAliasString().c_str()));
// Players faction
grp->ennemyFaction().addProperty(NLMISC::toString("outpost:%s:defender", getAliasString().c_str()));
}
grp->_AggroRange = 25;

View file

@ -1562,7 +1562,7 @@ void CGrpProfileGoToPoint::updateProfile(uint ticksSinceLastUpdate)
dx+=dir.x;
dy+=dir.y;
// 4 rangées.
// 4 rows
CAIVector idealPos=groupPosition;
if (botIndex>=_NbBotInNormalShape)
{
@ -2054,7 +2054,7 @@ void CGrpProfileFollowRoute::updateProfile(uint ticksSinceLastUpdate)
dx+=dir.x;
dy+=dir.y;
// 4 rangées.
// 4 rows
CAIVector idealPos=groupPosition;
if (botIndex>=_NbBotInNormalShape)
{
@ -2299,6 +2299,94 @@ void CGrpProfileStandOnVertices::updateProfile(uint ticksSinceLastUpdate)
}
}
//////////////////////////////////////////////////////////////////////////////
// CGrpProfileFollowPlayer //
//////////////////////////////////////////////////////////////////////////////
CGrpProfileFollowPlayer::CGrpProfileFollowPlayer(CProfileOwner* owner, TDataSetRow const& playerRow, uint32 dispersionRadius)
: CMoveProfile(owner)
, _PlayerRow(playerRow)
, _DispersionRadius(dispersionRadius)
, _PathPos(CAngle(0))
, _PathCont(NLMISC::safe_cast<CSpawnBotNpc*>(owner)->getAStarFlag())
{
PROFILE_LOG("group", "follow player", "ctor", "");
_Status = CFollowPath::FOLLOWING;
}
bool CGrpProfileFollowPlayer::destinationReach() const
{
return _Status == CFollowPath::FOLLOW_ARRIVED
|| _Status==CFollowPath::FOLLOW_NO_PATH;
}
void CGrpProfileFollowPlayer::beginProfile()
{
_Status = CFollowPath::FOLLOWING;
}
// TODO: this doesn't work very well at all...
void CGrpProfileFollowPlayer::updateProfile(uint ticksSinceLastUpdate)
{
H_AUTO(CGrpProfileFollowPlayerUpdate);
CFollowPathContext fpcGrpFollowPlayerUpdate("CGrpProfileFollowPlayerUpdate");
// check all bot to see if there need to move
CSpawnGroupNpc* grp = static_cast<CSpawnGroupNpc*>(static_cast<CSpawnGroup*>(_Grp));
CGroupNpc &pgrp = grp->getPersistent();
CBotPlayer* plrPtr = dynamic_cast<CBotPlayer*>(CAIS::instance().getEntityPhysical(_PlayerRow));
if ( ! plrPtr) {
nlwarning("CGrpProfileFollowPlayer: No valid player position to follow");
return;
}
_PathCont.setDestination(plrPtr->wpos());
_PathPos._Angle = plrPtr->theta();
for (uint i = 0; i < pgrp.bots().size(); ++i)
{
CBotNpc* bot = static_cast<CBotNpc*>(pgrp.bots()[i]);
if (!bot)
continue;
// check current bot state
CSpawnBotNpc *sbot = bot->getSpawn();
if (!sbot)
continue;
// Need to wait for a correct position before moving?
CAIVector const& dest = _PathCont.getDestination();
if (dest.x()==0 || dest.y()==0)
return;
static const std::string runParameter("running");
float dist;
if (sbot->getPersistent().getOwner()->getSpawnObj()->checkProfileParameter(runParameter))
dist = sbot->runSpeed()*ticksSinceLastUpdate;
else
dist = sbot->walkSpeed()*ticksSinceLastUpdate;
// Move
CFollowPath::TFollowStatus const status = CFollowPath::getInstance()->followPath(
sbot,
_PathPos,
_PathCont,
dist,
0.f,
0.5f);
if (status==CFollowPath::FOLLOW_NO_PATH)
{
nlwarning("Problem with following player");
}
}
}
//////////////////////////////////////////////////////////////////////////////
// CGrpProfileIdle //
//////////////////////////////////////////////////////////////////////////////
@ -3687,10 +3775,14 @@ bool CGrpProfileFaction::entityHavePartOfFactions(CAIEntityPhysical const* entit
std::set<TStringId>::const_iterator it, end = factionsSet.end();
for (it=factionsSet.begin(); it!=end; ++it)
{
std::string fameFaction = scriptFactionToFameFaction(CStringMapper::unmap(*it));
string factionInfos = CStringMapper::unmap(*it);
string fameFaction = scriptFactionToFameFaction(factionInfos);
// sint32 fame = CFameInterface::getInstance().getFameOrCivilisationFame(entity->getEntityId(), CStringMapper::map(fameFaction));
sint32 const fame = entity->getFame(fameFaction);
if (fame!=NO_FAME && fame>0)
sint32 const value = scriptFactionToFameFactionValue(factionInfos);
bool gt = scriptFactionToFameFactionGreaterThan(factionInfos);
if ((fame != NO_FAME && gt && fame > value) ||
(fame != NO_FAME && !gt && fame < value))
{
// nldebug("Entity has faction %s", CStringMapper::unmap(*it).c_str());
return true;
@ -3731,12 +3823,41 @@ std::string CGrpProfileFaction::scriptFactionToFameFaction(std::string name)
ret += "_";
ret += name[i]-'A'+'a';
}
else if (name[i] == '>' || name[i] == '<')
{
return ret;
}
else
{
ret += name[i];
}
}
return ret;
}
bool CGrpProfileFaction::scriptFactionToFameFactionGreaterThan(string name)
{
if (name.find("<") != string::npos)
return false;
return true;
}
sint32 CGrpProfileFaction::scriptFactionToFameFactionValue(string name)
{
size_t start = name.find(">");
if (start == string::npos)
{
start = name.find("<");
if (start == string::npos)
return 0;
}
sint32 value;
NLMISC::fromString(name.substr(start+1), value);
return value*6000;
}
std::string CGrpProfileFaction::fameFactionToScriptFaction(std::string name)
{
std::string ret = "Famous";
@ -3772,9 +3893,9 @@ void CGrpProfileFaction::checkTargetsAround()
CPropertySetWithExtraList<TAllianceId> const& thisEnnemyFactions = thisGrpNpc.ennemyFaction();
// We don't assist or attack players if our friends/ennemies are not in factions
bool const assistPlayers = thisFriendFactions.containsPartOfStrict(_FameFactions);
bool const assistPlayers = (thisFriendFactions.containsPartOfStrictFilter("Famous*") || thisFriendFactions.have(AITYPES::CPropertyId("Player")));
bool const assistBots = !thisFriendFactions.empty() && !bNoAssist;
bool const attackPlayers = (!thisEnnemyFactions.extraSetEmpty()) || thisEnnemyFactions.containsPartOfStrict(_FameFactions) || thisEnnemyFactions.containsPartOfStrictFilter("outpost:*");
bool const attackPlayers = (!thisEnnemyFactions.extraSetEmpty()) || thisEnnemyFactions.containsPartOfStrictFilter("Famous*") || thisEnnemyFactions.have(AITYPES::CPropertyId("Player")) || thisEnnemyFactions.containsPartOfStrictFilter("outpost:*");
bool const attackBots = !thisEnnemyFactions.empty();
CAIVision<CPersistentOfPhysical> Vision;

View file

@ -628,6 +628,49 @@ private:
CAITimer _Timer;
};
class CGrpProfileFollowPlayer :
public CMoveProfile
{
public:
CGrpProfileFollowPlayer(CProfileOwner* owner, TDataSetRow const& playerRow, uint32 dispersionRadius);
virtual ~CGrpProfileFollowPlayer() {};
void setBotStandProfile(AITYPES::TProfiles botStandProfileType, IAIProfileFactory* botStandProfileFactory);
/// @name IAIProfile implementation
//@{
virtual void beginProfile();
virtual void updateProfile(uint ticksSinceLastUpdate);
virtual void endProfile() {};
virtual AITYPES::TProfiles getAIProfileType() const { return AITYPES::BOT_FOLLOW_POS; }
virtual std::string getOneLineInfoString() const { return std::string("follow_player group profile"); }
//@}
void stateChangeProfile() {};
bool destinationReach() const;
void addBot (CBot* bot) {};
void removeBot (CBot* bot) {};
CPathCont* getPathCont (CBot const* bot) { return NULL; };
protected:
private:
/// the profile type to apply to bot standing between two deplacement
AITYPES::TProfiles _BotStandProfileType;
/// the profile factory to apply to bot standing between two deplacement
IAIProfileFactory*_BotStandProfileFactory;
CFollowPath::TFollowStatus _Status;
CPathPosition _PathPos;
CPathCont _PathCont;
CAIVector _LastPos;
TDataSetRow _PlayerRow;
uint32 _DispersionRadius;
};
//////////////////////////////////////////////////////////////////////////////
// CGrpProfileIdle //
//////////////////////////////////////////////////////////////////////////////
@ -792,6 +835,10 @@ public:
static std::string scriptFactionToFameFaction(std::string name);
static std::string fameFactionToScriptFaction(std::string name);
static bool scriptFactionToFameFactionGreaterThan(std::string name);
static sint32 scriptFactionToFameFactionValue(std::string name);
private:
CAITimer _checkTargetTimer;
bool bNoAssist;

View file

@ -259,7 +259,7 @@ NLMISC_COMMAND(eventCreateNpcGroup, "create an event npc group", "<aiInstanceId>
std::string botsName;
if (args.size()>8) botsName = args[8];
aiInstance->eventCreateNpcGroup(nbBots, sheetId, CAIVector(x, y), dispersionRadius, spawnBots, orientation, botsName);
aiInstance->eventCreateNpcGroup(nbBots, sheetId, CAIVector(x, y), dispersionRadius, spawnBots, orientation, botsName, "");
return true;
}

View file

@ -3013,7 +3013,10 @@ public:
}
if(!_Id)
npcChatToChannelSentence(bot->dataSetRow(),CChatGroup::say,_Sentence);
{
ucstring ucstr = _Sentence;
npcChatToChannelSentence(bot->dataSetRow(),CChatGroup::say, ucstr);
}
else
{
if(!_Arg)

View file

@ -697,7 +697,8 @@ void CMessages::init()
TRANSPORT_CLASS_REGISTER (CReportStaticAIInstanceMsg);
TRANSPORT_CLASS_REGISTER (CReportAIInstanceDespawnMsg);
TRANSPORT_CLASS_REGISTER (CWarnBadInstanceMsgImp);
TRANSPORT_CLASS_REGISTER (CCreatureSetUrlMsg);
TRANSPORT_CLASS_REGISTER (CChangeCreatureMaxHPMsg)
TRANSPORT_CLASS_REGISTER (CChangeCreatureHPMsg);
TRANSPORT_CLASS_REGISTER (CChangeCreatureModeMsgImp);
TRANSPORT_CLASS_REGISTER (CQueryEgs);
@ -770,10 +771,10 @@ void CAIAskForInfosOnEntityImp::callback (const std::string &name, NLNET::TServi
}
break;
default:
break;
}
std::vector<std::string> strings = phys->getMultiLineInfoString();
msg.Infos.insert(msg.Infos.end(), strings.begin(), strings.end());
break;
}
}
else
{

View file

@ -1497,6 +1497,41 @@ void setAutoSpawn_f_(CStateInstance* entity, CScriptStack& stack)
// HP related methods
/** @page code
@subsection setMaxHP_ff_
Sets the Max HP level of each bot of the group.
Arguments: f(MaxHp) f(SetFull) ->
@param[in] MaxHP is the new maximum HP for each bot
@param[in] SetFull if not 0, will set the HP to the new maximum
@code
()setMaxHP(50000,1);
@endcode
*/
// CGroup
void setMaxHP_ff_(CStateInstance* entity, CScriptStack& stack)
{
bool setFull = ((float)stack.top() != 0.f); stack.pop();
float maxHp = ((float)stack.top()); stack.pop();
CChangeCreatureMaxHPMsg& msgList = CAIS::instance().getCreatureChangeMaxHP();
FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
{
if (!bot->isSpawned())
continue;
CSpawnBot* const sbot = bot->getSpawnObj();
msgList.Entities.push_back(sbot->dataSetRow());
msgList.MaxHp.push_back((uint32)(maxHp));
msgList.SetFull.push_back((uint8)(setFull?1:0));
}
}
/** @page code
@subsection setHPLevel_f_
Sets the current HP level of each bot of the group.
@ -1573,10 +1608,42 @@ void setHPScale_f_(CStateInstance* entity, CScriptStack& stack)
}
}
//----------------------------------------------------------------------------
// Url related method
/** @page code
@subsection setUrl_ss_
Sets the name and url of right-click action
Arguments: s(actionName),s(url) ->
@param[in] actionName of action when player mouse over
@param[in] url of action when player mouse over
@code
()setUrl("Click on Me", "http://www.domain.com/script.php");
@endcode
*/
// CGroup
void setUrl_ss_(CStateInstance* entity, CScriptStack& stack)
{
std::string url = (std::string)stack.top();stack.pop();
std::string actionName = (std::string)stack.top();stack.pop();
CCreatureSetUrlMsg msg;
FOREACH(botIt, CCont<CBot>, entity->getGroup()->bots())
{
CSpawnBot* pbot = botIt->getSpawnObj();
if (pbot!=NULL)
{
msg.Entities.push_back(pbot->dataSetRow());
}
}
msg.ActionName = actionName;
msg.Url = url;
msg.send(egsString);
}
@ -1870,7 +1937,7 @@ Arguments: s(parameterName) ->
@param[in] parameterName is a the id of the parameter to add
@code
()addProfileParameter("running"); // équivalent à un parameter "running" dans la primitive du groupe
()addProfileParameter("running"); // equivalent to "running" parameter in group primitive
@endcode
*/
@ -1898,7 +1965,7 @@ Arguments: s(parameterName),s(parameterContent) ->
@param[in] parameterContent is the value of the parameter
@code
()addProfileParameter("foo", "bar"); // équivalent à un parameter "foo:bar" dans la primitive du groupe
()addProfileParameter("foo", "bar"); // equivalent to "foo:bar" parameter in group primitive
@endcode
*/
@ -1927,7 +1994,7 @@ Arguments: s(parameterName),f(parameterContent) ->
@param[in] parameterContent is the value of the parameter
@code
()addProfileParameter("foo", 0.5); // équivalent à un parameter "foo:0.5" dans la primitive du groupe
()addProfileParameter("foo", 0.5); // equivalent to "foo:0.5" parameter in group primitive
@endcode
*/
@ -4456,6 +4523,37 @@ void setSheet_s_(CStateInstance* entity, CScriptStack& stack)
}
}
//----------------------------------------------------------------------------
/** @page code
@subsection setClientSheet_s_
Change the client sheet of a creature
Arguments: -> s(sheetName)
@code
()setClientSheet('ccdeb2');
@endcode
*/
void setClientSheet_s_(CStateInstance* entity, CScriptStack& stack)
{
string sheetname = stack.top();
stack.pop();
if (sheetname.find(".creature") == string::npos)
sheetname += ".creature";
FOREACH(itBot, CCont<CBot>, entity->getGroup()->bots())
{
CBot* bot = *itBot;
if (bot)
{
bot->setClientSheet(sheetname);
}
}
}
/****************************************************************************/
@ -4581,6 +4679,62 @@ void setConditionSuccess_f_(CStateInstance* entity, CScriptStack& stack)
CAILogicDynamicIfHelper::setConditionSuccess(conditionState);
}
inline
static float randomAngle()
{
uint32 const maxLimit = CAngle::PI*2;
float val = (float)CAIS::rand32(maxLimit);
return val;
}
//----------------------------------------------------------------------------
/** @page code
@subsection facing_f_
The npc will face the given direction
Arguments: f(direction)
@param[in] direction is the new angle of the bot in radians
@code
()facing(3.14);
@endcode
*/
// CStateInstance
void facing_f_(CStateInstance* entity, CScriptStack& stack)
{
float const theta = (float)stack.top(); stack.pop();
CGroup* group = entity->getGroup();
bool bRandomAngle = false;
if (theta > (NLMISC::Pi * 2.0) || theta < (-NLMISC::Pi * 2.0))
bRandomAngle = true;
if (group->isSpawned())
{
FOREACH(itBot, CCont<CBot>, group->bots())
{
CBot* bot = *itBot;
if (bot)
{
if (bot->isSpawned())
{
CSpawnBot *spawnBot = bot->getSpawnObj();
if (bRandomAngle)
spawnBot->setTheta(randomAngle());
else
spawnBot->setTheta(theta);
}
}
}
}
}
std::map<std::string, FScrptNativeFunc> nfGetGroupNativeFunctions()
{
@ -4628,6 +4782,7 @@ std::map<std::string, FScrptNativeFunc> nfGetGroupNativeFunctions()
REGISTER_NATIVE_FUNC(functions, clearAggroList__);
REGISTER_NATIVE_FUNC(functions, setMode_s_);
REGISTER_NATIVE_FUNC(functions, setAutoSpawn_f_);
REGISTER_NATIVE_FUNC(functions, setMaxHP_ff_);
REGISTER_NATIVE_FUNC(functions, setHPLevel_f_);
REGISTER_NATIVE_FUNC(functions, setHPScale_f_);
REGISTER_NATIVE_FUNC(functions, scaleHP_f_);
@ -4651,10 +4806,11 @@ std::map<std::string, FScrptNativeFunc> nfGetGroupNativeFunctions()
REGISTER_NATIVE_FUNC(functions, getEventParam_f_f);
REGISTER_NATIVE_FUNC(functions, getEventParam_f_s);
REGISTER_NATIVE_FUNC(functions, setSheet_s_);
REGISTER_NATIVE_FUNC(functions, setClientSheet_s_);
REGISTER_NATIVE_FUNC(functions, setHealer_f_);
REGISTER_NATIVE_FUNC(functions, setConditionSuccess_f_);
REGISTER_NATIVE_FUNC(functions, facing_f_);
REGISTER_NATIVE_FUNC(functions, setUrl_ss_);
// Boss functions (custom text)
REGISTER_NATIVE_FUNC(functions, phraseBegin__);
@ -4700,9 +4856,6 @@ std::map<std::string, FScrptNativeFunc> nfGetGroupNativeFunctions()
REGISTER_NATIVE_FUNC(functions, summonPlayer_fs_);
#undef REGISTER_NATIVE_FUNC
return functions;

View file

@ -462,7 +462,7 @@ Arguments: f(Radius) ->
@param[in] Radius dispersion of wander activity
@code
()startWander(100); // Gives a wander activity to the group with dispersion of 100
()startMoving(100,-100,10); // Moves the group to 100,-100 with radius of 10
@endcode
*/
@ -501,6 +501,56 @@ void startMoving_fff_(CStateInstance* entity, CScriptStack& stack)
return;
}
//----------------------------------------------------------------------------
/** @page code
@subsection followPlayer_sf_
Set activity to follow the given player
Arguments: s(PlayerEid) f(Radius) ->
@param[in] PlayerEid id of player to follow
@param[in] Radius dispersion of wander activity
@code
()followPlayer("(0x0002015bb4:01:88:88)",10);
@endcode
*/
// Spawned CGroupNpc not in a family behaviour
void followPlayer_sf_(CStateInstance* entity, CScriptStack& stack)
{
uint32 dispersionRadius = (uint32)(float&)stack.top(); stack.pop();
NLMISC::CEntityId playerId = NLMISC::CEntityId((std::string)stack.top());
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
if (!aiInstance)
return;
if (!entity) { nlwarning("followPlayer failed!"); return; }
CGroupNpc* group = dynamic_cast<CGroupNpc*>(entity->getGroup());
if (!group)
{ nlwarning("followPlayer failed: no NPC group");
return;
}
CSpawnGroupNpc* spawnGroup = group->getSpawnObj();
if (!spawnGroup)
{ nlwarning("followPlayer failed: no spawned group");
return;
}
if (playerId == CEntityId::Unknown)
{
nlwarning("followPlayer failed: unknown player");
DEBUG_STOP;
return;
}
spawnGroup->movingProfile().setAIProfile(new CGrpProfileFollowPlayer(spawnGroup, TheDataset.getDataSetRow(playerId), dispersionRadius));
return;
}
//----------------------------------------------------------------------------
@ -2179,14 +2229,11 @@ void facing_cscs_(CStateInstance* entity, CScriptStack& stack)
// bot1->setTheta(bot1->pos().angleTo(bot2->pos()));
}
//----------------------------------------------------------------------------
/** @page code
@subsection npcSay_css_
A new entry of the npc contextual menu will propose to the targeter player to talk to the npc.
Make a npc say a text
There are 3 type of text
@ -2201,9 +2248,9 @@ Arguments: c(group), s(botname), s(text), ->
@code
(@group)group_name.context();
()emote(@group, "bob", "DSS_1601 RtEntryText_6") ;// Send To dss
()emote(@group, "bob", "RAW Ca farte?"); // phrase direcly send to IOS as raw (for debug)
()emote(@group, "bob", "answer_group_no_m"); //phrase id
()npcSay(@group, "bob", "DSS_1601 RtEntryText_6") ;// Send To dss
()npcSay(@group, "bob", "RAW Ca farte?"); // phrase direcly send to IOS as raw (for debug)
()npcSay(@group, "bob", "answer_group_no_m"); //phrase id
@endcode
@ -2214,6 +2261,34 @@ Arguments: c(group), s(botname), s(text), ->
#include "game_share/chat_group.h"
#include "game_share/send_chat.h"
void execSayHelper(CSpawnBot *spawnBot, NLMISC::CSString text, CChatGroup::TGroupType mode = CChatGroup::say)
{
if (spawnBot)
{
NLMISC::CSString prefix = text.left(4);
if (prefix=="DSS_")
{
NLMISC::CSString phrase = text.right(text.length() - 4);
NLMISC::CSString idStr = phrase.strtok(" ",false,false,false,false);
uint32 scenarioId = atoi(idStr.c_str());
forwardToDss(spawnBot->dataSetRow(), mode, phrase, scenarioId);
return;
}
if (prefix=="RAW ")
{
std::string phrase = text.right(text.length()-4);
ucstring ucstr = phrase;
npcChatToChannelSentence(spawnBot->dataSetRow(), mode, ucstr);
return;
}
//Classic phrase ID
npcChatToChannel(spawnBot->dataSetRow(), mode, text);
}
}
void npcSay_css_(CStateInstance* entity, CScriptStack& stack)
{
string text = (string)stack.top(); stack.pop();
@ -2224,29 +2299,58 @@ void npcSay_css_(CStateInstance* entity, CScriptStack& stack)
if (!spawnBot) { return; }
execSayHelper(spawnBot, text);
}
std::string prefix =NLMISC::CSString (text).left(4);
if(prefix=="DSS_")
//----------------------------------------------------------------------------
/** @page code
@subsection npcSay_ss_
Make a npc say a text
Arguments: s(text), s(mode) ->
@param[in] text is the text to say. prefix with ID: to use an id
@param[in] mode is the mode to use (say, shout)
@code
()npcSay("Hello!","say"); // phrase direcly send to IOS as raw
()npcSay("ID:answer_group_no_m","shout"); // phrase id
@endcode
*/
void npcSay_ss_(CStateInstance* entity, CScriptStack& stack)
{
std::string sMode = (std::string)stack.top(); stack.pop();
std::string text = (std::string)stack.top(); stack.pop();
CChatGroup::TGroupType mode = CChatGroup::say;
mode = CChatGroup::stringToGroupType(sMode);
CGroup* group = entity->getGroup();
if (group->isSpawned())
{
NLMISC::CSString phrase = NLMISC::CSString (text).right((uint)text.length()-4);
NLMISC::CSString idStr = phrase.strtok(" ",false,false,false,false);
uint32 scenarioId;
NLMISC::fromString(idStr, scenarioId);
forwardToDss(spawnBot->dataSetRow(), CChatGroup::say, phrase, scenarioId);
return;
}
if (prefix=="RAW ")
FOREACH(itBot, CCont<CBot>, group->bots())
{
NLMISC::CSString phrase = NLMISC::CSString (text).right((uint)text.length()-4);
npcChatToChannelSentence(spawnBot->dataSetRow(),CChatGroup::say, phrase);
return;
CBot* bot = *itBot;
if (bot)
{
if (bot->isSpawned())
{
CSpawnBot *spawnBot = bot->getSpawnObj();
std::string prefix = NLMISC::CSString(text).left(3);
if (NLMISC::nlstricmp(prefix.c_str(), "id:") == 0) {
text = NLMISC::CSString(text).right(text.length()-3);
execSayHelper(spawnBot, text, mode);
}
else {
execSayHelper(spawnBot, "RAW " + text, mode);
}
}
}
}
}
//Classic phrase ID
npcChatToChannel(spawnBot->dataSetRow(), CChatGroup::say, text);
return;
}
@ -2514,6 +2618,7 @@ void rename_s_(CStateInstance* entity, CScriptStack& stack)
msgout.serial(row);
msgout.serial(name);
sendMessageViaMirror("IOS", msgout);
bot->setCustomName(name);
}
}
}
@ -2650,6 +2755,7 @@ std::map<std::string, FScrptNativeFunc> nfGetNpcGroupNativeFunctions()
REGISTER_NATIVE_FUNC(functions, startMoving_fff_);
REGISTER_NATIVE_FUNC(functions, waitInZone_s_);
REGISTER_NATIVE_FUNC(functions, stopMoving__);
REGISTER_NATIVE_FUNC(functions, followPlayer_sf_);
REGISTER_NATIVE_FUNC(functions, wander__);
REGISTER_NATIVE_FUNC(functions, setAttackable_f_);
REGISTER_NATIVE_FUNC(functions, setPlayerAttackable_f_);
@ -2687,6 +2793,7 @@ std::map<std::string, FScrptNativeFunc> nfGetNpcGroupNativeFunctions()
REGISTER_NATIVE_FUNC(functions, rename_s_);
REGISTER_NATIVE_FUNC(functions, vpx_s_);
REGISTER_NATIVE_FUNC(functions, npcSay_css_);
REGISTER_NATIVE_FUNC(functions, npcSay_ss_);
REGISTER_NATIVE_FUNC(functions, dssMessage_fsss_);
REGISTER_NATIVE_FUNC(functions, despawnBotByAlias_s_);
REGISTER_NATIVE_FUNC(functions, giveReward_ssssc_);

View file

@ -1000,8 +1000,8 @@ void setSimplePhrase_ss_(CStateInstance* entity, CScriptStack& stack)
phraseContent2 += "]}";
ucstring ucPhraseContent;
// ucPhraseContent.fromUtf8(phraseContent2); // utf-8 version
ucPhraseContent = phraseContent2; // iso-8859-1 version
ucPhraseContent.fromUtf8(phraseContent2); // utf-8 version
//ucPhraseContent = phraseContent2; // iso-8859-1 version
NLNET::CMessage msgout("SET_PHRASE");
msgout.serial(phraseName);
@ -1009,6 +1009,33 @@ void setSimplePhrase_ss_(CStateInstance* entity, CScriptStack& stack)
sendMessageViaMirror("IOS", msgout);
}
void setSimplePhrase_sss_(CStateInstance* entity, CScriptStack& stack)
{
std::string lang = (std::string)stack.top();
stack.pop();
std::string phraseContent = (std::string)stack.top();
stack.pop();
std::string phraseName = (std::string)stack.top();
stack.pop();
std::string phraseContent2;
phraseContent2 += phraseName;
phraseContent2 += "(){[";
phraseContent2 += phraseContent;
phraseContent2 += "]}";
ucstring ucPhraseContent;
ucPhraseContent.fromUtf8(phraseContent2); // utf-8 version
//ucPhraseContent = phraseContent2; // iso-8859-1 version
NLNET::CMessage msgout("SET_PHRASE_LANG");
msgout.serial(phraseName);
msgout.serial(ucPhraseContent);
msgout.serial(lang);
sendMessageViaMirror("IOS", msgout);
}
//----------------------------------------------------------------------------
/** @page code
@ -1330,6 +1357,7 @@ std::map<std::string, FScrptNativeFunc> nfGetStaticNativeFunctions()
REGISTER_NATIVE_FUNC(functions, getNamedEntityProp_ss_s);
REGISTER_NATIVE_FUNC(functions, destroyNamedEntity_s_);
REGISTER_NATIVE_FUNC(functions, setSimplePhrase_ss_);
REGISTER_NATIVE_FUNC(functions, setSimplePhrase_sss_);
REGISTER_NATIVE_FUNC(functions, dataGetVar_s_s);
REGISTER_NATIVE_FUNC(functions, dataGetVar_s_f);
REGISTER_NATIVE_FUNC(functions, dataSetVar_ss_);

View file

@ -788,6 +788,13 @@ bool CNpcChatProfileImp::parseChatArgs(CAIInstance *aiInstance, const std::strin
return true;
}
// organization entry
if (NLMISC::nlstricmp(keyword, "organization") == 0)
{
NLMISC::fromString(tail, _Organization);
return true;
}
// if no match found throw an error
return false;
}
@ -830,4 +837,5 @@ void TGenNpcDescMsgImp::setChat(const CNpcChatProfileImp& chatProfile)
_OptionalProperties = chatProfile.getOptionalProperties();
_Outpost = chatProfile.getOutpost();
_Organization = chatProfile.getOrganization();
}

View file

@ -36,7 +36,7 @@ public:
CNpcChatProfileImp(const CNpcChatProfileImp &other0,const CNpcChatProfileImp &other1);
// interface for setting up chat info
void clear() { clearShopInfo(); clearMissions(); clearCellZones(); clearContextOption(); _OptionalProperties.clear(); }
void clear() { clearShopInfo(); clearMissions(); clearCellZones(); clearContextOption(); clearWeb(); _OptionalProperties.clear(); }
void clearShopInfo()
{
_ShopTypes.clear();
@ -56,6 +56,11 @@ public:
}
void clearCellZones() { _CellZones.clear(); }
void clearMissions() { _Missions.clear(); }
void clearWeb()
{
_WebPage.clear();
_WebPageName.clear();
}
bool add(CAIInstance *aiInstance, const std::string &chatArgs) { return parseChatArgs(aiInstance, chatArgs); }
void addMission(uint32 mission) { _Missions.push_back(mission); }
void clearContextOption() { _ContextOptions.clear(); }

View file

@ -1083,25 +1083,33 @@ CSmartPtr<const AIVM::CByteCode> CCompiler::compileCode (const std::vector<std::
FOREACHC(itArg, TList, sourceCodeLines)
{
const string &str=*itArg;
size_t firstIndex=str.find_first_of("/",0);
while (firstIndex!=string::npos)
size_t index = str.find("//",0);
if (index == string::npos)
code += str;
else {
// We have a potential comment. Now check if it is quoted or not
bool inQuote = false;
uint i = 0;
for (;;)
{
firstIndex++;
if (firstIndex>=str.size())
if ('"' == str[i])
inQuote = !inQuote;
if ( !inQuote && ('/' == str[i]) )
{
firstIndex=string::npos;
++i;
if ('/' == str[i])
break;
code += '/';
}
code += str[i];
++i;
if (str.size() == i)
break;
}
}
if (str.at(firstIndex)=='/')
{
code+=str.substr(0, firstIndex-1);
break;
}
firstIndex=str.find_first_of("/",firstIndex);
}
if (firstIndex==string::npos)
code+=str;
code+="\n "; // additional ..
}
code+="}";

View file

@ -221,10 +221,12 @@ arguments.
- @ref moveToZone_ss_
- @ref waitInZone_s_
- @ref stopMoving__
- @ref followPlayer_sf_
- @ref wander__
- @ref downScaleHP_f_
- @ref upScaleHP_f_
- @ref scaleHP_f_
- @ref setMaxHP_ff_
- @ref setHPLevel_f_
- @ref addHP_f_
- @ref aiAction_s_

View file

@ -69,7 +69,7 @@ void CVisualPropertiesInterface::release()
}
// set different visual properties for a bot.
void CVisualPropertiesInterface::setName(const TDataSetRow& dataSetRow,std::string name)
void CVisualPropertiesInterface::setName(const TDataSetRow& dataSetRow, ucstring name)
{
if (!IOSHasMirrorReady)
return;
@ -77,8 +77,6 @@ void CVisualPropertiesInterface::setName(const TDataSetRow& dataSetRow,std::stri
NLNET::CMessage msgout("CHARACTER_NAME");
CEntityId eid=CMirrors::DataSet->getEntityId(dataSetRow);
msgout.serial (const_cast<TDataSetRow&>(dataSetRow));
ucstring uname;
uname.fromUtf8(name);
msgout.serial (uname); // Daniel: TODO update all name dependencies to ucstring in your service.
msgout.serial (name);
sendMessageViaMirror("IOS",msgout);
}

View file

@ -39,7 +39,7 @@ public:
static void release();
// set different visual properties for an entity
static void setName(const TDataSetRow& dataSetRow,std::string name);
static void setName(const TDataSetRow& dataSetRow, ucstring name);
// static void setMode(CAIEntityId id,MBEHAV::EMode mode);
// static void setBehaviour(CAIEntityId id,MBEHAV::EBehaviour behaviour);

File diff suppressed because it is too large Load diff

View file

@ -43,6 +43,8 @@ struct CAdminCommand
void initAdmin ();
void initCommandsPrivileges(const std::string & fileName);
void initPositionFlags(const std::string & fileName);
void initSalt();
const std::string &getSalt();
CAdminCommand * findAdminCommand(const std::string & name);

View file

@ -268,6 +268,7 @@ bool CBuildingManager::parsePhysicalBuildings( const NLLIGO::IPrimitive* prim, C
else
{
_BuildingPhysicals.insert( make_pair( alias, building ) );
_BuildingPhysicalsName.insert( make_pair( building->getName(), building));
return true;
}
}
@ -853,18 +854,18 @@ IBuildingPhysical * CBuildingManager::getBuildingPhysicalsByAlias( TAIAlias alia
//----------------------------------------------------------------------------
IBuildingPhysical* CBuildingManager::getBuildingPhysicalsByName( const std::string & name )
{
for ( std::map<TAIAlias,IBuildingPhysical*>::iterator it = _BuildingPhysicals.begin(); it != _BuildingPhysicals.end(); ++it )
std::map<std::string,IBuildingPhysical*>::iterator it = _BuildingPhysicalsName.find( name );
if ( it != _BuildingPhysicalsName.end() )
{
if( (*it).second == NULL )
{
nlwarning("<BUILDING> NULL building in building maps. Checks should be done at init time");
return NULL;
}
if ( (*it).second->getName() == name )
return (*it).second;
}
return NULL;
return NULL;
}
//----------------------------------------------------------------------------
@ -1134,3 +1135,9 @@ void CBuildingManager::buyBuildingOption(const NLMISC::CEntityId & userId, uint8
}
}
//----------------------------------------------------------------------------
void CBuildingManager::buyBuilding(const NLMISC::CEntityId & userId, TAIAlias alias)
{
CCharacter * user = PlayerManager.getChar(userId);
user->getRoomInterface().init( user, dynamic_cast<CBuildingPhysicalPlayer*>(getBuildingPhysicalsByAlias(alias)) );
}

View file

@ -86,7 +86,7 @@ public:
void registerPlayer( CCharacter * user );
/// get a building destination from its alias.
IBuildingPhysical* getBuildingPhysicalsByAlias( TAIAlias Alias );
/// get a building destination from its name. WARNING : slow
/// get a building destination from its name.
IBuildingPhysical* getBuildingPhysicalsByName( const std::string & name );
/// remove a player from a room
void removePlayerFromRoom( CCharacter * user );
@ -122,6 +122,7 @@ public:
void buildBuildingTradeList(const NLMISC::CEntityId & userId, uint16 session);
/// buy a player flat option
void buyBuildingOption(const NLMISC::CEntityId & userId, uint8 idx);
void buyBuilding(const NLMISC::CEntityId & userId, TAIAlias alias);
//@}
private:
@ -201,9 +202,12 @@ private:
typedef CHashMap< TDataSetRow , CTriggerRequest , TDataSetRow::CHashCode > TTriggerRequestCont;
TTriggerRequestCont _TriggerRequests;
/// physical buildings by name
/// physical buildings by Alias
std::map<TAIAlias,IBuildingPhysical*> _BuildingPhysicals;
/// physical buildings by name
std::map<std::string,IBuildingPhysical*> _BuildingPhysicalsName;
/// room instances
struct CRoomInstanceEntry
{

View file

@ -109,7 +109,6 @@ void CBuildingPhysicalGuild::addGuild( uint32 guildId )
{
if ( std::find(_Guilds.begin(), _Guilds.end(), guildId) != _Guilds.end() )
{
nlwarning("<BUILDING> trying to add a guild that is already present in the building, guild id = %u", guildId);
return;
}

View file

@ -815,6 +815,34 @@ void cbClientCombatDodge( NLNET::CMessage& msgin, const std::string &serviceName
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// CLIENT:LEAGUE
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
//
void cbClientLeagueJoin( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId)
{
cbJoinLeague(msgin, serviceName, serviceId);
}
//
void cbClientLeagueJoinProposal( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId)
{
cbJoinLeagueProposal(msgin, serviceName, serviceId);
}
//
void cbClientLeagueJoinProposalDecline( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId)
{
cbJoinLeagueDecline(msgin, serviceName, serviceId);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// CLIENT:TEAM
@ -857,7 +885,8 @@ void cbClientTeamSetSuccessor( NLNET::CMessage& msgin, const std::string &servic
CEntityId id;
uint8 idx;
msgin.serial( id,idx );
msgin.serial(id);
msgin.serial(idx);
CCharacter* user = PlayerManager.getChar( id );
if ( !user )
{
@ -872,9 +901,17 @@ void cbClientTeamSetSuccessor( NLNET::CMessage& msgin, const std::string &servic
}
if ( team->getLeader() != id )
{
nlwarning("<TEAM> user %s is not leader : cant set successor",id.toString().c_str() );
nlwarning("<TEAM> user %s is not leader: cant set successor",id.toString().c_str() );
return;
}
if (team->getSuccessor() == id)
{
nlwarning("<TEAM> user %s already is successor", id.toString().c_str() );
return;
}
// increment the target index as the leader is not in its team list
++idx;
team->setSuccessor( idx );
}
@ -2370,7 +2407,6 @@ void cbClientWhere( NLNET::CMessage& msgin, const std::string &serviceName, NLNE
}\
}
// Send list of connected character name / account to client
void cbClientWho( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId )
{
@ -2381,6 +2417,11 @@ void cbClientWho( NLNET::CMessage& msgin, const std::string &serviceName, NLNET:
msgin.serial( id,opt );
const std::vector<CEntityId> * gms = NULL;
// Make sure opt is not like "A(c)" for "é"
ucstring ucopt;
ucopt.fromUtf8(opt);
opt = ucopt.toString();
uint nbAnswers = 0;
// standard who
@ -2420,7 +2461,7 @@ void cbClientWho( NLNET::CMessage& msgin, const std::string &serviceName, NLNET:
&& user->getInstanceNumber() == ch->getInstanceNumber())
{
params[0].setEId( (*it) );
CCharacter::sendDynamicSystemMessage( id,"WHO_REGION_LIST",params );
CCharacter::sendDynamicSystemMessage( id,"WHO_REGION_LIST", params );
nbAnswers++;
}
}
@ -2429,7 +2470,7 @@ void cbClientWho( NLNET::CMessage& msgin, const std::string &serviceName, NLNET:
}
// GM who
else if ( NLMISC::nlstricmp( opt.c_str() , "GM" ) == 0)
else if ( NLMISC::nlstricmp( opt.c_str(), "GM" ) == 0)
{
TVectorParamCheck params(1);
params[0].Type = STRING_MANAGER::player;
@ -2476,6 +2517,75 @@ void cbClientWho( NLNET::CMessage& msgin, const std::string &serviceName, NLNET:
}
}
}
else
{
TChanID chanID;
CCharacter * user = PlayerManager.getChar( id );
if ( !user )
{
nlwarning("<WHO>'%s' is invalid", id.toString().c_str() );
return;
}
CPlayer *p = PlayerManager.getPlayer(PlayerManager.getPlayerId(user->getId()));
if (NLMISC::nlstricmp( opt.c_str(), "league" ) == 0)
{
chanID = user->getLeagueId();
}
else
{
chanID = DynChatEGS.getChanIDFromName(opt);
}
if (chanID == DYN_CHAT_INVALID_CHAN)
{
CCharacter::sendDynamicSystemMessage( id, "WHO_CHANNEL_NOT_FOUND" );
return;
}
bool havePriv = p->havePriv(":DEV:SGM:GM:");
bool hasChannel = false;
nbAnswers = 0;
vector<NLMISC::CEntityId> players;
DynChatEGS.getPlayersInChan(chanID, players);
ucstring playerNames("");
uint32 shardId = CEntityIdTranslator::getInstance()->getEntityShardId(id);
for (uint i = 0; i < players.size(); i++)
{
if (players[i] == id)
hasChannel = true;
ucstring name = CEntityIdTranslator::getInstance()->getByEntity(players[i]);
if (shardId == CEntityIdTranslator::getInstance()->getEntityShardId(players[i]))
{
// Same shard, remove shard from name
CEntityIdTranslator::removeShardFromName(name);
}
playerNames += ((i > 0) ? "\n" : "") + name ;
}
if (!hasChannel && !havePriv)
{
SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
params[0].Literal = opt;
CCharacter::sendDynamicSystemMessage( id, "WHO_CHANNEL_NOT_CONNECTED", params );
return;
}
if (!playerNames.empty())
{
CCharacter::sendDynamicSystemMessage( id, "WHO_CHANNEL_INTRO" );
//playerNames = "Players in channel \"" + opt + "\":" + playerNames;
SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
params[0].Literal = playerNames;
CCharacter::sendDynamicSystemMessage( id, "LITERAL", params );
return;
}
}
if ( nbAnswers == 0 )
{
@ -3508,9 +3618,9 @@ TUnifiedCallbackItem CbClientArray[]=
{ "CLIENT:DUEL:REFUSE", cbClientDuelRefuse },
{ "CLIENT:DUEL:ABANDON", cbClientDuelAbandon },
{ "CLIENT:PVP_CHALLENGE:ASK", cbClientPVPChallengeAsked },
{ "CLIENT:PVP_CHALLENGE:ACCEPT", cbClientPVPChallengeAccept },
{ "CLIENT:PVP_CHALLENGE:REFUSE", cbClientPVPChallengeRefuse },
{ "CLIENT:PVP_CHALLENGE:ASK", cbClientLeagueJoinProposal },
{ "CLIENT:PVP_CHALLENGE:ACCEPT", cbClientLeagueJoin },
{ "CLIENT:PVP_CHALLENGE:REFUSE", cbClientLeagueJoinProposalDecline },
{ "CLIENT:PVP_CHALLENGE:ABANDON", cbClientPVPChallengeAbandon },
// { "CLIENT:PVP_VERSUS:CLAN", cbClientPvpChooseClan },

View file

@ -145,6 +145,7 @@ CCreature::CCreature() : CEntityBase(true)
_TicketFameRestrictionValue = 0;
_MaxHitRangeForPC = -1.f;
_Organization = 0;
// _MissionIconFlags.IsMissionStepIconDisplayable = true;
// _MissionIconFlags.IsMissionGiverIconDisplayable = true;
}
@ -941,6 +942,8 @@ void CCreature::setBotDescription( const CGenNpcDescMsgImp& description )
_BotChatOutpost = description.getOutpost();
_Organization = description.getOrganization();
bool cosmeticCategory = false;
bool tradeCategory = false;
bool tpCategory = false;

View file

@ -496,6 +496,8 @@ public:
const std::string &getWebPage() const {return _WebPage;}
const std::string &getWebPageName() const {return _WebPageName;}
const uint32 getOrganization() const { return _Organization; }
const NLMISC::CSheetId &getBotChatOutpost() const {return _BotChatOutpost;}
const std::vector<NLMISC::CSheetId> &getExplicitActionTradeList() const {return _ExplicitActionTradeList;}
@ -590,6 +592,7 @@ private:
NLMISC::CSmartPtr<CMerchant> _Merchant; // smart pointer on CMerchant class of creature
uint32 _BotChatProgram; // Program enabled for bot chat
uint32 _Organization; // Organization for bot
TDataSetRow _CharacterLeaderIndex; // The data set row of the beast's leader character if it's in a pack/train
std::string _WelcomePhrase; // welcome message id of the bot

View file

@ -195,6 +195,28 @@ void CCreatureCompleteHealImp::callback(const string &, NLNET::TServiceId sid)
}
}
//--------------------------------------------------------------
// CChangeCreatureMaxHPImp ::callback()
//--------------------------------------------------------------
void CChangeCreatureMaxHPImp::callback(const string &, NLNET::TServiceId sid)
{
H_AUTO(CChangeCreatureMaxHPImp);
// for each creature, restore full HP
for ( uint i = 0; i < Entities.size(); ++i )
{
CCreature * c = CreatureManager.getCreature( Entities[i] );
if ( c )
{
c->getScores()._PhysicalScores[SCORES::hit_points].Max = MaxHp[i];
if (SetFull[i] != 0)
c->changeCurrentHp( c->maxHp() - c->currentHp() );
}
}
}
//--------------------------------------------------------------
// CChangeCreatureHPImp ::callback()
//--------------------------------------------------------------
@ -229,6 +251,50 @@ void CChangeCreatureHPImp::callback(const string &, NLNET::TServiceId sid)
}
}
//--------------------------------------------------------------
// CChangeCreatureMaxHPImp ::callback()
//--------------------------------------------------------------
void CCreatureSetUrlImp::callback(const string &, NLNET::TServiceId sid)
{
H_AUTO(CCreatureSetUrlImp);
// for each creature set url
for ( uint i = 0; i < Entities.size(); ++i )
{
CCreature * c = CreatureManager.getCreature( Entities[i] );
if ( c )
{
uint32 program = c->getBotChatProgram();
if(!(program & (1<<BOTCHATTYPE::WebPageFlag)))
{
if(program != 0)
{
return;
}
program |= 1 << BOTCHATTYPE::WebPageFlag;
c->setBotChatProgram(program);
}
const string &wp = c->getWebPage();
if(Url == "*") {
(string &)wp = "";
program &= ~(1 << BOTCHATTYPE::WebPageFlag);
c->setBotChatProgram(program);
return;
}
else
(string &)wp = Url;
const string &wpn = c->getWebPageName();
(string &)wpn = ActionName;
return;
}
}
}
//---------------------------------------------------
// Constructor
//

View file

@ -71,6 +71,15 @@ public:
virtual void callback (const std::string &name, NLNET::TServiceId id);
};
/**
* Implementation of the set Max HP message for creatures
*/
class CChangeCreatureMaxHPImp : public CChangeCreatureMaxHPMsg
{
public:
virtual void callback (const std::string &name, NLNET::TServiceId id);
};
/**
* Implementation of the change HP message for creatures
*/
@ -81,6 +90,16 @@ public:
};
/**
* Implementation of the change setUrl message for creatures
*/
class CCreatureSetUrlImp : public CCreatureSetUrlMsg
{
public:
virtual void callback (const std::string &name, NLNET::TServiceId id);
};
typedef CHashMap< NLMISC::CEntityId, CCreature *, NLMISC::CEntityIdHashMapTraits> TMapCreatures;
/**

View file

@ -3140,6 +3140,9 @@ void CBankAccessor_PLR::TPACK_ANIMAL::TBEAST::init(ICDBStructNode *parent, uint
nlassert(node != NULL);
_DESPAWN = node;
node = parent->getNode( ICDBStructNode::CTextId("NAME"), true );
nlassert(node != NULL);
_NAME = node;
// branch init

View file

@ -8855,7 +8855,7 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C
ICDBStructNode *_POS;
ICDBStructNode *_HUNGER;
ICDBStructNode *_DESPAWN;
ICDBStructNode *_NAME;
public:
void init(ICDBStructNode *parent, uint index);
@ -9045,6 +9045,23 @@ inline void _getProp(const CCDBSynchronised &db, ICDBStructNode *node, NLMISC::C
return _DESPAWN;
}
void setNAME(CCDBSynchronised &dbGroup, uint32 value, bool forceSending = false)
{
_setProp(dbGroup, _NAME, value, forceSending);
}
uint32 getNAME(const CCDBSynchronised &dbGroup)
{
uint32 value;
_getProp(dbGroup, _NAME, value);
return value;
}
ICDBStructNode *getNAMECDBNode()
{
return _NAME;
}
};

View file

@ -248,6 +248,23 @@ bool CDynChatEGS::removeSession(TChanID chan,const TDataSetRow &client)
return true;
}
//============================================================================================================
bool CDynChatEGS::getPlayersInChan(TChanID chanID, std::vector<NLMISC::CEntityId> &players)
{
CDynChatChan *chan = _DynChat.getChan(chanID);
if (!chan) return false;
CDynChatSession *currSession = chan->getFirstSession();
bool havePlayers = false;
while (currSession)
{
players.push_back(TheDataset.getEntityId(currSession->getClient()->getID()));
havePlayers = true;
currSession = currSession->getNextChannelSession();
}
return havePlayers;
}
//============================================================================================================
void CDynChatEGS::iosSetHistoricSize(TChanID chan, uint32 size)

View file

@ -76,6 +76,9 @@ public:
bool setWriteRight(TChanID chan, const TDataSetRow &client, bool writeRight);
// Set size of historic for a given channel
void setHistoricSize(TChanID chan, uint32 size);
// Get list of players in channel
bool getPlayersInChan(TChanID chanID, std::vector<NLMISC::CEntityId> &players);
// Resend all channel / sessions to the IOS
void iosConnection();
// Get all channel names (for read only)
@ -83,6 +86,7 @@ public:
const TChanIDToName &getChanIDToNameMap() const { return _ChanNames.getAToBMap(); }
// Get pointer on all channels
void getChans(std::vector<CDynChatChan *> &channels) { _DynChat.getChans(channels); }
const TChanID getNextChanID() const { return _NextChanID; }
/// Message from a service that need to create a new dynamic channel
static void cbServiceAddChan(NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId);

View file

@ -1382,7 +1382,9 @@ void CPlayerService::init()
TRANSPORT_CLASS_REGISTER (CReportAIInstanceDespawnMsgImp);
TRANSPORT_CLASS_REGISTER (CWarnBadInstanceMsg);
TRANSPORT_CLASS_REGISTER (CCreatureCompleteHealImp);
TRANSPORT_CLASS_REGISTER (CChangeCreatureMaxHPImp);
TRANSPORT_CLASS_REGISTER (CChangeCreatureHPImp);
TRANSPORT_CLASS_REGISTER (CCreatureSetUrlImp);
TRANSPORT_CLASS_REGISTER (CChangeCreatureModeMsg);
TRANSPORT_CLASS_REGISTER (CGiveItemRequestMsgImp);
TRANSPORT_CLASS_REGISTER (CReceiveItemRequestMsgImp);

View file

@ -446,6 +446,8 @@ void cbClientReady( CMessage& msgin, const std::string &serviceName, NLNET::TSer
c->initAnimalHungerDb();
c->initFactionPointDb();
c->initPvpPointDb();
c->initOrganizationInfos();
c->updateOutpostAdminFlagInDB();
@ -516,17 +518,6 @@ void cbClientReady( CMessage& msgin, const std::string &serviceName, NLNET::TSer
// ask backup for offline commands file
COfflineCharacterCommand::getInstance()->characterOnline( characterId );
if( CGameEventManager::getInstance().getChannelEventId() != TChanID::Unknown )
{
if( c->haveAnyPrivilege() )
{
DynChatEGS.addSession(CGameEventManager::getInstance().getChannelEventId(), entityIndex, true);
}
else
{
DynChatEGS.addSession(CGameEventManager::getInstance().getChannelEventId(), entityIndex, false);
}
}
c->onConnection();
} // cbClientReady //
@ -680,6 +671,9 @@ void finalizeClientReady( uint32 userId, uint32 index )
CPVPManager2::getInstance()->setPVPModeInMirror( c );
c->updatePVPClanVP();
// Add character to event channel if event is active
CGameEventManager::getInstance().addCharacterToChannelEvent( c );
// for GM player, trigger a 'infos' command to remember their persistent state
if (!PlayerManager.getPlayer(uint32(c->getId().getShortId())>>4)->getUserPriv().empty())
CCommandRegistry::getInstance().execute(toString("infos %s", c->getId().toString().c_str()).c_str(), InfoLog(), true);
@ -1596,6 +1590,53 @@ void cbJoinTeamProposal( NLNET::CMessage& msgin, const std::string &serviceName,
} // cbJoinTeamProposal //
//---------------------------------------------------
// cbJoinLeague: join specified League
//---------------------------------------------------
void cbJoinLeague( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId)
{
H_AUTO(cbJoinLeague);
CEntityId charId;
msgin.serial( charId );
TeamManager.joinLeagueAccept( charId );
} // cbJoinLeague //
//---------------------------------------------------
// cbJoinLeagueDecline: player decline the proposition
//---------------------------------------------------
void cbJoinLeagueDecline( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId)
{
H_AUTO(cbJoinLeagueDecline);
CEntityId charId;
msgin.serial( charId );
TeamManager.joinLeagueDecline( charId );
} // cbJoinLeagueDecline //
//---------------------------------------------------
// cbJoinLeagueProposal: propose a player (current target) to enter the League
//---------------------------------------------------
void cbJoinLeagueProposal( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId)
{
H_AUTO(cbJoinLeagueProposal);
CEntityId charId;
msgin.serial( charId );
CCharacter *character = PlayerManager.getChar( charId );
if (character == NULL || !character->getEnterFlag())
{
nlwarning("<cbJoinLeagueProposal> Invalid player Id %s", charId.toString().c_str() );
return;
}
character->setAfkState(false);
TeamManager.joinLeagueProposal( character, character->getTarget() );
} // cbJoinLeagueProposal //
//---------------------------------------------------
// cbKickTeammate: kick your target from your team
//---------------------------------------------------

View file

@ -82,6 +82,15 @@ void cbJoinTeamProposal( NLNET::CMessage& msgin, const std::string &serviceName,
// kick your target from your team
void cbKickTeammate( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId);
/// callback for JOIN_LEAGUE message
void cbJoinLeague( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId);
/// callback for JOIN_LEAGUE_DECLINE message
void cbJoinLeagueDecline( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId);
/// callback for JOIN_LEAGUE_PROPOSAL message
void cbJoinLeagueProposal( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId);
// toogle god mode on / off for testing
//void cbGodMode( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId);

View file

@ -791,6 +791,7 @@ void CGameItem::ctor( const CSheetId& sheetId, uint32 recommended, bool destroya
// SlotCount = slotCount;
_Recommended = recommended;
_TotalSaleCycle = 0;
_PetIndex = MAX_INVENTORY_ANIMAL;
_Form = CSheets::getForm( sheetId );
if (_Form)
@ -1146,6 +1147,14 @@ uint32 CGameItem::getNonLockedStackSize()
return _StackSize - _LockCount;
}
void CGameItem::setLockedByOwner(bool value)
{
if (value != _LockedByOwner)
{
_LockedByOwner = value;
callItemChanged(INVENTORIES::TItemChangeFlags(INVENTORIES::itc_lock_state));
}
}
//-----------------------------------------------
// getCopy :
@ -1362,6 +1371,8 @@ void CGameItem::clear()
_RequiredCharacLevel = 0;
_HasPrerequisit= false;
_LockedByOwner = false;
_TypeSkillMods.clear();
_PhraseId.clear();
_CustomText.clear();

View file

@ -679,6 +679,9 @@ public :
/// set required skill level
inline void setRequiredSkillLevel2( uint16 l ) { _RequiredSkillLevel2 = l; }
bool getLockedByOwner() const { return _LockedByOwner; }
void setLockedByOwner(bool value);
/// get required stat
inline CHARACTERISTICS::TCharacteristics getRequiredCharac() const { return _RequiredCharac; }
/// set required stat
@ -706,6 +709,13 @@ public :
/// set custom string (for scroll-like items)
void setCustomText(const ucstring &val);
uint8 getPetIndex() const { return _PetIndex; }
void setPetIndex(uint8 val) { _PetIndex = val; }
ucstring getCustomName() const { return _CustomName; }
void setCustomName(ucstring val) { _CustomName = val; }
protected:
friend class CFaberPhrase;
// set Default Color (for craft only)
@ -947,6 +957,9 @@ private:
std::vector<CTypeSkillMod> _TypeSkillMods;
ucstring _CustomText;
bool _LockedByOwner;
uint8 _PetIndex;
ucstring _CustomName;
};
/**

View file

@ -84,6 +84,10 @@ bool CExchangeView::putItemInExchange(uint32 bagSlot, uint32 exchangeSlot, uint3
if (_InterlocutorView != NULL && (!form->DropOrSell && form->Family != ITEMFAMILY::PET_ANIMAL_TICKET))
return false;
// Can't trade items locked by owner
if (item->getLockedByOwner())
return false;
if( getCharacter()->isAnActiveXpCatalyser(item) )
return false;

View file

@ -1066,6 +1066,12 @@ void CCharacterInvView::updateClientSlot(uint32 slot, const CGameItemPtr item)
getCharacter()->queryItemPrice( item, price );
itemBestStat = item->getCraftParameters() == 0 ? RM_FABER_STAT_TYPE::Unknown : item->getCraftParameters()->getBestItemStat();
BOTCHATTYPE::TBotChatResaleFlag resaleFlag = (item->durability() == item->maxDurability() ? BOTCHATTYPE::ResaleOk : BOTCHATTYPE::ResaleKOBroken);
if (item->getLockedByOwner())
{
resaleFlag = BOTCHATTYPE::ResaleKOLockedByOwner;
}
INVENTORIES::CItemSlot itemSlot( slot );
itemSlot.setItemProp( INVENTORIES::Sheet, item->getSheetId().asInt() );
itemSlot.setItemProp( INVENTORIES::Quality, item->quality() );
@ -1076,7 +1082,7 @@ void CCharacterInvView::updateClientSlot(uint32 slot, const CGameItemPtr item)
itemSlot.setItemProp( INVENTORIES::NameId, item->sendNameId(getCharacter()) );
itemSlot.setItemProp( INVENTORIES::Enchant, item->getClientEnchantValue() );
itemSlot.setItemProp( INVENTORIES::Price, price );
itemSlot.setItemProp( INVENTORIES::ResaleFlag, item->durability() == item->maxDurability() ? BOTCHATTYPE::ResaleOk : BOTCHATTYPE::ResaleKOBroken );
itemSlot.setItemProp( INVENTORIES::ResaleFlag, resaleFlag );
itemSlot.setItemProp( INVENTORIES::ItemClass, item->getItemClass() );
itemSlot.setItemProp( INVENTORIES::ItemBestStat, itemBestStat );
itemSlot.setItemProp( INVENTORIES::PrerequisitValid, getCharacter()->checkPreRequired( item ) );

View file

@ -217,7 +217,7 @@ void CGuild::setBuilding(TAIAlias buildingAlias)
if (getBuilding() != CAIAliasTranslator::Invalid)
{
CBuildingManager::getInstance()->removeGuildBuilding( getId() );
_Inventory->clearInventory();
//_Inventory->clearInventory();
}
// set the new guild building
@ -1298,23 +1298,34 @@ uint16 CGuild::getMaxGradeCount(EGSPD::CGuildGrade::TGuildGrade grade)const
for ( uint i = 0; i < size; ++i )
count+=_GradeCounts[i];
if ( grade == EGSPD::CGuildGrade::Leader )
return 1;
if ( grade == EGSPD::CGuildGrade::HighOfficer )
switch (grade)
{
case EGSPD::CGuildGrade::Leader:
return 1;
break;
case EGSPD::CGuildGrade::HighOfficer:
{
return GuildMaxMemberCount;
/*
count *= 5;
if ( count %100 == 0 )
return count/100;
else
return count/100 + 1;
*/
}
if ( grade == EGSPD::CGuildGrade::Officer )
break;
case EGSPD::CGuildGrade::Officer:
{
return GuildMaxMemberCount;
/*
count *= 10;
if ( count %100 == 0 )
return count/100;
else
return count/100 + 1;
*/
}
}
return 0xFFFF;
}
@ -2238,7 +2249,7 @@ void IGuild::updateMembersStringIds()
//-----------------------------------------------------------------------------
/**
* This class is used to load old guild inventory, DO NOT BREAK IT!
* \author Sébastien 'kxu' Guignot
* \author Sebastien 'kxu' Guignot
* \author Nevrax France
* \date 2005
*/

View file

@ -100,7 +100,7 @@ void CGuildLeaderModule::quitGuild()
CGuildMember * member = EGS_PD_CAST<CGuildMember*>( (*it).second );
EGS_PD_AST( member );
// ignore current leader
if ( member->getGrade() == EGSPD::CGuildGrade::Leader )
if ( _GuildMemberCore->getId() == member->getId() )
continue;
// check if the current member is the successor

View file

@ -230,7 +230,6 @@ void cbClientGroupAbandonMission( NLNET::CMessage& msgin, const std::string &ser
if (index < MaxGroupMissionCount)
{
// Team
CTeam * team = TeamManager.getRealTeam( user->getTeamId() );
if ( !team )
{
@ -250,7 +249,6 @@ void cbClientGroupAbandonMission( NLNET::CMessage& msgin, const std::string &ser
return;
}
CMissionTeam* mission = team->getMissions()[index];
nlassert(mission);
@ -301,7 +299,6 @@ void cbClientGroupAbandonMission( NLNET::CMessage& msgin, const std::string &ser
return;
}
CMissionGuild* mission = guild->getMissions()[index];
nlassert(mission);

View file

@ -1961,7 +1961,6 @@ class CMissionActionRecvMoney : public IMissionAction
PHRASE_UTILITIES::sendDynamicSystemMessage(user->getEntityRowId(),"MIS_GUILD_RECV_MONEY",params);
}
}
}
};
uint _Amount;

View file

@ -48,6 +48,7 @@ class CMissionStepKillFauna : public IMissionStepTemplate
{
struct CSubStep
{
string Dynamic;
CSheetId Sheet;
uint16 Quantity;
};
@ -56,7 +57,7 @@ class CMissionStepKillFauna : public IMissionStepTemplate
_SourceLine = line;
_Place = 0xFFFF;
bool ret = true;
if ( script.size() < 2 || script.size() > 3)
if (script.size() < 2 || script.size() > 3)
{
MISLOGSYNTAXERROR("<creature> <quantity> *[; <creature> <quantity>] [: <place>]");
return false;
@ -68,15 +69,28 @@ class CMissionStepKillFauna : public IMissionStepTemplate
_SubSteps.reserve( subs.size() );
for ( uint i = 0; i < subs.size(); i++ )
{
CSubStep subStep;
std::vector< std::string > args;
CMissionParser::tokenizeString( subs[i]," \t", args );
//// Dynamic Mission Args : #dynamic# <quantity>
if ((args.size() == 2) && (args[0] == "#dynamic#"))
{
subStep.Dynamic = missionData.Name;
subStep.Quantity = atoi(args[1].c_str());
}
////
else
{
if ( args.size() != 2 )
{
MISLOGSYNTAXERROR("<creature> <quantity> *[; <creature> <quantity>] [: <place>]");
return false;
}
missionData.ChatParams.push_back( make_pair(args[0],STRING_MANAGER::creature_model) );
CSubStep subStep;
subStep.Dynamic = "";
subStep.Sheet = CSheetId( args[0] + ".creature");
if ( subStep.Sheet == CSheetId::Unknown )
{
@ -84,6 +98,7 @@ class CMissionStepKillFauna : public IMissionStepTemplate
MISLOGERROR1("invalid sheet '%s'", args[0].c_str());
}
NLMISC::fromString(args[1], subStep.Quantity);
}
_SubSteps.push_back(subStep);
}
if ( script.size() == 3 )
@ -104,15 +119,54 @@ class CMissionStepKillFauna : public IMissionStepTemplate
}
uint processEvent( const TDataSetRow & userRow, const CMissionEvent & event,uint subStepIndex,const TDataSetRow & giverRow )
{
nlinfo("Process Event");
string webAppUrl;
bool ret = true;
_User = PlayerManager.getChar(getEntityIdFromRow(userRow));
if ( event.Type == CMissionEvent::Kill )
{
CMissionEventKill & eventSpe = (CMissionEventKill&)event;
CCreature * c = CreatureManager.getCreature( event.TargetEntity );
CSheetId faunaSheet;
//// Dynamic Mission Args
if (_SubSteps[subStepIndex].Dynamic.empty()) {
faunaSheet = _SubSteps[subStepIndex].Sheet;
}
else
{
vector<string> params = _User->getCustomMissionParams(_SubSteps[subStepIndex].Dynamic);
if (params.size() < 2)
{
LOGMISSIONSTEPERROR("kill_fauna : invalid dynamic creature");
return 0;
}
else
{
webAppUrl = params[0];
faunaSheet = CSheetId(params[1]);
if (params.size() > 2) {
string placeStr = CMissionParser::getNoBlankString( params[2] );
CPlace * place = CZoneManager::getInstance().getPlaceFromName( placeStr );
if ( !place )
{
ret = false;
LOGMISSIONSTEPERROR("kill_fauna : invalid place "+params[2]);
}
else
_Place = place->getId();
}
}
////
}
if ( !c )
{
LOGMISSIONSTEPERROR("kill_fauna : invalid creature " + toString(event.TargetEntity.getIndex()));
}
else if ( _SubSteps[subStepIndex].Sheet == c->getType() )
else if ( faunaSheet == c->getType() )
{
if ( _Place != 0xFFFF )
{
@ -126,6 +180,8 @@ class CMissionStepKillFauna : public IMissionStepTemplate
if ( region && region->getId() == _Place )
{
if (!webAppUrl.empty())
_User->validateDynamicMissionStep(webAppUrl);
LOGMISSIONSTEPSUCCESS("kill_fauna");
return 1;
}
@ -134,6 +190,8 @@ class CMissionStepKillFauna : public IMissionStepTemplate
{
if ( places[i] && places[i]->getId() == _Place )
{
if (!webAppUrl.empty())
_User->validateDynamicMissionStep(webAppUrl);
LOGMISSIONSTEPSUCCESS("kill_fauna");
return 1;
}
@ -142,11 +200,14 @@ class CMissionStepKillFauna : public IMissionStepTemplate
}
else
{
if (!webAppUrl.empty())
_User->validateDynamicMissionStep(webAppUrl);
LOGMISSIONSTEPSUCCESS("kill_fauna");
return 1;
}
}
}
return 0;
}
@ -162,23 +223,61 @@ class CMissionStepKillFauna : public IMissionStepTemplate
virtual void getTextParams( uint & nbSubSteps,const std::string* & textPtr,TVectorParamCheck& retParams, const std::vector<uint32>& subStepStates)
{
static const std::string stepTextReact = "MIS_NEED_REACTIVATION";
static const std::string stepText = "MIS_KILL_FAUNA_";
static const std::string stepTextLoc = "MIS_KILL_FAUNA_LOC_";
nlassert( _SubSteps.size() == subStepStates.size() );
CSheetId faunaSheet;
for ( uint i = 0; i < subStepStates.size(); i++ )
{
if( subStepStates[i] != 0 )
{
if (_SubSteps[i].Dynamic.empty())
{
faunaSheet = _SubSteps[i].Sheet;
}
else
{
//// Dynamic Mission Args
vector<string> params = _User->getCustomMissionParams(_SubSteps[i].Dynamic);
if (params.size() < 2)
{
faunaSheet = CSheetId::Unknown;
}
else
{
faunaSheet = CSheetId(params[1]);
}
if ((_Place == 0xFFFF) && (params.size() > 2))
{
string placeStr = CMissionParser::getNoBlankString( params[2] );
CPlace * place = CZoneManager::getInstance().getPlaceFromName( placeStr );
if ( !place )
{
MISLOG("sline:%u ERROR : kill_fauna : Invalid place %u", _SourceLine, _Place);
}
else
_Place = place->getId();
}
////
}
nbSubSteps++;
if (faunaSheet != CSheetId::Unknown)
{
retParams.push_back(STRING_MANAGER::TParam());
retParams.back().Type = STRING_MANAGER::creature_model;
retParams.back().SheetId = _SubSteps[i].Sheet;
retParams.back().SheetId = faunaSheet;
retParams.push_back(STRING_MANAGER::TParam());
retParams.back().Type = STRING_MANAGER::integer;
retParams.back().Int = subStepStates[i];
}
}
}
if (faunaSheet != CSheetId::Unknown)
{
if ( _Place != 0xFFFF )
{
STRING_MANAGER::TParam param;
@ -198,6 +297,9 @@ class CMissionStepKillFauna : public IMissionStepTemplate
else
textPtr = &stepText;
}
else
textPtr = &stepTextReact;
}
std::vector< CSubStep > _SubSteps;
uint16 _Place;
@ -329,6 +431,7 @@ class CMissionStepKillRace : public IMissionStepTemplate
virtual void getTextParams( uint & nbSubSteps, const std::string* & textPtr,TVectorParamCheck& retParams, const std::vector<uint32>& subStepStates)
{
static const std::string stepTextReact = "MIS_NEED_REACTIVATION";
static const std::string stepText = "MIS_KILL_RACE_";
static const std::string stepTextLoc = "MIS_KILL_RACE_LOC_";
@ -380,6 +483,7 @@ class CMissionStepKillNpc : public IMissionStepTemplate
{
struct CSubStep
{
string Dynamic;
TAIAlias Alias;
// NLMISC::TStringId NpcName;
};
@ -400,9 +504,17 @@ class CMissionStepKillNpc : public IMissionStepTemplate
for ( uint i = 0; i < subs.size(); i++ )
{
CSubStep subStep;
//// Dynamic Mission Args : #dynamic#
if (trim(subs[i]) == "#dynamic#") {
subStep.Dynamic = missionData.Name;
}
////
else
{
subStep.Alias = CAIAliasTranslator::Invalid;
if ( !CMissionParser::parseBotName(subs[i],subStep.Alias,missionData) )
ret = false;
}
_SubSteps.push_back( subStep );
}
return ret;
@ -410,6 +522,9 @@ class CMissionStepKillNpc : public IMissionStepTemplate
}
uint processEvent( const TDataSetRow & userRow, const CMissionEvent & event,uint subStepIndex,const TDataSetRow & giverRow )
{
string webAppUrl;
CCharacter * user = PlayerManager.getChar(getEntityIdFromRow(userRow));
if ( event.Type == CMissionEvent::Kill )
{
CMissionEventKill & eventSpe = (CMissionEventKill&)event;
@ -419,6 +534,8 @@ class CMissionStepKillNpc : public IMissionStepTemplate
LOGMISSIONSTEPERROR("kill_npc : invalid creature " + toString(event.TargetEntity.getIndex()));
}
else
{
if (_SubSteps[subStepIndex].Dynamic.empty())
{
if ( _SubSteps[subStepIndex].Alias != CAIAliasTranslator::Invalid )
{
@ -434,6 +551,30 @@ class CMissionStepKillNpc : public IMissionStepTemplate
return 1;
}
}
else
{
//// Dynamic Mission Args
vector<string> params = user->getCustomMissionParams(_SubSteps[subStepIndex].Dynamic);
if (params.size() < 2) {
LOGMISSIONSTEPERROR("kill_npc : invalid dynamic npc");
return 0;
}
else
{
webAppUrl = params[0];
string name;
CAIAliasTranslator::getInstance()->getNPCNameFromAlias(c->getAlias(), name);
if ( name == params[1] )
{
user->validateDynamicMissionStep(webAppUrl);
LOGMISSIONSTEPSUCCESS("kill_npc");
return 1;
}
}
////
}
}
}
return 0;
}
@ -450,6 +591,7 @@ class CMissionStepKillNpc : public IMissionStepTemplate
virtual void getTextParams( uint & nbSubSteps, const std::string* & textPtr,TVectorParamCheck& retParams, const std::vector<uint32>& subStepStates)
{
static const std::string stepTextReact = "MIS_NEED_REACTIVATION";
static const std::string stepText = "MIS_KILL_NPC_";
textPtr = &stepText;
nlassert( _SubSteps.size() == subStepStates.size() );
@ -460,11 +602,35 @@ class CMissionStepKillNpc : public IMissionStepTemplate
nbSubSteps++;
retParams.push_back(STRING_MANAGER::TParam());
retParams.back().Type = STRING_MANAGER::bot;
if (_SubSteps[i].Dynamic.empty())
{
if ( _SubSteps[i].Alias != CAIAliasTranslator::Invalid )
retParams.back().Int = _SubSteps[i].Alias;
else
retParams.back().Identifier = "giver";
}
else
{
vector<string> params = _User->getCustomMissionParams(_SubSteps[i].Dynamic);
if (params.size() < 2)
{
nlinfo("kill_npc : invalid dynamic npc");
textPtr = &stepTextReact;
return;
}
else
{
vector<TAIAlias> aliases;
CAIAliasTranslator::getInstance()->getNPCAliasesFromName( params[1] , aliases );
if ( aliases.empty() )
{
retParams.back().Int = CAIAliasTranslator::Invalid;
return;
}
retParams.back().Int = aliases[0];
}
}
}
}
}
@ -891,10 +1057,6 @@ class CMissionStepKillByName : public IMissionStepTemplate
MISSION_REGISTER_STEP(CMissionStepKillByName,"kill_npc_by_name");
// ----------------------------------------------------------------------------
class CMissionStepKillPlayer : public IMissionStepTemplate
{

View file

@ -22,6 +22,7 @@
#include "mission_manager/mission_parser.h"
#include "mission_manager/ai_alias_translator.h"
#include "player_manager/character.h"
#include "player_manager/player_manager.h"
#include "creature_manager/creature_manager.h"
#include "mission_manager/mission_manager.h"
#include "game_item_manager/player_inv_xchg.h"
@ -49,18 +50,29 @@ class CMissionStepTalk : public IMissionStepTemplate
bool buildStep( uint32 line, const std::vector< std::string > & script, CMissionGlobalParsingData & globalData, CMissionSpecificParsingData & missionData )
{
_SourceLine = line;
if ( script.size() < 3 )
if ( script.size() < 2 )
{
MISLOGSYNTAXERROR("<npc_name> [: <phrase_id>*[;<param>]]");
return false;
}
bool ret = true;
//// Dynamic Mission Args : #dynamic#
if (trim(script[1]) == "#dynamic#")
{
_Dynamic = missionData.Name;
_PhraseId = _Dynamic+"_ACTION";
_IsDynamic = true;
}
else
{
_IsDynamic = false;
// parse bot
if ( !CMissionParser::parseBotName(script[1], _Bot, missionData) )
{
MISLOGERROR1("invalid npc '%s'", script[1].c_str());
return false;
}
// parse phrase and params
if (script.size() > 2)
{
@ -80,12 +92,13 @@ class CMissionStepTalk : public IMissionStepTemplate
// add a first default param (the name of the bot we talk to)
_Params.insert(_Params.begin(), STRING_MANAGER::TParam());
_Params[0].Identifier = CMissionParser::getNoBlankString(script[1]);
}
return true;
}
uint processEvent( const TDataSetRow & userRow, const CMissionEvent & event,uint subStepIndex,const TDataSetRow & giverRow )
{
_User = PlayerManager.getChar(getEntityIdFromRow(userRow));
// not check here : they are done befor. If a talk event comes here, the step is complete
if( event.Type == CMissionEvent::Talk )
{
@ -102,9 +115,50 @@ class CMissionStepTalk : public IMissionStepTemplate
ret[0] = 1;
}
bool getDynamicBot(TAIAlias & aliasRet)
{
if (_User != NULL)
{
vector<string> params = _User->getCustomMissionParams(_Dynamic);
if (params.size() < 2)
{
MISLOG("sline:%u ERROR : talk_to (sendContextText) : invalid bot", _SourceLine);
return false;
}
else
{
vector<TAIAlias> aliases;
CAIAliasTranslator::getInstance()->getNPCAliasesFromName(params[1], aliases);
if ( aliases.empty() )
{
MISLOG("sline:%u ERROR : talk_to (sendContextText) : invalid bot", _SourceLine);
return false;
}
aliasRet = aliases[0];
return true;
}
}
return false;
}
virtual uint32 sendContextText(const TDataSetRow& user, const TDataSetRow& interlocutor, CMission * instance, bool & gift, const NLMISC::CEntityId & giver )
{
if (_IsDynamic)
{
if (!getDynamicBot(_Bot) || _User == NULL)
{
MISLOG("sline:%u ERROR : talk_to (sendContextText) : invalid bot", _SourceLine);
return 0;
}
TVectorParamCheck params;
return STRING_MANAGER::sendStringToClient( user, _PhraseId, params );
}
CCreature * bot = CreatureManager.getCreature( interlocutor );
if ( bot )
{
if ( ( _Bot != CAIAliasTranslator::Invalid && _Bot == bot->getAlias() ) ||
@ -124,6 +178,12 @@ class CMissionStepTalk : public IMissionStepTemplate
virtual bool hasBotChatOption(const TDataSetRow & interlocutor, CMission * instance, bool & gift)
{
if (_IsDynamic && !getDynamicBot(_Bot))
{
MISLOG("sline:%u ERROR : talk_to (sendContextText) : invalid bot", _SourceLine);
return 0;
}
CCreature * bot = CreatureManager.getCreature( interlocutor );
if ( bot )
{
@ -140,6 +200,27 @@ class CMissionStepTalk : public IMissionStepTemplate
virtual void getTextParams( uint & nbSubSteps,const std::string* & textPtr,TVectorParamCheck& retParams, const std::vector<uint32>& subStepStates)
{
if (_IsDynamic && !getDynamicBot(_Bot))
{
MISLOG("sline:%u ERROR : talk_to (sendContextText) : invalid bot", _SourceLine);
static const std::string stepText = "DEBUG_CRASH_P_SMG_CRASH2";
textPtr = &stepText;
return;
}
if (_IsDynamic && _User != NULL)
{
vector<string> params = _User->getCustomMissionParams(_Dynamic);
if (params.size() < 2)
{
MISLOG("sline:%u ERROR : talk_to (sendContextText) : invalid bot", _SourceLine);
return;
}
_Params.insert(_Params.begin(), STRING_MANAGER::TParam());
_Params[0].Identifier = params[1];
}
nbSubSteps = 1;
static const std::string stepText = "MIS_TALK_TO";
textPtr = &stepText;
@ -151,16 +232,23 @@ class CMissionStepTalk : public IMissionStepTemplate
else
retParams[0].Identifier = "giver";
}
bool solveTextsParams( CMissionSpecificParsingData & missionData,CMissionTemplate * templ )
{
if (!_IsDynamic)
{
bool ret = IMissionStepTemplate::solveTextsParams(missionData,templ);
if ( !CMissionParser::solveTextsParams(_SourceLine, _Params,missionData ) )
ret = false;
return ret;
}
return true;
}
virtual TAIAlias getInvolvedBot(bool& invalidIsGiver) const { invalidIsGiver=true; return _Bot; }
bool _IsDynamic;
std::string _Dynamic;
std::string _PhraseId;
TVectorParamCheck _Params;
TAIAlias _Bot;

Some files were not shown because too many files have changed in this diff Show more