Merge with develop

--HG--
branch : compatibility-develop
This commit is contained in:
kervala 2015-12-29 22:36:04 +01:00
commit 2f45ff1ebe
17 changed files with 862 additions and 57 deletions

View file

@ -1,7 +1,4 @@
IF(RYZOM_ETC_PREFIX STREQUAL ".") IF(WITH_UNIX_STRUCTURE)
# in case of local client, only copy 48x48 icon
INSTALL(FILES ryzom_48x48.png DESTINATION ${RYZOM_ETC_PREFIX} RENAME ${RYZOM_CLIENT_ICON}.png)
ELSE()
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/ryzom_client.desktop.in" "${CMAKE_CURRENT_BINARY_DIR}/ryzom_client.desktop") CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/ryzom_client.desktop.in" "${CMAKE_CURRENT_BINARY_DIR}/ryzom_client.desktop")
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/ryzom_client.desktop" DESTINATION share/applications) INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/ryzom_client.desktop" DESTINATION share/applications)
@ -13,4 +10,7 @@ ELSE()
INSTALL(FILES ryzom_32x32.png DESTINATION share/icons/hicolor/32x32/apps RENAME ${RYZOM_CLIENT_ICON}.png) INSTALL(FILES ryzom_32x32.png DESTINATION share/icons/hicolor/32x32/apps RENAME ${RYZOM_CLIENT_ICON}.png)
INSTALL(FILES ryzom_48x48.png DESTINATION share/icons/hicolor/48x48/apps RENAME ${RYZOM_CLIENT_ICON}.png) INSTALL(FILES ryzom_48x48.png DESTINATION share/icons/hicolor/48x48/apps RENAME ${RYZOM_CLIENT_ICON}.png)
INSTALL(FILES ryzom_128x128.png DESTINATION share/icons/hicolor/128x128/apps RENAME ${RYZOM_CLIENT_ICON}.png) INSTALL(FILES ryzom_128x128.png DESTINATION share/icons/hicolor/128x128/apps RENAME ${RYZOM_CLIENT_ICON}.png)
ELSE()
# in case of local client, only copy 48x48 icon
INSTALL(FILES ryzom_48x48.png DESTINATION ${RYZOM_ETC_PREFIX} RENAME ${RYZOM_CLIENT_ICON}.png)
ENDIF() ENDIF()

View file

@ -49,7 +49,7 @@ NL_INSTANCE_COUNTER_IMPL(CBackupInterfaceSingleton);
// method used to update stuff on config file reload / variable change // method used to update stuff on config file reload / variable change
void onSaveShardRootModified( NLMISC::IVariable &var ); void onSaveShardRootModified( NLMISC::IVariable &var );
// configuration variables - to be setup in cfg files // configuration variables - to be setup in cfg files
CVariable<string> SaveShardRoot("variables", "SaveShardRoot", "Root directory of all files saved by any shard", "", 0, true, onSaveShardRootModified, false); CVariable<string> SaveShardRootGameShare("variables", "SaveShardRoot", "Root directory of all files saved by any shard", "", 0, true, onSaveShardRootModified, false);
// stats variables // stats variables
CVariable<NLMISC::TTime> BSLastAckTime("BSIF", "BSLastAckTime", "The timestamp of the last ack received from backup system", 0, 0, true); CVariable<NLMISC::TTime> BSLastAckTime("BSIF", "BSLastAckTime", "The timestamp of the last ack received from backup system", 0, 0, true);
@ -103,15 +103,15 @@ void CBackupInterfaceSingleton::init()
_ShardDependentBsi.init("BS"); _ShardDependentBsi.init("BS");
_ShardDependentBsi.setRemotePath( IService::getInstance()->SaveFilesDirectory.toString() ); _ShardDependentBsi.setRemotePath( IService::getInstance()->SaveFilesDirectory.toString() );
_ShardDependentBsi.setLocalPath( CPath::standardizePath( SaveShardRoot.get() ) + IService::getInstance()->SaveFilesDirectory.toString() ); _ShardDependentBsi.setLocalPath( CPath::standardizePath( SaveShardRootGameShare.get() ) + IService::getInstance()->SaveFilesDirectory.toString() );
_GlobalBsi.init("BS"); _GlobalBsi.init("BS");
_GlobalBsi.setRemotePath( string() ); _GlobalBsi.setRemotePath( string() );
_GlobalBsi.setLocalPath( SaveShardRoot.get() ); _GlobalBsi.setLocalPath( SaveShardRootGameShare.get() );
// _PDBsi.init("PDBS"); // _PDBsi.init("PDBS");
// _PDBsi.setRemotePath( IService::getInstance()->SaveFilesDirectory.toString() ); // _PDBsi.setRemotePath( IService::getInstance()->SaveFilesDirectory.toString() );
// _PDBsi.setLocalPath( CPath::standardizePath( SaveShardRoot.get() ) + IService::getInstance()->SaveFilesDirectory.toString() ); // _PDBsi.setLocalPath( CPath::standardizePath( SaveShardRootGameShare.get() ) + IService::getInstance()->SaveFilesDirectory.toString() );
IService::getInstance()->setDirectoryChangeCallback( this ); IService::getInstance()->setDirectoryChangeCallback( this );
} }
@ -357,9 +357,9 @@ void CBackupInterfaceSingleton::onVariableChanged( NLMISC::IVariable &var )
if ( var.getName() == "SaveFilesDirectory" ) if ( var.getName() == "SaveFilesDirectory" )
{ {
_ShardDependentBsi.setRemotePath( var.toString() ); _ShardDependentBsi.setRemotePath( var.toString() );
_ShardDependentBsi.setLocalPath( CPath::standardizePath( SaveShardRoot.get() ) + var.toString() ); _ShardDependentBsi.setLocalPath( CPath::standardizePath( SaveShardRootGameShare.get() ) + var.toString() );
// _PDBsi.setRemotePath( var.toString() ); // _PDBsi.setRemotePath( var.toString() );
// _PDBsi.setLocalPath( CPath::standardizePath( SaveShardRoot.get() ) + var.toString() ); // _PDBsi.setLocalPath( CPath::standardizePath( SaveShardRootGameShare.get() ) + var.toString() );
} }
else if ( var.getName() == "SaveShardRoot" ) else if ( var.getName() == "SaveShardRoot" )
{ {

View file

@ -36,7 +36,7 @@ NLMISC::CVariable<std::string> BSFileSubst("backup", "BSFileSubst", "file read/w
NLMISC::CVariable<bool> VerboseLog("backup", "VerboseLog", "Activate verbose logging of BS activity", false); NLMISC::CVariable<bool> VerboseLog("backup", "VerboseLog", "Activate verbose logging of BS activity", false);
NLMISC::CVariable<bool> UseTempFile("backup", "UseTempFile", "Flag the use of temporary file for safe write or append operation", true, true); NLMISC::CVariable<bool> UseTempFile("backup", "UseTempFile", "Flag the use of temporary file for safe write or append operation", true, true);
extern NLMISC::CVariable<std::string> SaveShardRoot; extern NLMISC::CVariable<std::string> SaveShardRootBackupService;
bool bsstrincmp(const char* s1, const char* s2, int n) bool bsstrincmp(const char* s1, const char* s2, int n)
{ {
@ -48,7 +48,7 @@ bool bsstrincmp(const char* s1, const char* s2, int n)
std::string getBackupFileName(const std::string& filename) std::string getBackupFileName(const std::string& filename)
{ {
return SaveShardRoot.get() + filename; return SaveShardRootBackupService.get() + filename;
/* // BSFilePrefix and BSFileSubst are deprecated /* // BSFilePrefix and BSFileSubst are deprecated
if (BSFilePrefix.get().empty()) if (BSFilePrefix.get().empty())
return filename; return filename;

View file

@ -62,7 +62,7 @@ struct CBackupMsgSaveFileRecv
extern CDirectoryRateStat DirStats; extern CDirectoryRateStat DirStats;
extern NLMISC::CVariable<std::string> SaveShardRoot; extern NLMISC::CVariable<std::string> SaveShardRootBackupService;
using namespace NLNET; using namespace NLNET;
using namespace NLMISC; using namespace NLMISC;
@ -542,7 +542,7 @@ static CMessage getFileClassImp( CMessage& msgin)
} }
} }
// In case something like getPathContent() has returned full paths, make paths relative to match the requested filenames // In case something like getPathContent() has returned full paths, make paths relative to match the requested filenames
fdc.stripFilename(SaveShardRoot.get()); fdc.stripFilename(SaveShardRootBackupService.get());
// compose the output message // compose the output message
CMessage msgout("BS_FILE_CLASS"); CMessage msgout("BS_FILE_CLASS");

View file

@ -30,7 +30,7 @@ using namespace NLNET;
CDirectoryRateStat DirStats; CDirectoryRateStat DirStats;
extern CVariable<string> SaveShardRoot; extern CVariable<string> SaveShardRootBackupService;
NLMISC_COMMAND(displayFileStats, "display file read/write stats for the last minute", "") NLMISC_COMMAND(displayFileStats, "display file read/write stats for the last minute", "")
@ -74,9 +74,9 @@ NLMISC_COMMAND ( dumpCharacterFile, "dump the content of the save file for a cha
{ {
// just output the list of available shard id // just output the list of available shard id
vector<string> shards; vector<string> shards;
CPath::getPathContent(SaveShardRoot, false, true, false, shards); CPath::getPathContent(SaveShardRootBackupService, false, true, false, shards);
log.displayNL("Listing %u available shard id in path '%s':", shards.size(), SaveShardRoot.c_str()); log.displayNL("Listing %u available shard id in path '%s':", shards.size(), SaveShardRootBackupService.c_str());
for (uint i=0; i<shards.size(); ++i) for (uint i=0; i<shards.size(); ++i)
{ {
string id = shards[i]; string id = shards[i];
@ -107,7 +107,7 @@ NLMISC_COMMAND ( dumpCharacterFile, "dump the content of the save file for a cha
useFilter = true; useFilter = true;
} }
string fileName = SaveShardRoot.toString()+"/"+args[0]+"/characters/account_"+args[1]+"_"+args[2]+"_pdr.bin"; string fileName = SaveShardRootBackupService.toString()+"/"+args[0]+"/characters/account_"+args[1]+"_"+args[2]+"_pdr.bin";
if (!CFile::isExists(fileName)) if (!CFile::isExists(fileName))
{ {
log.displayNL("The file '%s' (located here '%s') cannot be found in '%s' backup directory", log.displayNL("The file '%s' (located here '%s') cannot be found in '%s' backup directory",

View file

@ -169,8 +169,7 @@ void cbOnSaveShardRootModified( NLMISC::IVariable& var )
} }
CVariable<string> IncrementalBackupDirectory("backup", "IncrementalBackupDirectory", "Directory to find incremental backuped archives", "", 0, true); CVariable<string> IncrementalBackupDirectory("backup", "IncrementalBackupDirectory", "Directory to find incremental backuped archives", "", 0, true);
// (SaveShardRoot from game_share/backup_service_interface.cpp is not instanciated because the nothing is used from that file) CVariable<string> SaveShardRootBackupService("backup", "SaveShardRoot", "Root directory of all saved data by BS", "/home/nevrax/save_shard", 0, true, cbOnSaveShardRootModified); // (SaveShardRoot from game_share/backup_service_interface.cpp is not instanciated because the nothing is used from that file)
extern CVariable<string> SaveShardRoot;
CVariable<string> SaveTemplatePath("backup", "SaveTemplatePath", "Directory to find saves (with shard and account replacement strings)", "$shard/characters/account_$userid_$charid$ext", 0, true); CVariable<string> SaveTemplatePath("backup", "SaveTemplatePath", "Directory to find saves (with shard and account replacement strings)", "$shard/characters/account_$userid_$charid$ext", 0, true);
CVariable<string> SaveExtList("backup", "SaveExtList", "List of possible extensions for save files (space separated)", "_pdr.bin _pdr.xml .bin", 0, true); CVariable<string> SaveExtList("backup", "SaveExtList", "List of possible extensions for save files (space separated)", "_pdr.bin _pdr.xml .bin", 0, true);
@ -210,7 +209,7 @@ void cbGetSaveList(CMemStream &msgin, TSockId host)
explode(str, string("%%"), params, true); explode(str, string("%%"), params, true);
string incrementalDir = IncrementalBackupDirectory.get(); string incrementalDir = IncrementalBackupDirectory.get();
string saveShardRoot = SaveShardRoot.get(); string saveShardRoot = SaveShardRootBackupService.get();
string templatePath = SaveTemplatePath.get(); string templatePath = SaveTemplatePath.get();
string extList = SaveExtList.get(); string extList = SaveExtList.get();
@ -293,7 +292,7 @@ void cbRestoreSave(CMemStream &msgin, TSockId host)
explode(str, string("%%"), params, true); explode(str, string("%%"), params, true);
string saveShardRoot = SaveShardRoot.get(); string saveShardRoot = SaveShardRootBackupService.get();
string templatePath = SaveTemplatePath.get(); string templatePath = SaveTemplatePath.get();
string shard; string shard;
@ -368,7 +367,7 @@ void cbCopyOverSave(CMemStream &msgin, TSockId host)
explode(str, string("%%"), params, true); explode(str, string("%%"), params, true);
string saveShardRoot = SaveShardRoot.get(); string saveShardRoot = SaveShardRootBackupService.get();
string templatePath = SaveTemplatePath.get(); string templatePath = SaveTemplatePath.get();
string extList = SaveExtList.get(); string extList = SaveExtList.get();

View file

@ -268,10 +268,6 @@ void CCreatureSetUrlImp::callback(const string &, NLNET::TServiceId sid)
uint32 program = c->getBotChatProgram(); uint32 program = c->getBotChatProgram();
if(!(program & (1<<BOTCHATTYPE::WebPageFlag))) if(!(program & (1<<BOTCHATTYPE::WebPageFlag)))
{ {
if(program != 0)
{
return;
}
program |= 1 << BOTCHATTYPE::WebPageFlag; program |= 1 << BOTCHATTYPE::WebPageFlag;
c->setBotChatProgram(program); c->setBotChatProgram(program);
} }

View file

@ -51,7 +51,8 @@ public:
void cancelAFK(); void cancelAFK();
CCreature * getInterlocutor(); CCreature * getInterlocutor();
CModuleParent & getModuleParent(); CModuleParent & getModuleParent();
void sendSystemMessage( const std::string & msg, const TVectorParamCheck & params = TVectorParamCheck() ); void sendSystemMessage( const std::string & msg, const TVectorParamCheck & params);
void sendSystemMessage( const std::string & msg);
void sendDynamicMessageToChatGroup( const std::string & msg, CChatGroup::TGroupType type, const TVectorParamCheck & params = TVectorParamCheck() ); void sendDynamicMessageToChatGroup( const std::string & msg, CChatGroup::TGroupType type, const TVectorParamCheck & params = TVectorParamCheck() );
uint64 getMoney(); uint64 getMoney();
void spendMoney(uint64 money); void spendMoney(uint64 money);

View file

@ -33,9 +33,13 @@
#include "mission_manager/mission_guild.h" #include "mission_manager/mission_guild.h"
#include "guild_manager/guild_manager.h" #include "guild_manager/guild_manager.h"
#include "guild_manager/guild.h" #include "guild_manager/guild.h"
#include "building_manager/building_manager.h"
#include "building_manager/building_physical.h"
#include "admin.h" #include "admin.h"
#include "creature_manager/creature_manager.h" #include "creature_manager/creature_manager.h"
#include "world_instances.h"
using namespace NLMISC; using namespace NLMISC;
using namespace NLNET; using namespace NLNET;
@ -553,3 +557,677 @@ NLMISC_COMMAND(addMission,"Add mission to character","<character_id> <Mission gi
return true; return true;
} }
/// Commands used by ARK
CInventoryPtr getInventory(CCharacter *c, const string &inv)
{
CInventoryPtr inventoryPtr = NULL;
if (!inv.empty())
{
INVENTORIES::TInventory selectedInv = INVENTORIES::toInventory(inv);
switch (selectedInv)
{
case INVENTORIES::temporary:
case INVENTORIES::bag:
case INVENTORIES::equipment:
case INVENTORIES::pet_animal1:
case INVENTORIES::pet_animal2:
case INVENTORIES::pet_animal3:
case INVENTORIES::pet_animal4:
case INVENTORIES::guild:
case INVENTORIES::player_room:
inventoryPtr = c->getInventory(selectedInv);
break;
default:
// No-op
break;
}
}
return inventoryPtr;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(getEid, "get entitiy id of entity", "<uid>")
{
GET_ACTIVE_CHARACTER
log.displayNL("%s", c->getId().toString().c_str());
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(getItemList, "get list of named items of character by filter", "<uid> [bag sheet quantity_min quantity_max quality_min quality_max extra_infos]")
{
GET_ACTIVE_CHARACTER
std::vector<INVENTORIES::TInventory> inventories;
string selected_inv = "*";
string filter = "*";
uint32 quantity_min = 0;
uint32 quantity_max = 999;
uint32 quality_min = 0;
uint32 quality_max = 999;
string extra;
if (args.size() > 1)
selected_inv = args[1];
if (args.size() > 2)
filter = args[2];
if (args.size() > 3)
fromString(args[3], quantity_min);
if (args.size() > 4)
fromString(args[4], quantity_max);
if (args.size() > 5)
fromString(args[5], quality_min);
if (args.size() > 6)
fromString(args[6], quality_max);
if (args.size() > 7)
extra = args[7];
string msg;
if (selected_inv != "*")
{
std::vector<string> invs;
NLMISC::splitString(selected_inv, ",", invs);
for (uint32 i=0; i<invs.size(); i++)
{
INVENTORIES::TInventory selectedInv = INVENTORIES::toInventory(invs[i]);
if (selectedInv != INVENTORIES::UNDEFINED)
inventories.push_back(selectedInv);
}
} else {
inventories.push_back(INVENTORIES::equipment);
inventories.push_back(INVENTORIES::bag);
inventories.push_back(INVENTORIES::pet_animal1);
inventories.push_back(INVENTORIES::pet_animal2);
inventories.push_back(INVENTORIES::pet_animal3);
inventories.push_back(INVENTORIES::pet_animal4);
inventories.push_back(INVENTORIES::guild);
inventories.push_back(INVENTORIES::player_room);
}
if (inventories.empty()) {
log.displayNL("ERR: invalid inventories");
return false;
}
for (uint32 i=0; i<inventories.size(); i++)
{
CInventoryPtr childSrc = c->getInventory(inventories[i]);
if (childSrc != NULL)
{
uint32 k = 0;
log.displayNL("#%s", INVENTORIES::toString(inventories[i]).c_str());
for ( uint j = 0; j < childSrc->getSlotCount(); j++ )
{
CGameItemPtr itemPtr = childSrc->getItem(j);
if (itemPtr != NULL)
{
string sheet = itemPtr->getSheetId().toString();
if (testWildCard(sheet, filter))
{
uint32 item_stack = itemPtr->getStackSize();
uint32 item_quality = itemPtr->quality();
if (item_stack >= quantity_min && item_stack <= quantity_max
&& item_quality >= quality_min && item_quality <= quality_max)
{
string item_stats = toString("%3d|%s|", j, sheet.c_str());
if (!extra.empty())
itemPtr->getStats(extra, item_stats);
log.displayNL(item_stats.c_str());
}
}
}
}
}
}
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(getNamedItemList, "get list of named items of character by filter", "<uid> [bag named quantity_min quantity_max quality_min quality_max extra_infos]")
{
GET_ACTIVE_CHARACTER
std::vector<INVENTORIES::TInventory> inventories;
string selected_inv = "*";
string filter = "*";
uint32 quantity_min = 0;
uint32 quantity_max = 999;
uint32 quality_min = 0;
uint32 quality_max = 999;
string extra;
if (args.size() > 1)
selected_inv = args[1];
if (args.size() > 2)
filter = args[2];
if (args.size() > 3)
fromString(args[3], quantity_min);
if (args.size() > 4)
fromString(args[4], quantity_max);
if (args.size() > 5)
fromString(args[5], quality_min);
if (args.size() > 6)
fromString(args[6], quality_max);
if (args.size() > 7)
extra = args[7];
string msg;
if (selected_inv != "*")
{
std::vector<string> invs;
NLMISC::splitString(selected_inv, ",", invs);
for (uint32 i=0; i<invs.size(); i++)
{
INVENTORIES::TInventory selectedInv = INVENTORIES::toInventory(invs[i]);
if (selectedInv != INVENTORIES::UNDEFINED)
inventories.push_back(selectedInv);
}
} else {
inventories.push_back(INVENTORIES::equipment);
inventories.push_back(INVENTORIES::bag);
inventories.push_back(INVENTORIES::pet_animal1);
inventories.push_back(INVENTORIES::pet_animal2);
inventories.push_back(INVENTORIES::pet_animal3);
inventories.push_back(INVENTORIES::pet_animal4);
inventories.push_back(INVENTORIES::guild);
inventories.push_back(INVENTORIES::player_room);
}
for (uint32 i=0; i<inventories.size(); i++)
{
CInventoryPtr childSrc = c->getInventory(inventories[i]);
if (childSrc != NULL)
{
uint32 k = 0;
log.displayNL("#%s", INVENTORIES::toString(inventories[i]).c_str());
for ( uint j = 0; j < childSrc->getSlotCount(); j++ )
{
CGameItemPtr itemPtr = childSrc->getItem(j);
if (itemPtr != NULL)
{
string phraseId = itemPtr->getPhraseId();
if (!phraseId.empty() && testWildCard(phraseId, filter))
{
uint32 item_stack = itemPtr->getStackSize();
uint32 item_quality = itemPtr->quality();
if (item_stack >= quantity_min && item_stack <= quantity_max
&& item_quality >= quality_min && item_quality <= quality_max)
{
string item_stats = toString("%3d|%s|", j, phraseId.c_str());
if (!extra.empty())
itemPtr->getStats(extra, item_stats);
log.displayNL(item_stats.c_str());
}
}
}
}
}
}
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(deleteInventoryItems, "Delete items from a characters inventory", "<uid> <sheetnames> <quality> <quantity>")
{
if (args.size () < 5)
{
log.displayNL("ERR: Invalid number of parameters. Parameters: <inventory> <sheetnames> <quality> <quantity>");
return false;
}
GET_ACTIVE_CHARACTER
std::map<string, uint32> need_items;
std::vector<string> sheet_names;
NLMISC::splitString(args[1], ",", sheet_names);
std::vector<string> qualities;
NLMISC::splitString(args[2], ",", qualities);
std::vector<string> quantities;
NLMISC::splitString(args[3], ",", quantities);
for (uint32 i=0; i < std::min(quantities.size(), std::min(qualities.size(), sheet_names.size())); i++)
{
uint32 quantity = 0;
fromString(quantities[i], quantity);
need_items.insert(make_pair(sheet_names[i]+":"+qualities[i], quantity));
}
std::map<uint32, uint32> slots;
std::map<string, uint32>::iterator itNeedItems;
// Save list of slots and quantities to delete
CInventoryPtr inventory = c->getInventory(INVENTORIES::bag);
if (inventory != NULL)
{
for ( uint32 j = 0; j < inventory->getSlotCount(); j++ )
{
CGameItemPtr itemPtr = inventory->getItem(j);
if (itemPtr != NULL)
{
string sheet = itemPtr->getSheetId().toString();
uint32 item_quality = itemPtr->quality();
itNeedItems = need_items.find(sheet+":"+NLMISC::toString("%d", item_quality));
if (itNeedItems != need_items.end() && (*itNeedItems).second > 0)
{
nlinfo("Found : %s %d", sheet.c_str(), item_quality);
uint32 quantity = std::min((*itNeedItems).second, itemPtr->getStackSize());
slots.insert(make_pair(j, quantity));
(*itNeedItems).second -= quantity;
}
}
}
// Check if all items has been found
for ( itNeedItems = need_items.begin(); itNeedItems != need_items.end(); ++itNeedItems )
{
if ((*itNeedItems).second != 0) {
nlinfo("Missing : %s", (*itNeedItems).first.c_str());
log.displayNL("ERR: Not enough items.");
return false;
}
}
//Delete them
for ( std::map<uint32, uint32>::iterator it = slots.begin(); it != slots.end(); ++it )
{
nlinfo("Deleting... %d, %d", (*it).first, (*it).second);
inventory->deleteStackItem((*it).first, (*it).second);
}
}
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(getPosition, "get position of entity", "<uid>")
{
GET_ACTIVE_CHARACTER
double x = 0, y = 0, z = 0, h = 0;
sint32 cell = 0;
x = c->getState().X / 1000.;
y = c->getState().Y / 1000.;
z = c->getState().Z / 1000.;
h = c->getState().Heading;
TDataSetRow dsr = c->getEntityRowId();
CMirrorPropValueRO<TYPE_CELL> srcCell( TheDataset, dsr, DSPropertyCELL );
cell = srcCell;
log.displayNL("%.2f|%.2f|%.2f|%.4f|%d", x, y, z, h, cell);
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(getFame, "get fame of player", "<uid> faction")
{
if (args.size () < 2)
{
log.displayNL("ERR: invalid arg count");
return false;
}
GET_ACTIVE_CHARACTER
uint32 factionIndex = CStaticFames::getInstance().getFactionIndex(args[1]);
if (factionIndex == CStaticFames::INVALID_FACTION_INDEX)
{
log.displayNL("ERR: invalid fame");
return false;
}
sint32 fame = CFameInterface::getInstance().getFameIndexed(c->getId(), factionIndex);
log.displayNL("%d", fame);
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(getFames, "get fames of player", "<uid> faction1,faction2,faction3,...")
{
if (args.size () < 2)
{
log.displayNL("ERR: invalid arg count");
return false;
}
GET_ACTIVE_CHARACTER
string sfames;
std::pair<PVP_CLAN::TPVPClan, PVP_CLAN::TPVPClan> allegiance = c->getAllegiance();
log.displayNL("%s", PVP_CLAN::toString(allegiance.first).c_str());
log.displayNL("%s", PVP_CLAN::toString(allegiance.second).c_str());
log.displayNL("%d", c->getOrganization());
std::vector<string> fames;
NLMISC::splitString(args[1], ",", fames);
for (uint32 i=0; i<fames.size(); i++)
{
uint32 factionIndex = CStaticFames::getInstance().getFactionIndex(fames[i]);
if (factionIndex == CStaticFames::INVALID_FACTION_INDEX)
log.displayNL("ERR: invalid fame");
else
log.displayNL("%d", CFameInterface::getInstance().getFameIndexed(c->getId(), factionIndex));
}
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(getTarget, "get target of player", "<uid>")
{
GET_ACTIVE_CHARACTER
const CEntityId &target = c->getTarget();
string msg = target.toString()+"|";
if (target == CEntityId::Unknown)
{
log.displayNL("0");
return true;
}
if (target.getType() == RYZOMID::creature)
msg += "c|";
else if (target.getType() == RYZOMID::npc)
msg += "n|";
else if (target.getType() == RYZOMID::player)
msg += "p|";
else
msg += "0";
if (target.getType() == RYZOMID::player)
{
CCharacter * cTarget = dynamic_cast<CCharacter*>(CEntityBaseManager::getEntityBasePtr(target));
if (cTarget) {
msg += cTarget->getName().toString()+"|";
if (c->getGuildId() != 0 && c->getGuildId() == cTarget->getGuildId())
msg += "g|";
else
msg += "0|";
if (c->getTeamId() != CTEAM::InvalidTeamId && c->getTeamId() == cTarget->getTeamId())
msg += "t";
else
msg += "0";
}
}
log.displayNL(msg.c_str());
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(getMoney, "get money of player", "<uid>")
{
GET_ACTIVE_CHARACTER
string value = toString("%"NL_I64"u", c->getMoney());
log.displayNL(value.c_str());
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(getPvpPoints, "get pvp points of player", "<uid>")
{
GET_ACTIVE_CHARACTER
string value = toString("%u", c->getPvpPoint());
log.displayNL(value.c_str());
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(getCivCultOrg, "get civ cult and organization of player", "<uid>")
{
GET_ACTIVE_CHARACTER
std::pair<PVP_CLAN::TPVPClan, PVP_CLAN::TPVPClan> allegiance = c->getAllegiance();
log.displayNL("%s|%s|%u", PVP_CLAN::toString(allegiance.first).c_str(), PVP_CLAN::toString(allegiance.second).c_str(), c->getOrganization());
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(accessPowo, "give access to the powo", "<uid> player_name number")
{
GET_ACTIVE_CHARACTER
IBuildingPhysical * building;
if (args.size () >= 3)
building = CBuildingManager::getInstance()->getBuildingPhysicalsByName("building_instance_ZO_player_11"+args[2]);
else
building = CBuildingManager::getInstance()->getBuildingPhysicalsByName("building_instance_ZO_player_111");
if ( building )
{
if (building->getTemplate()->Type == BUILDING_TYPES::Player)
{
CBuildingPhysicalPlayer * buildingPlayer = dynamic_cast<CBuildingPhysicalPlayer *>( building );
CEntityBase *entityBase = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), args[2]));
if (buildingPlayer && entityBase)
{
CBuildingManager::getInstance()->removePlayerFromRoom( c );
uint16 ownerId = buildingPlayer->getOwnerIdx( entityBase->getId() );
sint32 cell;
buildingPlayer->addUser(c, 0, ownerId, cell);
c->setPowoCell(cell);
CBuildingManager::getInstance()->setRoomLifeTime(cell, TGameCycle(NLMISC::TGameTime(4*60*60) / CTickEventHandler::getGameTimeStep()));
log.displayNL("%d", cell);
}
} else {
log.displayNL("ERR: invalid number");
return false;
}
} else {
log.displayNL("ERR: invalid number");
return false;
}
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(slide, "slide to the powo", "<uid> x y cell [z] [h]")
{
if (args.size () < 4)
{
log.displayNL("ERR: invalid arg count");
return false;
}
GET_ACTIVE_CHARACTER
string value = args[1];
sint32 x;
sint32 y;
sint32 cell = c->getPowoCell();
sint32 z = 0;
float h = 0;
fromString(args[1], x);
x *= 1000;
fromString(args[2], y);
y *= 1000;
if (args[3] != "*")
fromString(args[3], cell);
if (args.size() >= 5)
{
fromString(args[4], z);
z *= 1000;
}
if (args.size() >= 6)
fromString(args[5], h);
c->teleportCharacter(x,y,z,false,true,h,0xFF,cell);
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(spawn, "spawn entity", "<uid> quantity sheet dispersion orientation groupname x y look cell")
{
if (args.size () < 10)
{
log.displayNL("ERR: invalid arg count");
return false;
}
GET_ACTIVE_CHARACTER
uint32 instanceNumber = 0;
sint32 x = 0;
sint32 y = 0;
sint32 z = c->getZ();
sint32 cell = 0;
sint32 orientation = 6666; // used to specify a random orientation
uint32 nbBots;
fromString(args[1], nbBots);
if (nbBots<=0)
{
log.displayNL("ERR: invalid bot count");
return false;
}
NLMISC::CSheetId sheetId(args[2]);
if (sheetId == NLMISC::CSheetId::Unknown)
sheetId = args[2] + ".creature";
if (sheetId == NLMISC::CSheetId::Unknown)
return true;
double dispersionRadius = 10.;
if (args.size()>3)
{
fromString(args[3], dispersionRadius);
if (dispersionRadius < 0.) {
log.displayNL("ERR: invalid dispersion");
return false;
}
}
bool spawnBots = true;
if (args.size()>4)
{
if (args[4] == "self")
{
orientation = (sint32)(c->getHeading() * 1000.0);
}
else if (args[4] != "random")
{
NLMISC::fromString(args[4], orientation);
orientation = (sint32)((double)orientation / 360.0 * (NLMISC::Pi * 2.0) * 1000.0);
}
}
string botsName = args[5];
float userX;
NLMISC::fromString(args[6], userX);
x = (sint32)(userX * 1000.0);
float userY;
NLMISC::fromString(args[7], userY);
y = (sint32)(userY * 1000.0);
string look = args[8];
NLMISC::fromString(args[9], cell);
// See if another AI instance has been specified
if (botsName.find("@") != string::npos)
{
string continent = botsName.substr(0, botsName.find('@'));
uint32 nr = CUsedContinent::instance().getInstanceForContinent(continent);
if (nr == ~0)
{
log.displayNL("ERR: invalid continent");
return false;
}
instanceNumber = nr;
botsName = botsName.substr(botsName.find('@') + 1, botsName.size());
}
CEntityId playerId = c->getId();
CMessage msgout("EVENT_CREATE_NPC_GROUP");
uint32 messageVersion = 1;
msgout.serial(messageVersion);
msgout.serial(instanceNumber);
msgout.serial(playerId);
msgout.serial(x);
msgout.serial(y);
msgout.serial(z);
msgout.serial(orientation);
msgout.serial(nbBots);
msgout.serial(sheetId);
msgout.serial(dispersionRadius);
msgout.serial(spawnBots);
msgout.serial(botsName);
msgout.serial(look);
msgout.serial(cell);
CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
return true;
}

View file

@ -181,7 +181,7 @@ void CDamageScoreTable::addPlayerDamage(TDataSetRow playerRowId, uint32 damage)
void CDamageScoreTable::addCreatureDamage(TDataSetRow creatureRowId, uint32 damage) void CDamageScoreTable::addCreatureDamage(TDataSetRow creatureRowId, uint32 damage)
{ {
nlassert(damage > 0); nlassert(damage > 0);
/*
CCreatureDamageScore * creatureScore = getCreatureDamageScore(creatureRowId); CCreatureDamageScore * creatureScore = getCreatureDamageScore(creatureRowId);
if (creatureScore == NULL) if (creatureScore == NULL)
{ {
@ -193,6 +193,7 @@ void CDamageScoreTable::addCreatureDamage(TDataSetRow creatureRowId, uint32 dama
{ {
creatureScore->TotalDamage += damage; creatureScore->TotalDamage += damage;
} }
*/
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1694,7 +1695,7 @@ bool CDamageScoreManager::playerInFactionPvP(const CCharacter * playerChar, PVP_
CPVPVersusZone * zone = dynamic_cast<CPVPVersusZone *>(const_cast<CPVPInterface &>(playerChar->getPVPInterface()).getPVPSession()); CPVPVersusZone * zone = dynamic_cast<CPVPVersusZone *>(const_cast<CPVPInterface &>(playerChar->getPVPInterface()).getPVPSession());
if (zone != NULL) if (zone != NULL)
{ {
PVP_CLAN::TPVPClan factionInZone = zone->getCharacterClan(playerChar->getId()); /*PVP_CLAN::TPVPClan factionInZone = zone->getCharacterClan(playerChar->getId());
if (factionInZone == PVP_CLAN::Neutral) if (factionInZone == PVP_CLAN::Neutral)
return false; return false;
@ -1705,7 +1706,7 @@ bool CDamageScoreManager::playerInFactionPvP(const CCharacter * playerChar, PVP_
if (withFactionPoints) if (withFactionPoints)
*withFactionPoints = zone->giveFactionPoints(); *withFactionPoints = zone->giveFactionPoints();
*/
return true; return true;
} }
} }

View file

@ -91,7 +91,7 @@ private:
struct CHash struct CHash
{ {
enum { bucket_size = 4, min_buckets = 8, }; enum { bucket_size = 4, min_buckets = 8 };
size_t operator () (const TEntityIndex& index) const { return index.getIndex(); } size_t operator () (const TEntityIndex& index) const { return index.getIndex(); }
bool operator() (const TEntityIndex& left, const TEntityIndex& right) { return left < right; } bool operator() (const TEntityIndex& left, const TEntityIndex& right) { return left < right; }
}; };

View file

@ -117,12 +117,15 @@ public:
/// Gets at maximum MAX_SEEN_ENTITIES entities contained in the cell /// Gets at maximum MAX_SEEN_ENTITIES entities contained in the cell
CVisionEntry* addEntities(CVisionEntry* fillPtr, CVisionEntry* endPtr, uint32 cellMask, uint32 distance) CVisionEntry* addEntities(CVisionEntry* fillPtr, CVisionEntry* endPtr, uint32 cellMask, uint32 distance, bool indoor, CWorldEntity *player)
{ {
CWorldEntity *ent = _EntitiesList.getHead(); CWorldEntity *ent = _EntitiesList.getHead();
while (ent != NULL && fillPtr < endPtr) while (ent != NULL && fillPtr < endPtr)
{ {
sint32 mask = cellMask & (sint32)(ent->WhoSeesMe); sint32 mask = cellMask & (sint32)(ent->WhoSeesMe);
if (mask && indoor && (float)(player->X()-ent->X())*(float)(player->X()-ent->X()) + (float)(player->Y()-ent->Y())*(float)(player->Y()-ent->Y()) > 15625000000)
mask = 0;
//if (!ent->IsInvisibleToPlayer && mask != 0) //if (!ent->IsInvisibleToPlayer && mask != 0)
if (mask != 0) if (mask != 0)
{ {
@ -136,12 +139,15 @@ public:
return fillPtr; return fillPtr;
} }
/// Gets at maximum MAX_SEEN_ENTITIES entities contained in the cell /// Gets at maximum MAX_SEEN_ENTITIES entities contained in the cell
CVisionEntry* addObjects(CVisionEntry* fillPtr, CVisionEntry* endPtr, uint32 cellMask, uint32 distance) CVisionEntry* addObjects(CVisionEntry* fillPtr, CVisionEntry* endPtr, uint32 cellMask, uint32 distance, bool indoor, CWorldEntity *player)
{ {
CWorldEntity *ent = _ObjectsList.getHead(); CWorldEntity *ent = _ObjectsList.getHead();
while (ent != NULL && fillPtr < endPtr) while (ent != NULL && fillPtr < endPtr)
{ {
sint32 mask = cellMask & (sint32)(ent->WhoSeesMe); sint32 mask = cellMask & (sint32)(ent->WhoSeesMe);
if (mask && indoor && (float)(player->X()-ent->X())*(float)(player->X()-ent->X()) + (float)(player->Y()-ent->Y())*(float)(player->Y()-ent->Y()) > 15625000000)
mask = 0;
//if (!ent->IsInvisibleToPlayer && mask != 0) //if (!ent->IsInvisibleToPlayer && mask != 0)
if (mask != 0) if (mask != 0)
{ {

View file

@ -493,7 +493,9 @@ void cbEntityTeleportation( CMessage& msgin, const string &serviceName, NLNET::T
id.serial( msgin ); id.serial( msgin );
TDataSetRow index = CWorldPositionManager::getEntityIndex(id); TDataSetRow index = CWorldPositionManager::getEntityIndex(id);
BOMB_IF(IsRingShard && !index.isValid(),"Ignoring request to TP entity withe invalid data set row: "<<id.toString(),return);
if (!index.isValid())
return;
// if no position provided, teleport entity to nowhere // if no position provided, teleport entity to nowhere
if (msgin.getPos() == (sint32)msgin.length()) if (msgin.getPos() == (sint32)msgin.length())
@ -544,6 +546,10 @@ void cbEntityTeleportation( CMessage& msgin, const string &serviceName, NLNET::T
cell = 0; cell = 0;
} }
uint8 move_to_new_cell = 0;
if (msgin.getPos() != (sint32)msgin.length())
msgin.serial(move_to_new_cell);
if (IsRingShard) if (IsRingShard)
{ {
// update the ring vision universe position // update the ring vision universe position
@ -560,14 +566,22 @@ void cbEntityTeleportation( CMessage& msgin, const string &serviceName, NLNET::T
} }
else else
{ {
if (move_to_new_cell == 1)
{
nlinfo("MSG: Sliding entity %d to cell %d) at tick: %d",index.getIndex(),cell,tick);
CWorldPositionManager::updateEntityPosition(CWorldPositionManager::getEntityPtr(index), cell);
}
else
{
nlinfo("MSG: Teleporting entity %d to continent %d cell %d (%d, %d, %d) at tick: %d",index.getIndex(),continent,cell,x,y,z,tick);
CWorldPositionManager::teleport(index, x, y, z, t, continent, cell, tick); CWorldPositionManager::teleport(index, x, y, z, t, continent, cell, tick);
} }
}
// lock entity after a real teleport // lock entity after a real teleport
CWorldPositionManager::lock(index, 10); CWorldPositionManager::lock(index, 10);
nlinfo("MSG: Teleporting entity %d to continent %d (%d, %d, %d) at tick: %d",index.getIndex(),continent,x,y,z,tick);
} // cbEntityTeleportation // } // cbEntityTeleportation //

View file

@ -2183,14 +2183,18 @@ void CWorldPositionManager::movePlayer(CWorldEntity *entity, sint32 x, sint32 y,
// Get the proper speed // Get the proper speed
CMirrorPropValueRO<TYPE_RUNSPEED> maxSpeed( TheDataset, entity->Index, DSPropertyCURRENT_RUN_SPEED ); CMirrorPropValueRO<TYPE_RUNSPEED> maxSpeed( TheDataset, entity->Index, DSPropertyCURRENT_RUN_SPEED );
float limitSpeedToUse = maxSpeed(); float limitSpeedToUse = maxSpeed();
// Get the proper speed of master
CMirrorPropValueRO<TYPE_RUNSPEED> maxSpeedMaster( TheDataset, master->Index, DSPropertyCURRENT_RUN_SPEED );
float mountWalkSpeed = maxSpeedMaster();
if ( entity != master ) if ( entity != master )
{ {
// If the player is on a mount, handle the hunger of the mount // If the player is on a mount, handle the hunger of the mount
if ( (movVector.x > 0.001) && (movVector.y > 0.001) ) // if ( (movVector.x > 0.001) && (movVector.y > 0.001) )
{ {
CMirrorPropValueRO<TYPE_WALKSPEED> walkSpeed( TheDataset, entity->Index, DSPropertyCURRENT_WALK_SPEED ); CMirrorPropValueRO<TYPE_WALKSPEED> walkSpeed( TheDataset, entity->Index, DSPropertyCURRENT_WALK_SPEED );
CSpeedLimit speedLimit( TheDataset, entity->Index ); CSpeedLimit speedLimit( TheDataset, entity->Index );
limitSpeedToUse = speedLimit.getSpeedLimit( walkSpeed, maxSpeed ); limitSpeedToUse = speedLimit.getSpeedLimit( walkSpeed, maxSpeed );
mountWalkSpeed = walkSpeed;
} }
} }
@ -2201,18 +2205,20 @@ void CWorldPositionManager::movePlayer(CWorldEntity *entity, sint32 x, sint32 y,
// Check player speed // Check player speed
// only consider (x,y) motion for speed and position correction // only consider (x,y) motion for speed and position correction
if (master->PlayerInfos != NULL && master->PlayerInfos->CheckSpeed && CheckPlayerSpeed && fabs(movVector.x)+fabs(movVector.y) > maxDist) if (master->PlayerInfos != NULL /*&& master->PlayerInfos->CheckSpeed && CheckPlayerSpeed && fabs(movVector.x)+fabs(movVector.y) > maxDist*/)
{ {
double movNorm = sqr(movVector.x)+sqr(movVector.y); // already done if (entity != master) but here is a rare overspeed case double movNorm = sqr(movVector.x)+sqr(movVector.y); // already done if (entity != master) but here is a rare overspeed case
if (movNorm > sqr(maxDist)) if (movNorm > sqr(maxDist))
{ {
if (VerboseSpeedAbuse) if (movNorm > sqr(5 * SecuritySpeedFactor * CTickEventHandler::getGameTimeStep() * ticksSinceLastUpdate)) {
{
nlwarning("CWorldPositionManager::movePlayer%s: limited speed (movNorm=%.2f, movMax=%.2f, maxSpeed=%.2f)", entity->Id.toString().c_str(), sqrt(movNorm), maxDist, limitSpeedToUse*0.001*SecuritySpeedFactor);
}
movVector *= (maxDist / sqrt(movNorm)); movVector *= (maxDist / sqrt(movNorm));
nlwarning("Player limitSpeed=%2.f, entitySpeed=%.2f, masterSpeed=%.2f", limitSpeedToUse, maxSpeed(), mountWalkSpeed);
}
else
{
nlwarning("Player limitSpeed=%2.f, entitySpeed=%.2f, masterSpeed=%.2f", limitSpeedToUse, maxSpeed(), mountWalkSpeed);
}
} }
} }
@ -2268,9 +2274,9 @@ void CWorldPositionManager::movePlayer(CWorldEntity *entity, sint32 x, sint32 y,
if (diff2d.sqrnorm() > 1.0 ) if (diff2d.sqrnorm() > 1.0 )
{ {
correctPos = true; correctPos = true;
if (VerboseSpeedAbuse) if (true/*VerboseSpeedAbuse*/)
{ {
nlwarning("CWorldPositionManager::movePlayer%s: corrected position: real=(%.1f,%.1f) targeted=(%.1f,%.1f)", master->Id.toString().c_str(), finalPos.x, finalPos.y, targetPos.x, targetPos.y); nlwarning("PlayerAbuse %s real=(%.1f,%.1f) targeted=(%.1f,%.1f)", master->Id.toString().c_str(), finalPos.x, finalPos.y, targetPos.x, targetPos.y);
} }
} }

View file

@ -1580,6 +1580,14 @@ string CMissionData::genPreRequisites()
ret += NL; ret += NL;
} }
} }
if (!_ReqCharacterAge.empty())
{
ret += "req_character_age : "+_ReqCharacterAge+NL;
}
if (!_ReqMaxPlayerID.empty())
{
ret += "req_max_player_id : "+_ReqMaxPlayerID+NL;
}
if (!_ReqSeason.empty()) if (!_ReqSeason.empty())
{ {
ret += "req_season : "+_ReqSeason+NL; ret += "req_season : "+_ReqSeason+NL;
@ -2019,6 +2027,10 @@ void CMissionData::parsePrerequisites(NLLIGO::IPrimitive *prim)
_ReqGrade = getProperty(prim, "require_guild_grade", true, false); _ReqGrade = getProperty(prim, "require_guild_grade", true, false);
// team size // team size
_ReqTeamSize = getProperty(prim, "require_team_size", true, false); _ReqTeamSize = getProperty(prim, "require_team_size", true, false);
// character minimum age
_ReqCharacterAge = getProperty(prim, "require_character_age", true, false);
// maximum player ID
_ReqMaxPlayerID = getProperty(prim, "require_max_player_id", true, false);
// brick // brick
vs = getPropertyArray(prim, "require_brick_knowledge", true, false); vs = getPropertyArray(prim, "require_brick_knowledge", true, false);
for (uint i=0; i<vs.size(); ++i) for (uint i=0; i<vs.size(); ++i)

View file

@ -388,6 +388,8 @@ private:
std::string _ReqGrade; std::string _ReqGrade;
std::string _ReqTeamSize; std::string _ReqTeamSize;
std::vector<std::string> _ReqBrick; std::vector<std::string> _ReqBrick;
std::string _ReqCharacterAge;
std::string _ReqMaxPlayerID;
std::string _ReqSeason; std::string _ReqSeason;
// bool _ReqEncycloTasksDone; // bool _ReqEncycloTasksDone;
std::string _ReqEncyclo; std::string _ReqEncyclo;

View file

@ -1844,6 +1844,13 @@ struct TKillRaceInfo
TCompilerVarName Quantity; TCompilerVarName Quantity;
}; };
struct TKillPlayerInfo
{
TCompilerVarName ClanName;
TCompilerVarName MinLevel;
TCompilerVarName MaxLevel;
TCompilerVarName Quantity;
};
class CContentKill : public CContentObjective class CContentKill : public CContentObjective
{ {
@ -1856,6 +1863,7 @@ class CContentKill : public CContentObjective
TCompilerVarName _KillFactionName; TCompilerVarName _KillFactionName;
TCompilerVarName _KillFactionQuantity; TCompilerVarName _KillFactionQuantity;
vector<string> _PredefVarName; vector<string> _PredefVarName;
vector<TKillPlayerInfo> _KillPlayers;
TCompilerVarName _Place; TCompilerVarName _Place;
@ -1924,7 +1932,22 @@ class CContentKill : public CContentObjective
predef[0].resize(2); predef[0].resize(2);
predef[0][0] = _KillFactionName; predef[0][0] = _KillFactionName;
predef[0][1] = _KillFactionQuantity; predef[0][1] = _KillFactionQuantity;
}
else if(!_KillPlayers.empty())
{
numEntry = _KillPlayers.size();
predef.resize(numEntry);
for (uint i=0; i<numEntry; ++i)
{
predef[i].resize(4*(i+1));
for (uint j=0; j<i+1; ++j)
{
predef[i][j*4] = _KillPlayers[j].ClanName;
predef[i][j*4+1] = _KillPlayers[j].MinLevel;
predef[i][j*4+2] = _KillPlayers[j].MaxLevel;
predef[i][j*4+3] = _KillPlayers[j].Quantity;
}
}
} }
// add optional place // add optional place
@ -1995,6 +2018,33 @@ public:
npcname.initWithText(toString("npc%u", i+1), STRING_MANAGER::bot, md, prim, vs[i]); npcname.initWithText(toString("npc%u", i+1), STRING_MANAGER::bot, md, prim, vs[i]);
_KillNpcs.push_back(npcname); _KillNpcs.push_back(npcname);
} }
vs = md.getPropertyArray(prim, "clan_name/min_level/max_level/quantity", true, false);
for (uint i=0; i<vs.size(); ++i)
{
vector<string> args;
explode(vs[i], string(" "), args, true);
if (args.size() != 4)
{
string err = toString("Invalid player clan infos in '%s', need <clan_name> <min_level> <max_level> <quantity>", vs[i].c_str());
throw EParseException(prim, err.c_str());
}
if (atoi(args[1].c_str()) >= atoi(args[2].c_str()))
{
string err = toString("Invalid player clan infos in '%s', need <min_level> lower than <max_level>", vs[i].c_str());
throw EParseException(prim, err.c_str());
}
if (atoi(args[3].c_str()) <= 0)
{
string err = toString("Invalid player clan infos in '%s', need <quantity> upper than 0", vs[i].c_str());
throw EParseException(prim, err.c_str());
}
TKillPlayerInfo kp;
kp.ClanName.initWithText(toString("clan%u", i+1), STRING_MANAGER::clan, md, prim, args[0]);
kp.MinLevel.initWithText(toString("minlvl%u", i+1), STRING_MANAGER::integer, md, prim, args[1]);
kp.MaxLevel.initWithText(toString("maxlvl%u", i+1), STRING_MANAGER::integer, md, prim, args[2]);
kp.Quantity.initWithText(toString("quantity%u", i+1), STRING_MANAGER::integer, md, prim, args[3]);
_KillPlayers.push_back(kp);
}
s = md.getProperty(prim, "npc_by_name/quantity", false, false); s = md.getProperty(prim, "npc_by_name/quantity", false, false);
if (!s.empty()) if (!s.empty())
@ -2058,6 +2108,12 @@ public:
throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); throw EParseException(prim, "Merging of multiple kill mode is forbidden !");
check = true; check = true;
} }
if (!_KillPlayers.empty())
{
if (check)
throw EParseException(prim, "Merging of multiple kill mode is forbidden !");
check = true;
}
_Place.init("p", STRING_MANAGER::place, md, prim, "place"); _Place.init("p", STRING_MANAGER::place, md, prim, "place");
@ -2117,6 +2173,16 @@ public:
{ {
ret += "kill_faction : "+_KillFactionName+" "+_KillFactionQuantity; ret += "kill_faction : "+_KillFactionName+" "+_KillFactionQuantity;
} }
else if (!_KillPlayers.empty())
{
ret += "kill_player : ";
for (uint i=0; i<_KillPlayers.size(); ++i)
{
ret += _KillPlayers[i].ClanName+" "+_KillPlayers[i].MinLevel+" "+_KillPlayers[i].MaxLevel+" "+_KillPlayers[i].Quantity;
if (i < _KillPlayers.size()-1)
{ret += "; ";}
}
}
if (!_Place.empty()) if (!_Place.empty())
ret += " : "+_Place; ret += " : "+_Place;
@ -2130,6 +2196,30 @@ public:
}; };
REGISTER_STEP_CONTENT(CContentKill, "kill"); REGISTER_STEP_CONTENT(CContentKill, "kill");
/*
class CContentKillFamedPlayer : public CContentObjective
{
vector<TKillFamedPlayerInfo> _Clans;
virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef)
{
numEntry = _Clans.size();
predef.resize(numEntry);
for (uint i=0; i<numEntry; ++i)
{
predef[i].resize(4*(i+1));
for (uint j=0; j<i+1; ++j)
{
predef[i][j*4] = _Clans[j].ClanName;
predef[i][j*4+1] = _Clans[j].MinLevel;
predef[i][j*4+2] = _Clans[j].MaxLevel;
predef[i][j*4+3] = _Clans[j].Quantity;
}
}
}
*/
class CContentTalkTo : public CContentObjective class CContentTalkTo : public CContentObjective
{ {
TCompilerVarName _BotName; TCompilerVarName _BotName;