Changed: Synchronization with SVN

This commit is contained in:
kervala 2012-09-11 21:39:30 +02:00
parent 8922f96b9a
commit eea1360021
43 changed files with 898 additions and 255 deletions

View file

@ -345,6 +345,23 @@ void CSpawnBot::sheetChanged()
// CMirrors::initSheet(dataSetRow(), getPersistent().getSheet()->SheetId()); // CMirrors::initSheet(dataSetRow(), getPersistent().getSheet()->SheetId());
} }
void CSpawnBot::sendInfoToEGS() const
{
if (!EGSHasMirrorReady)
return;
const uint32& maxHp = getPersistent().getCustomMaxHp();
if (maxHp > 0.f)
{
CChangeCreatureMaxHPMsg& msgList = CAIS::instance().getCreatureChangeMaxHP();
msgList.Entities.push_back(dataSetRow());
msgList.MaxHp.push_back((uint32)(maxHp));
msgList.SetFull.push_back((uint8)(1));
}
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// CBot // // CBot //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -359,6 +376,7 @@ CBot::CBot(CGroup* owner, CAIAliasDescriptionNode* alias)
, _SetSheetData(NULL) , _SetSheetData(NULL)
, _Observers(NULL) , _Observers(NULL)
, _ProfileData(NULL) , _ProfileData(NULL)
, _CustomMaxHp(0)
{ {
} }
@ -372,6 +390,7 @@ CBot::CBot(CGroup* owner, uint32 alias, std::string const& name)
, _SetSheetData(NULL) , _SetSheetData(NULL)
, _Observers(NULL) , _Observers(NULL)
, _ProfileData(NULL) , _ProfileData(NULL)
, _CustomMaxHp(0.f)
{ {
} }

View file

@ -69,7 +69,7 @@ public:
virtual void setTheta(CAngle theta); virtual void setTheta(CAngle theta);
virtual void sendInfoToEGS() const = 0; virtual void sendInfoToEGS() const;
CBot& getPersistent() const; CBot& getPersistent() const;
@ -244,6 +244,9 @@ public:
const ucstring& getCustomName() const { return _CustomName; } const ucstring& getCustomName() const { return _CustomName; }
void setCustomName(const ucstring &name) { _CustomName = name; } void setCustomName(const ucstring &name) { _CustomName = name; }
const uint32& getCustomMaxHp() const { return _CustomMaxHp; }
void setCustomMaxHp(const uint32 &maxHp) { _CustomMaxHp = maxHp; }
virtual void setClientSheet(const std::string & clientSheetName); virtual void setClientSheet(const std::string & clientSheetName);
// Can be redefine by NpcGroup in case of a BotNpc with a fauna sheet but that we don't want the name to ignore // Can be redefine by NpcGroup in case of a BotNpc with a fauna sheet but that we don't want the name to ignore
@ -273,6 +276,7 @@ private:
bool _Healer; bool _Healer;
bool _BuildingBot; bool _BuildingBot;
ucstring _CustomName; ucstring _CustomName;
uint32 _CustomMaxHp;
CTimer _SetSheetTimer; CTimer _SetSheetTimer;
struct CSetSheetData struct CSetSheetData
{ {

View file

@ -62,6 +62,8 @@ void CSpawnBotNpc::sendInfoToEGS() const
if (!EGSHasMirrorReady) if (!EGSHasMirrorReady)
return; return;
CSpawnBot::sendInfoToEGS();
TGenNpcDescMsgImp msg; TGenNpcDescMsgImp msg;
msg.setEntityIndex(dataSetRow()); msg.setEntityIndex(dataSetRow());

View file

@ -1113,6 +1113,29 @@ void CGroupNpc::setOutpostSide(OUTPOSTENUMS::TPVPSide side)
} }
} }
void CGroupNpc::setOutpostFactions(OUTPOSTENUMS::TPVPSide side)
{
// Attack only the declared ennemies of the outpost
if (side == OUTPOSTENUMS::OutpostOwner)
{
// Bots factions
faction ().addProperty(NLMISC::toString("outpost:%s:bot_defender", getAliasString().c_str()));
friendFaction().addProperty(NLMISC::toString("outpost:%s:bot_defender", getAliasString().c_str()));
ennemyFaction().addProperty(NLMISC::toString("outpost:%s:bot_attacker", getAliasString().c_str()));
// Players faction
ennemyFaction().addProperty(NLMISC::toString("outpost:%s:attacker", getAliasString().c_str()));
}
if (side == OUTPOSTENUMS::OutpostAttacker)
{
// Bots factions
faction ().addProperty(NLMISC::toString("outpost:%s:bot_attacker", getAliasString().c_str()));
friendFaction().addProperty(NLMISC::toString("outpost:%s:bot_attacker", getAliasString().c_str()));
ennemyFaction().addProperty(NLMISC::toString("outpost:%s:bot_defender", getAliasString().c_str()));
// Players faction
ennemyFaction().addProperty(NLMISC::toString("outpost:%s:defender", getAliasString().c_str()));
}
}
void CGroupNpc::setFactionAttackableAbove(std::string faction, sint32 threshold, bool botAttackable) void CGroupNpc::setFactionAttackableAbove(std::string faction, sint32 threshold, bool botAttackable)
{ {
if (botAttackable) if (botAttackable)

View file

@ -231,6 +231,7 @@ public:
void setColour(uint8 colour); void setColour(uint8 colour);
void setOutpostSide(OUTPOSTENUMS::TPVPSide side); void setOutpostSide(OUTPOSTENUMS::TPVPSide side);
void setOutpostFactions(OUTPOSTENUMS::TPVPSide side);
bool isRingGrp() const { return _RingGrp;} bool isRingGrp() const { return _RingGrp;}
private: private:

View file

@ -870,25 +870,8 @@ void COutpost::createSquad(CGroupDesc<COutpostSquadFamily> const* groupDesc, COu
}*/ }*/
grp->setOutpostSide(side); grp->setOutpostSide(side);
// Attack only the declared ennemies of the outpost grp->setOutpostFactions(side);
if (side==OUTPOSTENUMS::OutpostOwner)
{
// 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)
{
// 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; grp->_AggroRange = 25;
grp->_UpdateNbTicks = 10; grp->_UpdateNbTicks = 10;
grp->respawnTime() = respawTimeGC; grp->respawnTime() = respawTimeGC;

View file

@ -1522,11 +1522,14 @@ void setMaxHP_ff_(CStateInstance* entity, CScriptStack& stack)
if (!bot->isSpawned()) if (!bot->isSpawned())
continue; continue;
CSpawnBot* const sbot = bot->getSpawnObj(); if (maxHp > 0)
{
msgList.Entities.push_back(sbot->dataSetRow()); CSpawnBot* const sbot = bot->getSpawnObj();
msgList.MaxHp.push_back((uint32)(maxHp)); msgList.Entities.push_back(sbot->dataSetRow());
msgList.SetFull.push_back((uint8)(setFull?1:0)); msgList.MaxHp.push_back((uint32)(maxHp));
msgList.SetFull.push_back((uint8)(setFull?1:0));
}
bot->setCustomMaxHp((uint32)maxHp);
} }
} }

View file

@ -124,6 +124,51 @@ void setFactionProp_ss_(CStateInstance* entity, CScriptStack& stack)
} }
} }
void setOupostMode_ss_(CStateInstance* entity, CScriptStack& stack)
{
std::string sideStr = stack.top(); stack.pop();
std::string aliasStr = stack.top();
CGroupNpc* const npcGroup = dynamic_cast<CGroupNpc*>(entity->getGroup());
if ( ! npcGroup)
{
nlwarning("setOutpostMode on a non Npc Group, doesnt work");
return;
}
OUTPOSTENUMS::TPVPSide side;
if (sideStr == "attacker")
{
side = OUTPOSTENUMS::OutpostAttacker;
}
else if (sideStr == "owner")
{
side = OUTPOSTENUMS::OutpostOwner;
}
else
{
nlwarning("setOutpostMode: invalid side");
}
npcGroup->setOutpostSide(side);
npcGroup->setOutpostFactions(side);
FOREACH(botIt, CCont<CBot>, npcGroup->bots())
{
CBot* bot = *botIt;
CBotNpc* botNpc = NLMISC::safe_cast<CBotNpc*>(bot);
if (botNpc)
{
CSpawnBotNpc* spawnBotNpc = botNpc->getSpawn();
if (spawnBotNpc)
{
spawnBotNpc->setOutpostSide(side);
spawnBotNpc->setOutpostAlias(LigoConfig.aliasFromString(aliasStr));
}
}
}
if (npcGroup->isSpawned())
npcGroup->getSpawnObj()->sendInfoToEGS();
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** @page code /** @page code
@ -2749,6 +2794,7 @@ std::map<std::string, FScrptNativeFunc> nfGetNpcGroupNativeFunctions()
#define REGISTER_NATIVE_FUNC(cont, func) cont.insert(std::make_pair(std::string(#func), &func)) #define REGISTER_NATIVE_FUNC(cont, func) cont.insert(std::make_pair(std::string(#func), &func))
REGISTER_NATIVE_FUNC(functions, setFactionProp_ss_); REGISTER_NATIVE_FUNC(functions, setFactionProp_ss_);
REGISTER_NATIVE_FUNC(functions, setOupostMode_ss_);
REGISTER_NATIVE_FUNC(functions, moveToZone_ss_); REGISTER_NATIVE_FUNC(functions, moveToZone_ss_);
REGISTER_NATIVE_FUNC(functions, setActivity_s_); REGISTER_NATIVE_FUNC(functions, setActivity_s_);
REGISTER_NATIVE_FUNC(functions, startWander_f_); REGISTER_NATIVE_FUNC(functions, startWander_f_);

View file

@ -831,10 +831,9 @@ void TGenNpcDescMsgImp::setChat(const CNpcChatProfileImp& chatProfile)
_ContextOptions = chatProfile.getContextOptions(); _ContextOptions = chatProfile.getContextOptions();
// ContextOptionsTitles = chatProfile.getContextOptionsTitles(); // ContextOptionsTitles = chatProfile.getContextOptionsTitles();
// ContextOptionsDetails = chatProfile.getContextOptionsDetails(); // ContextOptionsDetails = chatProfile.getContextOptionsDetails();
// As I don't remembre why I did an insert instead of an affectation I let it commented here.
// vector<string> const& chatOptionalProperties = chatProfile.getOptionalProperties(); vector<string> const& chatOptionalProperties = chatProfile.getOptionalProperties();
// OptionalProperties.insert(OptionalProperties.end(), chatOptionalProperties.begin(), chatOptionalProperties.end()); _OptionalProperties.insert(_OptionalProperties.end(), chatOptionalProperties.begin(), chatOptionalProperties.end());
_OptionalProperties = chatProfile.getOptionalProperties();
_Outpost = chatProfile.getOutpost(); _Outpost = chatProfile.getOutpost();
_Organization = chatProfile.getOrganization(); _Organization = chatProfile.getOrganization();

View file

@ -431,6 +431,15 @@ IFileAccess::TReturnCode CWriteFile::execute(CFileAccessManager& manager)
return MinorFailure; return MinorFailure;
} }
NLMISC::COFile flog;
std::string str = getBackupFileName(Filename)+"\n";
if(str.find("characters")!=std::string::npos)
{
flog.open(getBackupFileName("new_save.txt"), true);
flog.serialBuffer((uint8*)&(str[0]), str.size());
flog.close();
}
return Success; return Success;
} }

View file

@ -49,6 +49,7 @@
#include "game_share/outpost.h" #include "game_share/outpost.h"
#include "game_share/visual_slot_manager.h" #include "game_share/visual_slot_manager.h"
#include "game_share/shard_names.h" #include "game_share/shard_names.h"
#include "game_share/http_client.h"
#include "server_share/log_command_gen.h" #include "server_share/log_command_gen.h"
#include "server_share/r2_vision.h" #include "server_share/r2_vision.h"
@ -180,8 +181,9 @@ AdminCommandsInit[] =
"validateRespawnPoint", true, "validateRespawnPoint", true,
"summonPet", true, "summonPet", true,
"connectUserChannel", true, "connectUserChannel", true,
"updateTarget", true, "updateTarget", true,
"resetName", true, "resetName", true,
"showOnline", true,
// Web commands managment // Web commands managment
"webExecCommand", true, "webExecCommand", true,
@ -212,7 +214,7 @@ AdminCommandsInit[] =
"learnBrick", true, "learnBrick", true,
"unlearnBrick", true, "unlearnBrick", true,
"learnPhrase", true, "learnPhrase", true,
"learnAllForagePhrases", true, "learnAllForagePhrases", true,
"learnAllFaberPlans", true, "learnAllFaberPlans", true,
"logXpGain", true, "logXpGain", true,
"memorizePhrase", true, "memorizePhrase", true,
@ -312,7 +314,7 @@ AdminCommandsInit[] =
"setGuildChargePoint", false, "setGuildChargePoint", false,
"characterInventoryDump", true, "characterInventoryDump", true,
"deleteInventoryItem", true, "deleteInventoryItem", true,
"setSimplePhrase", false, "setSimplePhrase", false,
// PUT HERE THE VARIABLE / COMMAND THAT ARE TEMPORARY // PUT HERE THE VARIABLE / COMMAND THAT ARE TEMPORARY
// remove when message of the day interface is ready // remove when message of the day interface is ready
@ -323,8 +325,8 @@ AdminCommandsInit[] =
"EntitiesNoActionFailure", false, "EntitiesNoActionFailure", false,
"EntitiesNoCastBreak", false, "EntitiesNoCastBreak", false,
"EntitiesNoResist", false, "EntitiesNoResist", false,
"lockItem", true, "lockItem", true,
"setTeamLeader", true, "setTeamLeader", true,
// aggroable state // aggroable state
"Aggro", true, "Aggro", true,
@ -388,7 +390,7 @@ AdminCommandsInit[] =
"eventSetBotURLName", true, "eventSetBotURLName", true,
"eventSpawnToxic", true, "eventSpawnToxic", true,
"eventNpcSay", true, "eventNpcSay", true,
"eventSetBotFacing", true, "eventSetBotFacing", true,
"eventGiveControl", true, "eventGiveControl", true,
"eventLeaveControl", true, "eventLeaveControl", true,
@ -422,7 +424,7 @@ bool getAIInstanceFromGroupName(string& groupName, uint32& instanceNumber)
return false; return false;
} }
instanceNumber = nr; instanceNumber = nr;
groupName = groupName.substr(groupName.find('@'), groupName.size()); groupName = groupName.substr(groupName.find('@') + 1, groupName.size());
} }
return true; return true;
} }
@ -460,6 +462,7 @@ void initAdmin ()
cmd.Name = AdminCommandsInit[i].Name; cmd.Name = AdminCommandsInit[i].Name;
cmd.AddEId = AdminCommandsInit[i].AddEId; cmd.AddEId = AdminCommandsInit[i].AddEId;
cmd.Priv = DefaultPriv; cmd.Priv = DefaultPriv;
cmd.Audit = false;
AdminCommands.push_back(cmd); AdminCommands.push_back(cmd);
} }
@ -525,9 +528,9 @@ static void loadCommandsPrivileges(const string & fileName, bool init)
CSString fullLine = line; CSString fullLine = line;
// only extract the first 2 params // only extract the first 4 params
CVectorSString params; CVectorSString params;
for (uint i = 0; !line.empty() && i < 2; i++) for (uint i = 0; !line.empty() && i < 4; i++)
{ {
string param = line.strtok(" \t"); string param = line.strtok(" \t");
if (param.empty()) if (param.empty())
@ -546,7 +549,7 @@ static void loadCommandsPrivileges(const string & fileName, bool init)
{ {
// this is a forward // this is a forward
} }
else if (params.size() > 2) else if (params.size() > 3)
{ {
nlwarning("ADMIN: invalid entry: '%s'.", fullLine.c_str()); nlwarning("ADMIN: invalid entry: '%s'.", fullLine.c_str());
continue; continue;
@ -563,15 +566,23 @@ static void loadCommandsPrivileges(const string & fileName, bool init)
params.push_back(""); params.push_back("");
} }
if (params.size() < 4)
{
// no audit specified
params.push_back("");
}
const string & cmdName = params[0]; const string & cmdName = params[0];
const string & forward = params[1]; const string & forward = params[1];
const string & cmdPriv = params[2]; const string & cmdPriv = params[2];
const bool & audit = (params[3] == "audit");
CAdminCommand * cmd = findAdminCommand(cmdName); CAdminCommand * cmd = findAdminCommand(cmdName);
if (cmd) if (cmd)
{ {
cmd->Priv = cmdPriv; cmd->Priv = cmdPriv;
cmd->ForwardToservice = forward.substr(1, forward.size()-2); cmd->ForwardToservice = forward.substr(1, forward.size()-2);
cmd->Audit = audit;
nlinfo("ADMIN: command '%s' forwarded to [%s] has new privileges '%s'.", cmdName.c_str(), cmd->ForwardToservice.c_str(), cmdPriv.c_str()); nlinfo("ADMIN: command '%s' forwarded to [%s] has new privileges '%s'.", cmdName.c_str(), cmd->ForwardToservice.c_str(), cmdPriv.c_str());
} }
else else
@ -2376,16 +2387,18 @@ NLMISC_COMMAND(getPetAnimalSatiety,"Get the satiety of pet animal (petIndex in 0
return true; return true;
} }
NLMISC_COMMAND(setPetAnimalName, "Set the name of a pet animal (petIndex in 0..3)","<eid> <petIndex> <name>") NLMISC_COMMAND(setPetAnimalName, "Set the name of a pet animal","<eid> <petIndex (0..3)> [<name>]")
{ {
if (args.size () < 3) return false; if (args.size () < 2) return false;
GET_CHARACTER GET_CHARACTER
if ( c ) if ( c )
{ {
uint petIndex; uint petIndex;
fromString(args[1], petIndex); fromString(args[1], petIndex);
ucstring customName = args[2]; ucstring customName;
if (args.size () == 3)
customName = args[2];
c->setAnimalName(petIndex, customName); c->setAnimalName(petIndex, customName);
} }
@ -2932,6 +2945,29 @@ NLMISC_DYNVARIABLE (uint32, RyzomDate, "Current ryzom date")
// //
// //
// //
void audit(const CAdminCommand *cmd, const string &rawCommand, const CEntityId &eid, const string &name, const string &targetName)
{
if (cmd == NULL)
return;
CConfigFile::CVar *varHost = IService::getInstance()->ConfigFile.getVarPtr("AdminCommandAuditHost");
CConfigFile::CVar *varPage = IService::getInstance()->ConfigFile.getVarPtr("AdminCommandAuditPage");
if (varHost == NULL || varPage == NULL)
return;
string host = varHost->asString();
string page = varPage->asString();
if (host == "" || page == "")
return;
char params[1024];
sprintf(params, "action=audit&cmd=%s&raw=%s&name=(%s,%s)&target=%s", cmd->Name.c_str(), rawCommand.c_str(), eid.toString().c_str(), name.c_str(), targetName.c_str());
IThread *thread = IThread::create(new CHttpPostTask(host, page, params));
thread->start();
}
// all admin /a /b commands executed by the client go in this callback // all admin /a /b commands executed by the client go in this callback
void cbClientAdmin (NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId) void cbClientAdmin (NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId)
@ -3062,6 +3098,8 @@ void cbClientAdmin (NLNET::CMessage& msgin, const std::string &serviceName, NLNE
res = (string)cs_res; res = (string)cs_res;
nlinfo ("ADMIN: Player (%s,%s) will execute client admin command '%s' on target %s", eid.toString().c_str(), csName.c_str(), res.c_str(), targetName.c_str()); nlinfo ("ADMIN: Player (%s,%s) will execute client admin command '%s' on target %s", eid.toString().c_str(), csName.c_str(), res.c_str(), targetName.c_str());
audit(cmd, res, eid, csName, targetName);
CLightMemDisplayer *CmdDisplayer = new CLightMemDisplayer("CmdDisplayer"); CLightMemDisplayer *CmdDisplayer = new CLightMemDisplayer("CmdDisplayer");
CLog *CmdLogger = new CLog( CLog::LOG_NO ); CLog *CmdLogger = new CLog( CLog::LOG_NO );
CmdLogger->addDisplayer( CmdDisplayer ); CmdLogger->addDisplayer( CmdDisplayer );
@ -3585,8 +3623,11 @@ NLMISC_COMMAND( killMob, "kill a mob ( /a killMob )", "<CSR eId>" )
} }
if ( !creature->getContextualProperty().directAccessForStructMembers().attackable() ) if ( !creature->getContextualProperty().directAccessForStructMembers().attackable() )
{ {
CCharacter::sendDynamicSystemMessage( eid, "CSR_NOT_ATTACKABLE" ); if ( ! creature->checkFactionAttackable(c->getId()))
return true; {
CCharacter::sendDynamicSystemMessage( eid, "CSR_NOT_ATTACKABLE" );
return true;
}
} }
creature->getScores()._PhysicalScores[SCORES::hit_points].Current = 0; creature->getScores()._PhysicalScores[SCORES::hit_points].Current = 0;
return true; return true;
@ -5442,35 +5483,148 @@ NLMISC_COMMAND (webExecCommand, "Execute a web command", "<user id> <web_app_url
//***************** teleport //***************** teleport
//************************************************* //*************************************************
else if (command_args[0] == "teleport") else if (command_args[0] == "teleport") // teleport![x,y,z|player name|bot name]!teleport mektoub?!check pvpflag?
{ {
// args: x y z [t] if (command_args.size () < 2) return false;
if (command_args.size () < 4 ||
command_args.size () > 5 ) return false;
sint32 x; bool pvpValid = (c->getPvPRecentActionFlag() == false || c->getPVPFlag() == false);
sint32 y; if (command_args.size () > 3 && command_args[3] == "1" && !pvpValid)
sint32 z;
float t;
fromString(command_args[1], x);
fromString(command_args[2], y);
fromString(command_args[3], z);
if (command_args.size() > 4)
{ {
fromString(command_args[4], t); CCharacter::sendDynamicSystemMessage(c->getEntityRowId(), "PVP_TP_FORBIDEN");
return true;
}
string value = command_args[1];
vector<string> res;
sint32 x = 0, y = 0, z = 0;
float h = 0;
if ( value.find(',') != string::npos ) // Position x,y,z,a
{
explode (value, string(","), res);
if (res.size() >= 2)
{
fromString(res[0], x);
x *= 1000;
fromString(res[1], y);
y *= 1000;
}
if (res.size() >= 3)
{
fromString(res[2], z);
z *= 1000;
}
if (res.size() >= 4)
fromString(res[3], h);
} }
else else
{ {
t = c->getState().Heading; if ( value.find(".creature") != string::npos )
{
CSheetId creatureSheetId(value);
if( creatureSheetId != CSheetId::Unknown )
{
double minDistance = -1.;
CCreature * creature = NULL;
TMapCreatures::const_iterator it;
const TMapCreatures& creatures = CreatureManager.getCreature();
for( it = creatures.begin(); it != creatures.end(); ++it )
{
CSheetId sheetId = (*it).second->getType();
if( sheetId == creatureSheetId )
{
double distance = PHRASE_UTILITIES::getDistance( c->getEntityRowId(), (*it).second->getEntityRowId() );
if( !creature || (creature && distance < minDistance) )
{
creature = (*it).second;
minDistance = distance;
}
}
}
if( creature )
{
x = creature->getState().X();
y = creature->getState().Y();
z = creature->getState().Z();
h = creature->getState().Heading();
}
}
else
{
nlwarning ("<Position> '%s' is an invalid creature", value.c_str());
}
}
else
{
CEntityBase *entityBase = PlayerManager.getCharacterByName (CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), value));
if (entityBase == 0)
{
// try to find the bot name
vector<TAIAlias> aliases;
CAIAliasTranslator::getInstance()->getNPCAliasesFromName( value, aliases );
if ( aliases.empty() )
{
nldebug ("<Position> Ignoring attempt to teleport because no NPC found matching name '%s'", value.c_str());
return true;
}
TAIAlias alias = aliases[0];
const CEntityId & botId = CAIAliasTranslator::getInstance()->getEntityId (alias);
if ( botId != CEntityId::Unknown )
{
entityBase = CreatureManager.getCreature (botId);
}
else
{
nlwarning ("'%s' has no eId. Is it Spawned???", value.c_str());
return true;
}
}
if (entityBase != 0)
{
x = entityBase->getState().X + sint32 (cos (entityBase->getState ().Heading) * 2000);
y = entityBase->getState().Y + sint32 (sin (entityBase->getState ().Heading) * 2000);
z = entityBase->getState().Z;
h = entityBase->getState().Heading;
}
}
} }
NLNET::CMessage msgout( "TELEPORT_PLAYER" ); if (x == 0 && y == 0 && z == 0)
msgout.serial( const_cast<CEntityId &>(c->getId()) ); {
msgout.serial( const_cast<sint32 &>(x) ); nlwarning ("'%s' is a bad value for position, don't change position", value.c_str());
msgout.serial( const_cast<sint32 &>(y) ); return true;
msgout.serial( const_cast<sint32 &>(z) ); }
msgout.serial( const_cast<float &>(t) );
sendMessageViaMirror( "EGS", msgout ); CContinent * cont = CZoneManager::getInstance().getContinent(x,y);
bool allowPetTp = false;
if (command_args.size () == 3 && command_args[2] == "1")
allowPetTp = true;
if (allowPetTp)
c->allowNearPetTp();
else
c->forbidNearPetTp();
// Respawn player if dead
if (c->isDead())
{
PROGRESSIONPVP::CCharacterProgressionPVP::getInstance()->playerRespawn(c);
// apply respawn effects because user is dead
c->applyRespawnEffects();
}
c->teleportCharacter(x,y,z,allowPetTp,true,h);
if ( cont )
{
c->getRespawnPoints().addDefaultRespawnPoint( CONTINENT::TContinent(cont->getId()) );
}
} }
//************************************************* //*************************************************
@ -8434,6 +8588,21 @@ NLMISC_COMMAND (resetName, "Reset your name; undo a temporary rename", "<user id
return true; return true;
} }
//----------------------------------------------------------------------------
NLMISC_COMMAND(showOnline, "Set friend visibility", "<user id> <mode=0,1,2>")
{
if (args.size() < 2) return false;
GET_CHARACTER;
uint8 mode = 0;
NLMISC::fromString(args[1], mode);
if (mode < NB_FRIEND_VISIBILITY)
{
c->setFriendVisibility((TFriendVisibility)mode);
}
return true;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
NLMISC_COMMAND (lockItem, "Lock/unlock item in inventory", "<user id> <inventory> <slot> <lock=0,1>") NLMISC_COMMAND (lockItem, "Lock/unlock item in inventory", "<user id> <inventory> <slot> <lock=0,1>")
{ {

View file

@ -34,6 +34,7 @@ struct CAdminCommand
bool AddEId; bool AddEId;
std::string Priv; std::string Priv;
std::string ForwardToservice; std::string ForwardToservice;
bool Audit;
}; };
// //

View file

@ -336,6 +336,10 @@ bool CBuildingPhysicalGuild::isUserAllowed(CCharacter * user, uint16 ownerId, ui
nlassert( user ); nlassert( user );
nlassert( ownerId < _Guilds.size() ); nlassert( ownerId < _Guilds.size() );
nlassert( roomIdx < _Template->Rooms.size() ); nlassert( roomIdx < _Template->Rooms.size() );
if (user->isDead())
return false;
CGuild * guild = CGuildManager::getInstance()->getGuildFromId( user->getGuildId() ); CGuild * guild = CGuildManager::getInstance()->getGuildFromId( user->getGuildId() );
if ( !guild ) if ( !guild )
return false; return false;
@ -530,6 +534,9 @@ bool CBuildingPhysicalPlayer::isUserAllowed(CCharacter * user, uint16 ownerId, u
nlassert(user); nlassert(user);
nlassert(ownerId < _Players.size() ); nlassert(ownerId < _Players.size() );
if (user->isDead())
return false;
CCharacter * owner = PlayerManager.getChar( _Players[ownerId] ); CCharacter * owner = PlayerManager.getChar( _Players[ownerId] );
if (owner) if (owner)
return ( (user->getId() == _Players[ownerId]) || owner->playerHaveRoomAccess(user->getId()) ); return ( (user->getId() == _Players[ownerId]) || owner->playerHaveRoomAccess(user->getId()) );

View file

@ -307,6 +307,10 @@ bool CRoomDestination::isUserAllowed(CCharacter * user,uint16 ownerIdx)
#ifdef NL_DEBUG #ifdef NL_DEBUG
nlassert(user); nlassert(user);
#endif #endif
if (user && user->isDead())
return false;
CMirrorPropValueRO<TYPE_CELL> mirrorCell( TheDataset, user->getEntityRowId(), DSPropertyCELL ); CMirrorPropValueRO<TYPE_CELL> mirrorCell( TheDataset, user->getEntityRowId(), DSPropertyCELL );
sint32 cell = mirrorCell; sint32 cell = mirrorCell;
const IRoomInstance * room = CBuildingManager::getInstance()->getRoomInstanceFromCell( cell ); const IRoomInstance * room = CBuildingManager::getInstance()->getRoomInstanceFromCell( cell );
@ -423,6 +427,9 @@ bool CExitDestination::build( const NLLIGO::IPrimitive* prim,const NLLIGO::IPrim
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool CExitDestination::isUserAllowed(CCharacter * user, uint16 ownerIdx) bool CExitDestination::isUserAllowed(CCharacter * user, uint16 ownerIdx)
{ {
if (user && user->isDead())
return false;
CMirrorPropValueRO<TYPE_CELL> mirrorCell( TheDataset, user->getEntityRowId(), DSPropertyCELL ); CMirrorPropValueRO<TYPE_CELL> mirrorCell( TheDataset, user->getEntityRowId(), DSPropertyCELL );
sint32 cell = mirrorCell; sint32 cell = mirrorCell;
const IRoomInstance * room = CBuildingManager::getInstance()->getRoomInstanceFromCell( cell ); const IRoomInstance * room = CBuildingManager::getInstance()->getRoomInstanceFromCell( cell );

View file

@ -1114,9 +1114,8 @@ void cbClientMoveInContactLists( NLNET::CMessage& msgin, const std::string &serv
if (listOrigin == 0) if (listOrigin == 0)
{ {
NLMISC::CEntityId eid= c->getFriendByContactId(contactIdOrigin); NLMISC::CEntityId eid= c->getFriendByContactId(contactIdOrigin);
// allows the whole operation or nothing if player is not present // allows the whole operation or nothing if player does not exist
CCharacter * other = PlayerManager.getChar( eid ); if (eid != CEntityId::Unknown)
if(other)
{ {
c->removePlayerFromFriendListByEntityId(eid); c->removePlayerFromFriendListByEntityId(eid);
c->addPlayerToIgnoreList(eid); c->addPlayerToIgnoreList(eid);
@ -1124,15 +1123,14 @@ void cbClientMoveInContactLists( NLNET::CMessage& msgin, const std::string &serv
else else
{ {
// player not found => message // player not found => message
PHRASE_UTILITIES::sendDynamicSystemMessage( c->getEntityRowId(), "OPERATION_OFFLINE"); PHRASE_UTILITIES::sendDynamicSystemMessage( c->getEntityRowId(), "OPERATION_NOTEXIST");
} }
} }
else else
{ {
NLMISC::CEntityId eid= c->getIgnoreByContactId(contactIdOrigin); NLMISC::CEntityId eid= c->getIgnoreByContactId(contactIdOrigin);
// allows the whole operation or nothing if player is not present // allows the whole operation or nothing if player is not present
CCharacter * other = PlayerManager.getChar( eid ); if(eid != CEntityId::Unknown)
if(other)
{ {
c->removePlayerFromIgnoreListByEntityId(eid); c->removePlayerFromIgnoreListByEntityId(eid);
c->addPlayerToFriendList(eid); c->addPlayerToFriendList(eid);
@ -1140,7 +1138,7 @@ void cbClientMoveInContactLists( NLNET::CMessage& msgin, const std::string &serv
else else
{ {
// player not found => message // player not found => message
PHRASE_UTILITIES::sendDynamicSystemMessage( c->getEntityRowId(), "OPERATION_OFFLINE"); PHRASE_UTILITIES::sendDynamicSystemMessage( c->getEntityRowId(), "OPERATION_NOTEXIST");
} }
} }
} }
@ -2544,7 +2542,7 @@ void cbClientWho( NLNET::CMessage& msgin, const std::string &serviceName, NLNET:
return; return;
} }
bool havePriv = p->havePriv(":DEV:SGM:GM:"); bool havePriv = p->havePriv(":DEV:SGM:GM:EM:");
bool hasChannel = false; bool hasChannel = false;
nbAnswers = 0; nbAnswers = 0;
@ -2578,9 +2576,10 @@ void cbClientWho( NLNET::CMessage& msgin, const std::string &serviceName, NLNET:
if (!playerNames.empty()) if (!playerNames.empty())
{ {
CCharacter::sendDynamicSystemMessage( id, "WHO_CHANNEL_INTRO" );
//playerNames = "Players in channel \"" + opt + "\":" + playerNames;
SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal); SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
params[0].Literal = opt;
CCharacter::sendDynamicSystemMessage( id, "WHO_CHANNEL_INTRO", params);
//playerNames = "Players in channel \"" + opt + "\":" + playerNames;
params[0].Literal = playerNames; params[0].Literal = playerNames;
CCharacter::sendDynamicSystemMessage( id, "LITERAL", params ); CCharacter::sendDynamicSystemMessage( id, "LITERAL", params );
return; return;

View file

@ -2060,9 +2060,9 @@ uint32 CCreature::tickUpdate()
setBars(); setBars();
} }
// test again as effects can kill the entity (dots...) // test again as effects can kill the entity (dots...)
if (isDead()) if (isDead())
{ {
deathOccurs(); deathOccurs();
} }

View file

@ -253,7 +253,7 @@ void CChangeCreatureHPImp::callback(const string &, NLNET::TServiceId sid)
//-------------------------------------------------------------- //--------------------------------------------------------------
// CChangeCreatureMaxHPImp ::callback() // CCreatureSetUrlImp ::callback()
//-------------------------------------------------------------- //--------------------------------------------------------------
void CCreatureSetUrlImp::callback(const string &, NLNET::TServiceId sid) void CCreatureSetUrlImp::callback(const string &, NLNET::TServiceId sid)
{ {

View file

@ -504,6 +504,7 @@ void cbClientReady( CMessage& msgin, const std::string &serviceName, NLNET::TSer
if (!IsRingShard && player->havePriv(AlwaysInvisiblePriv)) if (!IsRingShard && player->havePriv(AlwaysInvisiblePriv))
{ {
c->setWhoSeesMe(uint64(0)); c->setWhoSeesMe(uint64(0));
c->setInvisibility(true);
} }
TheDataset.declareEntity( entityIndex ); // after the writing of properties to mirror TheDataset.declareEntity( entityIndex ); // after the writing of properties to mirror
@ -676,8 +677,26 @@ void finalizeClientReady( uint32 userId, uint32 index )
// for GM player, trigger a 'infos' command to remember their persistent state // for GM player, trigger a 'infos' command to remember their persistent state
if (!PlayerManager.getPlayer(uint32(c->getId().getShortId())>>4)->getUserPriv().empty()) 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); {
string res = toString("infos %s", c->getId().toString().c_str()).c_str();
CLightMemDisplayer *CmdDisplayer = new CLightMemDisplayer("CmdDisplayer");
CLog *CmdLogger = new CLog( CLog::LOG_NO );
CmdLogger->addDisplayer( CmdDisplayer );
NLMISC::ICommand::execute(res, *CmdLogger, true);
const std::deque<std::string> &strs = CmdDisplayer->lockStrings ();
for (uint i = 0; i < strs.size(); i++)
{
InfoLog->displayNL("%s", trim(strs[i]).c_str());
SM_STATIC_PARAMS_1(params,STRING_MANAGER::literal);
params[0].Literal = trim(strs[i]);
CCharacter::sendDynamicSystemMessage( c->getId(), "LITERAL", params );
}
CmdDisplayer->unlockStrings();
CmdLogger->removeDisplayer (CmdDisplayer);
delete CmdDisplayer;
delete CmdLogger;
}
c->setFinalized(true); c->setFinalized(true);
} // finalizeClientReady // } // finalizeClientReady //

View file

@ -88,6 +88,13 @@ bool CExchangeView::putItemInExchange(uint32 bagSlot, uint32 exchangeSlot, uint3
if (item->getLockedByOwner()) if (item->getLockedByOwner())
return false; return false;
// You cannot exchange genesis named items
if (item->getPhraseId().find("genesis_") == 0)
{
nlwarning("Character %s tries to sell '%s'", getCharacter()->getId().toString().c_str(), item->getPhraseId().c_str() );
return false;
}
if( getCharacter()->isAnActiveXpCatalyser(item) ) if( getCharacter()->isAnActiveXpCatalyser(item) )
return false; return false;

View file

@ -953,6 +953,14 @@ void CGuild::putItem( CCharacter * user, uint32 slot, uint32 quantity, uint16 se
return; return;
} }
// You cannot exchange genesis named items
if (item->getPhraseId().find("genesis_") == 0)
{
nlwarning("Character %s tries to put in guild '%s'", user->getId().toString().c_str(), item->getPhraseId().c_str() );
CCharacter::sendDynamicSystemMessage( user->getId(),"GUILD_ITEM_CANT_BE_PUT" );
return;
}
// try to move the required quantity of the item // try to move the required quantity of the item
if ( CInventoryBase::moveItem( if ( CInventoryBase::moveItem(
user->getInventory(INVENTORIES::bag), slot, user->getInventory(INVENTORIES::bag), slot,

View file

@ -98,10 +98,29 @@ class CMissionStepTalk : public IMissionStepTemplate
uint processEvent( const TDataSetRow & userRow, const CMissionEvent & event,uint subStepIndex,const TDataSetRow & giverRow ) uint processEvent( const TDataSetRow & userRow, const CMissionEvent & event,uint subStepIndex,const TDataSetRow & giverRow )
{ {
string webAppUrl;
_User = PlayerManager.getChar(getEntityIdFromRow(userRow)); _User = PlayerManager.getChar(getEntityIdFromRow(userRow));
if (_IsDynamic && _User != NULL)
{
vector<string> params = _User->getCustomMissionParams(_Dynamic);
if (params.size() < 2)
{
LOGMISSIONSTEPERROR("talk_to : invalid npc name");
return 0;
}
else
{
webAppUrl = params[0];
}
}
// not check here : they are done befor. If a talk event comes here, the step is complete // not check here : they are done befor. If a talk event comes here, the step is complete
if( event.Type == CMissionEvent::Talk ) if( event.Type == CMissionEvent::Talk )
{ {
if (!webAppUrl.empty() && _User != NULL)
_User->validateDynamicMissionStep(webAppUrl);
LOGMISSIONSTEPSUCCESS("talk_to"); LOGMISSIONSTEPSUCCESS("talk_to");
return 1; return 1;
} }

View file

@ -29,6 +29,8 @@
#include "team_manager/team_manager.h" #include "team_manager/team_manager.h"
#include "player_manager/player_manager.h" #include "player_manager/player_manager.h"
#include "player_manager/player.h" #include "player_manager/player.h"
#include "creature_manager/creature_manager.h"
#include "creature_manager/creature.h"
#include "phrase_manager/area_effect.h" #include "phrase_manager/area_effect.h"
#include "aura_effect.h" #include "aura_effect.h"
@ -213,6 +215,15 @@ bool CAuraRootEffect::isEntityValidTarget(CEntityBase *entity, CEntityBase *crea
return true; return true;
} }
CCreature * creature = CreatureManager.getCreature( entity->getId() );
if (creature && creator)
{
if (creature->checkFactionAttackable( creator->getId() ))
{
return true;
}
}
return false; return false;
}// isEntityValidTarget // }// isEntityValidTarget //

View file

@ -28,9 +28,13 @@
#include "player_manager/character.h" #include "player_manager/character.h"
#include "player_manager/player_manager.h" #include "player_manager/player_manager.h"
#include "player_manager/player.h" #include "player_manager/player.h"
#include "creature_manager/creature_manager.h"
#include "creature_manager/creature.h"
#include "range_selector.h" #include "range_selector.h"
#include "phrase_manager/effect_factory.h" #include "phrase_manager/effect_factory.h"
extern CCreatureManager CreatureManager;
using namespace std; using namespace std;
using namespace NLMISC; using namespace NLMISC;
using namespace NLNET; using namespace NLNET;
@ -76,7 +80,7 @@ void CBounceEffect::removed()
//-------------------------------------------------------------- //--------------------------------------------------------------
// CBounceEffect::getTargetForBounce() // CBounceEffect::getTargetForBounce()
//-------------------------------------------------------------- //--------------------------------------------------------------
CEntityBase *CBounceEffect::getTargetForBounce() const CEntityBase *CBounceEffect::getTargetForBounce(CEntityBase *actor) const
{ {
// get entities around // get entities around
if (!_AffectedEntity) if (!_AffectedEntity)
@ -99,7 +103,7 @@ CEntityBase *CBounceEffect::getTargetForBounce() const
for (uint i = 0; i < entities.size() ; ++i) for (uint i = 0; i < entities.size() ; ++i)
{ {
if ( entities[i] && ( entities[i] != (CEntityBase*)(_AffectedEntity) ) && isEntityValidTarget(entities[i]) ) if ( entities[i] && ( entities[i] != (CEntityBase*)(_AffectedEntity) ) && isEntityValidTarget(entities[i], actor) )
{ {
selectedEntities.push_back(entities[i]); selectedEntities.push_back(entities[i]);
} }
@ -118,18 +122,30 @@ CEntityBase *CBounceEffect::getTargetForBounce() const
//-------------------------------------------------------------- //--------------------------------------------------------------
// CBounceEffect::isEntityValidTarget() // CBounceEffect::isEntityValidTarget()
//-------------------------------------------------------------- //--------------------------------------------------------------
bool CBounceEffect::isEntityValidTarget(CEntityBase *entity) const bool CBounceEffect::isEntityValidTarget(CEntityBase *entity, CEntityBase *actor) const
{ {
#ifdef NL_DEBUG #ifdef NL_DEBUG
nlassert(entity); nlassert(entity);
#endif #endif
if (entity->isDead())
return false;
if (entity->getId().getType() == RYZOMID::player) if (entity->getId().getType() == RYZOMID::player)
return true; return true;
if ( entity->getContextualProperty().getValue().attackable() ) if ( entity->getContextualProperty().getValue().attackable() )
return true; return true;
CCreature * creature = CreatureManager.getCreature( entity->getId() );
if (creature && actor)
{
if (creature->checkFactionAttackable( actor->getId() ))
{
return true;
}
}
return false; return false;
} // checkTargetValidity // } // checkTargetValidity //

View file

@ -61,11 +61,11 @@ public:
virtual void removed(); virtual void removed();
/// get entity on which the attack is redirected /// get entity on which the attack is redirected
CEntityBase *getTargetForBounce() const; CEntityBase *getTargetForBounce(CEntityBase *actor) const;
private: private:
/// check entity is a valid target /// check entity is a valid target
bool isEntityValidTarget(CEntityBase *entity) const; bool isEntityValidTarget(CEntityBase *entity, CEntityBase *actor) const;
private: private:
/// affected entity /// affected entity

View file

@ -4633,7 +4633,7 @@ void CCombatPhrase::applyBounceEffect(CEntityBase *actingEntity, sint32 attacker
} }
#endif #endif
CEntityBase *bounceTarget = bounceEffect->getTargetForBounce(); CEntityBase *bounceTarget = bounceEffect->getTargetForBounce(actingEntity);
if (!bounceTarget) if (!bounceTarget)
return; return;

View file

@ -28,6 +28,8 @@
#include "player_manager/character.h" #include "player_manager/character.h"
#include "player_manager/player_manager.h" #include "player_manager/player_manager.h"
#include "player_manager/player.h" #include "player_manager/player.h"
#include "creature_manager/creature_manager.h"
#include "creature_manager/creature.h"
#include "range_selector.h" #include "range_selector.h"
#include "phrase_manager/effect_factory.h" #include "phrase_manager/effect_factory.h"
@ -68,14 +70,15 @@ bool CDamageAuraEffect::update(CTimerEvent * event, bool applyEffect)
{ {
// get entities in surrouding area // get entities in surrouding area
CRangeSelector entitiesSelector; CRangeSelector entitiesSelector;
entitiesSelector.buildDisc( CEntityBaseManager::getEntityBasePtr(getCreatorRowId()), _AffectedEntity->getX(), _AffectedEntity->getY(), _AuraRadius, EntityMatrix, true ); CEntityBase * actor = CEntityBaseManager::getEntityBasePtr(getCreatorRowId());
entitiesSelector.buildDisc( actor, _AffectedEntity->getX(), _AffectedEntity->getY(), _AuraRadius, EntityMatrix, true );
// create or update effect on entities returned // create or update effect on entities returned
const vector<CEntityBase*> &entities = entitiesSelector.getEntities(); const vector<CEntityBase*> &entities = entitiesSelector.getEntities();
const uint size = (uint)entities.size(); const uint size = (uint)entities.size();
for (uint i = 0; i < size ; ++i) for (uint i = 0; i < size ; ++i)
{ {
if (entities[i] && (entities[i] != (CEntityBase*)_AffectedEntity) && isEntityValidTarget(entities[i]) ) if (entities[i] && (entities[i] != (CEntityBase*)_AffectedEntity) && isEntityValidTarget(entities[i], actor) )
{ {
CEntityBase *entity = entities[i]; CEntityBase *entity = entities[i];
@ -133,7 +136,7 @@ void CDamageAuraEffect::removed()
//-------------------------------------------------------------- //--------------------------------------------------------------
// CDamageAuraEffect::removed() // CDamageAuraEffect::removed()
//-------------------------------------------------------------- //--------------------------------------------------------------
bool CDamageAuraEffect::isEntityValidTarget(CEntityBase *entity) const bool CDamageAuraEffect::isEntityValidTarget(CEntityBase *entity, CEntityBase *actor) const
{ {
#ifdef NL_DEBUG #ifdef NL_DEBUG
nlassert(entity); nlassert(entity);
@ -153,6 +156,15 @@ bool CDamageAuraEffect::isEntityValidTarget(CEntityBase *entity) const
else else
retValue = false; retValue = false;
CCreature * creature = CreatureManager.getCreature( entity->getId() );
if (retValue == false && creature && actor)
{
if (creature->checkFactionAttackable( actor->getId() ))
{
retValue = true;
}
}
if (retValue) if (retValue)
{ {
// check entity isn't invulnerable // check entity isn't invulnerable

View file

@ -82,7 +82,7 @@ public:
private: private:
/// check entity is a valid target /// check entity is a valid target
bool isEntityValidTarget(CEntityBase *entity) const; bool isEntityValidTarget(CEntityBase *entity, CEntityBase *actor) const;
private: private:
/// cycle lenght in ticks /// cycle lenght in ticks

View file

@ -704,7 +704,7 @@ void CMagicActionBasicDamage::launch(
{ {
CBounceEffect *bounceEffect = safe_cast<CBounceEffect *> (& (*effect)); CBounceEffect *bounceEffect = safe_cast<CBounceEffect *> (& (*effect));
bool bounce = false; bool bounce = false;
CEntityBase *bounceTarget = bounceEffect->getTargetForBounce(); CEntityBase *bounceTarget = bounceEffect->getTargetForBounce(actor);
if (bounceTarget) if (bounceTarget)
{ {
bounce = true; bounce = true;

View file

@ -1547,15 +1547,21 @@ bool testOffensiveActionAllowed( const NLMISC::CEntityId &actorId, const NLMISC:
return true; return true;
else else
{ {
CEntityBase* actor = CreatureManager.getCreature( actorId ); CCreature* actor = CreatureManager.getCreature( actorId );
if (!actor) if (!actor)
return false; return false;
if (!actor->getContextualProperty().directAccessForStructMembers().attackable()) if (!actor->getContextualProperty().directAccessForStructMembers().attackable())
{ {
// actor is a guard or similar so cannot harm a player or a non attackable creature // actor is a guard or similar so cannot harm a player or a non attackable creature, unless faction attackable
if (targetId.getType() == RYZOMID::player || !target->getContextualProperty().directAccessForStructMembers().attackable()) if (targetId.getType() == RYZOMID::player || !target->getContextualProperty().directAccessForStructMembers().attackable())
{
if ( actor->checkFactionAttackable( targetId ) )
{
return true;
}
return false; return false;
}
else else
return true; return true;
} }
@ -1570,7 +1576,9 @@ bool testOffensiveActionAllowed( const NLMISC::CEntityId &actorId, const NLMISC:
} }
} }
switch ( targetId.getType() )
RYZOMID::TTypeId targetType = (RYZOMID::TTypeId)targetId.getType();
switch ( targetType )
{ {
case RYZOMID::player: case RYZOMID::player:
{ {
@ -1593,7 +1601,8 @@ bool testOffensiveActionAllowed( const NLMISC::CEntityId &actorId, const NLMISC:
case RYZOMID::mount: case RYZOMID::mount:
case RYZOMID::npc: case RYZOMID::npc:
{ {
if (actorId.getType() == RYZOMID::player) RYZOMID::TTypeId type = (RYZOMID::TTypeId)actorId.getType();
if (type == RYZOMID::player)
{ {
CCharacter* actor = PlayerManager.getChar( actorId ); CCharacter* actor = PlayerManager.getChar( actorId );
if ( ! actor ) if ( ! actor )
@ -1718,7 +1727,11 @@ bool validateSpellTarget( const TDataSetRow &actorRowId, const TDataSetRow &targ
// player can only heal other players // player can only heal other players
if ( getEntityIdFromRow(actorRowId).getType() == RYZOMID::player && target->getId().getType() != RYZOMID::player ) if ( getEntityIdFromRow(actorRowId).getType() == RYZOMID::player && target->getId().getType() != RYZOMID::player )
{ {
if (target->getContextualProperty().directAccessForStructMembers().attackable() ) CEntityBase * actor = CEntityBaseManager::getEntityBasePtr( actorRowId );
CCreature * creature = CreatureManager.getCreature( target->getId() );
bool bFactionAttackable = (actor && creature && creature->checkFactionAttackable( actor->getId()));
if (bFactionAttackable || target->getContextualProperty().directAccessForStructMembers().attackable() )
{ {
errorCode = "MAGIC_CANNOT_CAST_ON_ENEMY"; errorCode = "MAGIC_CANNOT_CAST_ON_ENEMY";
// nldebug("validateSpellTarget for entity %s returning false because %s MAGIC_CANNOT_CAST_ON_ENEMY",getEntityIdFromRow(actorRowId).toString().c_str(),TheDataset.getEntityId(targetRowId).toString().c_str()); // nldebug("validateSpellTarget for entity %s returning false because %s MAGIC_CANNOT_CAST_ON_ENEMY",getEntityIdFromRow(actorRowId).toString().c_str(),TheDataset.getEntityId(targetRowId).toString().c_str());

View file

@ -34,7 +34,7 @@
#include "player_manager/character.h" #include "player_manager/character.h"
#include "world_instances.h" #include "world_instances.h"
#include "player_manager/player.h" #include "player_manager/player.h"
#include "creature_manager/creature_manager.h"
#include "egs_sheets/egs_sheets.h" #include "egs_sheets/egs_sheets.h"
////////////// //////////////
@ -49,6 +49,7 @@ using namespace NLNET;
////////////// //////////////
extern CRandom RandomGenerator; extern CRandom RandomGenerator;
extern CPlayerManager PlayerManager; extern CPlayerManager PlayerManager;
extern CCreatureManager CreatureManager;
//-------------------------------------------------------------- //--------------------------------------------------------------
@ -130,10 +131,14 @@ bool CSpecialPowerTaunt::validate(std::string &errorCode)
} }
if (!entity->getContextualProperty().directAccessForStructMembers().attackable()) if (!entity->getContextualProperty().directAccessForStructMembers().attackable())
{ {
PHRASE_UTILITIES::sendDynamicSystemMessage(_ActorRowId, "POWER_TAUNT_TARGET_NOT_ATTACKABLE"); CCreature * creature = CreatureManager.getCreature( entity->getId() );
if ( ! creature->checkFactionAttackable(actor->getId()))
{
PHRASE_UTILITIES::sendDynamicSystemMessage(_ActorRowId, "POWER_TAUNT_TARGET_NOT_ATTACKABLE");
DEBUGLOG("<CSpecialPowerTaunt::validate> Target not attackable"); DEBUGLOG("<CSpecialPowerTaunt::validate> Target not attackable");
return false; return false;
}
} }
return true; return true;

View file

@ -596,6 +596,8 @@ CCharacter::CCharacter(): CEntityBase(false),
_CurrentParryLevel = 1; _CurrentParryLevel = 1;
_BaseParryLevel = 1; _BaseParryLevel = 1;
_BaseResistance = 1;
_SkillUsedForDodge = SKILLS::SF; _SkillUsedForDodge = SKILLS::SF;
_CurrentParrySkill = BarehandCombatSkill; _CurrentParrySkill = BarehandCombatSkill;
@ -671,6 +673,8 @@ CCharacter::CCharacter(): CEntityBase(false),
_CustomMissionsParams.clear(); _CustomMissionsParams.clear();
_FriendVisibility = VisibleToAll;
initDatabase(); initDatabase();
} // CCharacter // } // CCharacter //
@ -1414,6 +1418,7 @@ uint32 CCharacter::tickUpdate()
} }
} }
bool updatePVP = false;
{ {
H_AUTO(CharacterUpdateOutpost); H_AUTO(CharacterUpdateOutpost);
@ -1425,6 +1430,7 @@ uint32 CCharacter::tickUpdate()
{ {
stopOutpostLeavingTimer(); stopOutpostLeavingTimer();
setOutpostAlias(0); setOutpostAlias(0);
updatePVP = true;
} }
CSmartPtr<COutpost> outpost = COutpostManager::getInstance().getOutpostFromAlias( outpostAlias ); CSmartPtr<COutpost> outpost = COutpostManager::getInstance().getOutpostFromAlias( outpostAlias );
@ -1435,10 +1441,12 @@ uint32 CCharacter::tickUpdate()
{ {
stopOutpostLeavingTimer(); stopOutpostLeavingTimer();
setOutpostAlias(0); setOutpostAlias(0);
updatePVP = true;
} }
else else
{ {
outpost->fillCharacterOutpostDB(this); outpost->fillCharacterOutpostDB(this);
updatePVP = true;
} }
} }
} }
@ -1447,26 +1455,27 @@ uint32 CCharacter::tickUpdate()
{ {
H_AUTO(CharacterUpdatePVPMode); H_AUTO(CharacterUpdatePVPMode);
if (_PVPSafeLastTimeChange + 20 < CTickEventHandler::getGameCycle()) if (_PVPSafeLastTimeChange + 20 < CTickEventHandler::getGameCycle() || updatePVP)
{ {
bool update = false;
_PVPSafeLastTimeChange = CTickEventHandler::getGameCycle(); _PVPSafeLastTimeChange = CTickEventHandler::getGameCycle();
if (_PVPSafeLastTime != getSafeInPvPSafeZone()) if (_PVPSafeLastTime != getSafeInPvPSafeZone())
{ {
_PVPSafeLastTime = !_PVPSafeLastTime; _PVPSafeLastTime = !_PVPSafeLastTime;
update = true; updatePVP = true;
} }
if (_PVPInSafeZoneLastTime != CPVPManager2::getInstance()->inSafeZone(getPosition())) if (_PVPInSafeZoneLastTime != CPVPManager2::getInstance()->inSafeZone(getPosition()))
{ {
_PVPInSafeZoneLastTime = !_PVPInSafeZoneLastTime; _PVPInSafeZoneLastTime = !_PVPInSafeZoneLastTime;
update = true; updatePVP = true;
} }
if (update) { if (updatePVP)
{
CPVPManager2::getInstance()->setPVPModeInMirror(this); CPVPManager2::getInstance()->setPVPModeInMirror(this);
updatePVPClanVP(); updatePVPClanVP();
_HaveToUpdatePVPMode = false;
} }
} }
@ -1484,7 +1493,7 @@ uint32 CCharacter::tickUpdate()
if( getPvPRecentActionFlag() == false ) if( getPvPRecentActionFlag() == false )
{ {
CMirrorPropValue<TYPE_PVP_MODE> propPvpMode( TheDataset, TheDataset.getDataSetRow(_Id), DSPropertyPVP_MODE ); CMirrorPropValue<TYPE_EVENT_FACTION_ID> propPvpMode( TheDataset, TheDataset.getDataSetRow(_Id), DSPropertyEVENT_FACTION_ID );
if( propPvpMode.getValue()&PVP_MODE::PvpFactionFlagged ) if( propPvpMode.getValue()&PVP_MODE::PvpFactionFlagged )
{ {
CPVPManager2::getInstance()->setPVPModeInMirror(this); CPVPManager2::getInstance()->setPVPModeInMirror(this);
@ -1721,6 +1730,8 @@ void CCharacter::deathOccurs( void )
CPVPManager2::getInstance()->playerDies(this); CPVPManager2::getInstance()->playerDies(this);
CBuildingManager::getInstance()->removeTriggerRequest(getEntityRowId());
if( _TimeDeath < CTickEventHandler::getGameTime() ) if( _TimeDeath < CTickEventHandler::getGameTime() )
{ {
if (_Mode.getValue().Mode == MBEHAV::DEATH) if (_Mode.getValue().Mode == MBEHAV::DEATH)
@ -2878,14 +2889,7 @@ void CCharacter::postLoadTreatment()
{ {
tickets[ slot ] = true; tickets[ slot ] = true;
// init pet inventory initPetInventory(i);
const uint32 petMaxWeight = 0xFFFFFFFF; // no weight limit
const uint32 petMaxBulk = _PlayerPets[ i ].getAnimalMaxBulk();
const INVENTORIES::TInventory petInvId = (INVENTORIES::TInventory)(i + INVENTORIES::pet_animal);
CPetInventory *petInventory = dynamic_cast<CPetInventory*> ((CInventoryBase*)_Inventory[petInvId]);
if (petInventory)
petInventory->initPetInventory( i, petMaxWeight, petMaxBulk );
} }
} }
} }
@ -3000,6 +3004,13 @@ void CCharacter::postLoadTreatment()
computeMiscBonus(); computeMiscBonus();
} }
CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( getId() ));
if (!p->isTrialPlayer())
{
CBankAccessor_PLR::getCHARACTER_INFO().getRING_XP_CATALYSER().setLevel(_PropertyDatabase, 250);
CBankAccessor_PLR::getCHARACTER_INFO().getRING_XP_CATALYSER().setCount(_PropertyDatabase, 999);
}
{ {
H_AUTO(CItemServiceManager); H_AUTO(CItemServiceManager);
CItemServiceManager::getInstance()->initPersistentServices(this); CItemServiceManager::getInstance()->initPersistentServices(this);
@ -5200,15 +5211,10 @@ bool CCharacter::addCharacterAnimal( const CSheetId& PetTicket, uint32 Price, CG
pet.Slot = ptr->getInventorySlot(); pet.Slot = ptr->getInventorySlot();
// init pet inventory // init pet inventory
const uint32 petMaxWeight = 0xFFFFFFFF; // no weight limit if ( ! initPetInventory( i ))
const uint32 petMaxBulk = _PlayerPets[ i ].getAnimalMaxBulk(); {
const INVENTORIES::TInventory petInvId = (INVENTORIES::TInventory)(i + INVENTORIES::pet_animal);
CPetInventory *petInventory = dynamic_cast<CPetInventory*> ((CInventoryBase*)_Inventory[petInvId]);
if (petInventory)
petInventory->initPetInventory( i, petMaxWeight, petMaxBulk );
else
return false; return false;
}
return spawnCharacterAnimal( i ); return spawnCharacterAnimal( i );
} }
@ -6356,7 +6362,7 @@ void CCharacter::removePetCharacterAfterDeath( uint32 index )
{ {
TLogContext_Item_PetDespawn logContext(_Id); TLogContext_Item_PetDespawn logContext(_Id);
// pet founded // pet founded
if( index < MAX_PACK_ANIMAL ) if( index < MAX_INVENTORY_ANIMAL )
{ {
// reset despawn timer // reset despawn timer
// _PropertyDatabase.setProp( _DataIndexReminder->PACK_ANIMAL.BEAST[index].DESPAWN, 0 ); // _PropertyDatabase.setProp( _DataIndexReminder->PACK_ANIMAL.BEAST[index].DESPAWN, 0 );
@ -6766,11 +6772,14 @@ void CCharacter::setAnimalName( uint8 petIndex, ucstring customName )
animal.setCustomName(customName); animal.setCustomName(customName);
sendPetCustomNameToClient(petIndex); sendPetCustomNameToClient(petIndex);
TDataSetRow row = animal.SpawnedPets; if ( ! customName.empty())
NLNET::CMessage msgout("CHARACTER_NAME"); {
msgout.serial(row); TDataSetRow row = animal.SpawnedPets;
msgout.serial(customName); NLNET::CMessage msgout("CHARACTER_NAME");
sendMessageViaMirror("IOS", msgout); msgout.serial(row);
msgout.serial(customName);
sendMessageViaMirror("IOS", msgout);
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -6932,7 +6941,10 @@ double CCharacter::addXpToSkillInternal( double XpGain, const std::string& ContS
uint32 ringCatalyserLvl = 0; uint32 ringCatalyserLvl = 0;
uint32 ringCatalyserCount = 0; uint32 ringCatalyserCount = 0;
if( addXpMode != AddXpToSkillBranch ) // Don't take away cats if free trial limit reached and there is no DP.
bool bConsumeCats = ! ( bFreeTrialLimitReached && _DeathPenalties->isNull() );
if( bConsumeCats && (addXpMode != AddXpToSkillBranch) )
{ {
if( _XpCatalyserSlot != INVENTORIES::INVALID_INVENTORY_SLOT ) if( _XpCatalyserSlot != INVENTORIES::INVALID_INVENTORY_SLOT )
{ {
@ -6952,6 +6964,12 @@ double CCharacter::addXpToSkillInternal( double XpGain, const std::string& ContS
} }
} }
} }
if (!p->isTrialPlayer())
{
xpBonus = XpGain;
}
XpGain += xpBonus + ringXpBonus; XpGain += xpBonus + ringXpBonus;
// update death penalty // update death penalty
@ -8869,7 +8887,7 @@ void CCharacter::setDatabase()
_IneffectiveAuras.activate(); _IneffectiveAuras.activate();
_ConsumableOverdoseEndDates.activate(); _ConsumableOverdoseEndDates.activate();
// init the RRPs // init the RRPs
//RingRewarsdPoints.initDb(); //RingRewardPoints.initDb();
}// setDatabase // }// setDatabase //
@ -8931,7 +8949,8 @@ void CCharacter::startTradeItemSession( uint16 session )
nlwarning("fame %u is INVALID",(uint)bot->getRace() ); nlwarning("fame %u is INVALID",(uint)bot->getRace() );
fame = MinFameToTrade; fame = MinFameToTrade;
} }
else if ( fame < MinFameToTrade && bot->getOrganization() != getOrganization() )
if ( (bot->getOrganization() == 0 && fame < MinFameToTrade) || (bot->getOrganization() != 0 && bot->getOrganization() != getOrganization()) )
{ {
SM_STATIC_PARAMS_1(params, STRING_MANAGER::bot); SM_STATIC_PARAMS_1(params, STRING_MANAGER::bot);
params[0].setEIdAIAlias( _CurrentInterlocutor, CAIAliasTranslator::getInstance()->getAIAlias(_CurrentInterlocutor) ); params[0].setEIdAIAlias( _CurrentInterlocutor, CAIAliasTranslator::getInstance()->getAIAlias(_CurrentInterlocutor) );
@ -8939,6 +8958,9 @@ void CCharacter::startTradeItemSession( uint16 session )
npcTellToPlayerEx( bot->getEntityRowId(),_EntityRowId,txt ); npcTellToPlayerEx( bot->getEntityRowId(),_EntityRowId,txt );
return; return;
} }
else if (bot->getOrganization() != 0 && bot->getOrganization() == getOrganization())
fame = 0;
float fameFactor = 1.0f; float fameFactor = 1.0f;
if(bot->getForm()->getFaction() != CStaticFames::INVALID_FACTION_INDEX) if(bot->getForm()->getFaction() != CStaticFames::INVALID_FACTION_INDEX)
@ -9036,7 +9058,8 @@ void CCharacter::startTradePhrases(uint16 session)
{ {
nlwarning("fame %u is INVALID",(uint)bot->getRace() ); nlwarning("fame %u is INVALID",(uint)bot->getRace() );
} }
if ( fame < MinFameToTrade && bot->getOrganization() != getOrganization() )
if ( (bot->getOrganization() == 0 && fame < MinFameToTrade) || (bot->getOrganization() != 0 && bot->getOrganization() != getOrganization()) )
{ {
SM_STATIC_PARAMS_1(params, STRING_MANAGER::bot); SM_STATIC_PARAMS_1(params, STRING_MANAGER::bot);
params[0].setEIdAIAlias( _CurrentInterlocutor, CAIAliasTranslator::getInstance()->getAIAlias(_CurrentInterlocutor) ); params[0].setEIdAIAlias( _CurrentInterlocutor, CAIAliasTranslator::getInstance()->getAIAlias(_CurrentInterlocutor) );
@ -9045,7 +9068,6 @@ void CCharacter::startTradePhrases(uint16 session)
return; return;
} }
// *** Set right rolemaster flags and race in Database // *** Set right rolemaster flags and race in Database
uint8 flags = 0; uint8 flags = 0;
if( bot->isSellingCharacteristics() ) if( bot->isSellingCharacteristics() )
@ -9806,7 +9828,8 @@ void CCharacter::sellItem( INVENTORIES::TInventory inv, uint32 slot, uint32 quan
nlwarning("fame %u is INVALID",(uint)bot->getRace() ); nlwarning("fame %u is INVALID",(uint)bot->getRace() );
fame = MinFameToTrade; fame = MinFameToTrade;
} }
else if ( fame < MinFameToTrade && bot->getOrganization() != getOrganization() )
if ( (bot->getOrganization() == 0 && fame < MinFameToTrade) || (bot->getOrganization() != 0 && bot->getOrganization() != getOrganization()) )
{ {
SM_STATIC_PARAMS_1(params, STRING_MANAGER::bot); SM_STATIC_PARAMS_1(params, STRING_MANAGER::bot);
params[0].setEIdAIAlias( _CurrentInterlocutor, CAIAliasTranslator::getInstance()->getAIAlias(_CurrentInterlocutor) ); params[0].setEIdAIAlias( _CurrentInterlocutor, CAIAliasTranslator::getInstance()->getAIAlias(_CurrentInterlocutor) );
@ -9818,6 +9841,8 @@ void CCharacter::sellItem( INVENTORIES::TInventory inv, uint32 slot, uint32 quan
return; return;
} }
else if (bot->getOrganization() != 0 && bot->getOrganization() == getOrganization())
fame = 0;
CInventoryPtr child = _Inventory[ inv ]; CInventoryPtr child = _Inventory[ inv ];
if( child->getSlotCount() > slot && child->getItem( slot ) != NULL ) if( child->getSlotCount() > slot && child->getItem( slot ) != NULL )
@ -9853,6 +9878,13 @@ void CCharacter::sellItem( INVENTORIES::TInventory inv, uint32 slot, uint32 quan
return; return;
} }
// You cannot exchange genesis named items
if (item->getPhraseId().find("genesis_") == 0)
{
nlwarning("Character %s tries to sell '%s'", _Id.toString().c_str(), item->getPhraseId().c_str() );
return;
}
if( ! ITEMFAMILY::isSellableByPlayer( itemForm->Family ) ) if( ! ITEMFAMILY::isSellableByPlayer( itemForm->Family ) )
{ {
nlwarning("<CCharacter sellItem> character %s try to sell an unsealable item %s, must not permited by client", _Id.toString().c_str(), sheet.toString().c_str() ); nlwarning("<CCharacter sellItem> character %s try to sell an unsealable item %s, must not permited by client", _Id.toString().c_str(), sheet.toString().c_str() );
@ -10206,7 +10238,7 @@ void CCharacter::setOrganizationStatus(uint32 status)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CCharacter::changeOrganizationStatus(sint32 status) void CCharacter::changeOrganizationStatus(sint32 status)
{ {
if (status < 0 && abs(status) > _OrganizationStatus) if (status < 0 && abs(status) > (sint32)_OrganizationStatus)
_OrganizationStatus = 0; _OrganizationStatus = 0;
else else
_OrganizationStatus += status; _OrganizationStatus += status;
@ -10216,7 +10248,7 @@ void CCharacter::changeOrganizationStatus(sint32 status)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CCharacter::changeOrganizationPoints(sint32 points) void CCharacter::changeOrganizationPoints(sint32 points)
{ {
if (points < 0 && abs(points) > _OrganizationPoints) if (points < 0 && abs(points) > (sint32)_OrganizationPoints)
_OrganizationPoints = 0; _OrganizationPoints = 0;
else else
_OrganizationPoints += points; _OrganizationPoints += points;
@ -11161,14 +11193,14 @@ bool CCharacter::validateExchange()
sint32 ticketDelta = c->_ExchangeView->getPetTicketExchanged( ITEM_TYPE::MEKTOUB_PACKER_TICKET ) - _ExchangeView->getPetTicketExchanged( ITEM_TYPE::MEKTOUB_PACKER_TICKET ); sint32 ticketDelta = c->_ExchangeView->getPetTicketExchanged( ITEM_TYPE::MEKTOUB_PACKER_TICKET ) - _ExchangeView->getPetTicketExchanged( ITEM_TYPE::MEKTOUB_PACKER_TICKET );
if( !checkAnimalCount( packerSheet, false, ticketDelta ) ) if( !checkAnimalCount( packerSheet, false, ticketDelta ) )
{ {
sendDynamicSystemMessage(getId(), "ANIMAL_PLAYER_HAVE_MAX()"); sendDynamicSystemMessage(getId(), "ANIMAL_PLAYER_HAVE_MAX");
c->sendDynamicSystemMessage(c->getId(), "ANIMAL_INTERLOCUTOR_HAVE_MAX"); c->sendDynamicSystemMessage(c->getId(), "ANIMAL_INTERLOCUTOR_HAVE_MAX");
invalidateExchange(); invalidateExchange();
return false; return false;
} }
if( !c->checkAnimalCount( packerSheet, false, -ticketDelta ) ) if( !c->checkAnimalCount( packerSheet, false, -ticketDelta ) )
{ {
c->sendDynamicSystemMessage(getId(), "ANIMAL_PLAYER_HAVE_MAX()"); c->sendDynamicSystemMessage(getId(), "ANIMAL_PLAYER_HAVE_MAX");
sendDynamicSystemMessage(c->getId(), "ANIMAL_INTERLOCUTOR_HAVE_MAX"); sendDynamicSystemMessage(c->getId(), "ANIMAL_INTERLOCUTOR_HAVE_MAX");
invalidateExchange(); invalidateExchange();
return false; return false;
@ -11180,14 +11212,14 @@ bool CCharacter::validateExchange()
sint32 ticketDelta = c->_ExchangeView->getPetTicketExchanged(ITEM_TYPE::MEKTOUB_MOUNT_TICKET) - _ExchangeView->getPetTicketExchanged(ITEM_TYPE::MEKTOUB_MOUNT_TICKET); sint32 ticketDelta = c->_ExchangeView->getPetTicketExchanged(ITEM_TYPE::MEKTOUB_MOUNT_TICKET) - _ExchangeView->getPetTicketExchanged(ITEM_TYPE::MEKTOUB_MOUNT_TICKET);
if( !checkAnimalCount( mountSheet, false, ticketDelta ) ) if( !checkAnimalCount( mountSheet, false, ticketDelta ) )
{ {
sendDynamicSystemMessage(getId(), "ANIMAL_PLAYER_HAVE_MAX()"); sendDynamicSystemMessage(getId(), "ANIMAL_PLAYER_HAVE_MAX");
c->sendDynamicSystemMessage(c->getId(), "ANIMAL_INTERLOCUTOR_HAVE_MAX"); c->sendDynamicSystemMessage(c->getId(), "ANIMAL_INTERLOCUTOR_HAVE_MAX");
invalidateExchange(); invalidateExchange();
return false; return false;
} }
if( !c->checkAnimalCount( mountSheet, false, -ticketDelta ) ) if( !c->checkAnimalCount( mountSheet, false, -ticketDelta ) )
{ {
c->sendDynamicSystemMessage(getId(), "ANIMAL_PLAYER_HAVE_MAX()"); c->sendDynamicSystemMessage(getId(), "ANIMAL_PLAYER_HAVE_MAX");
sendDynamicSystemMessage(c->getId(), "ANIMAL_INTERLOCUTOR_HAVE_MAX"); sendDynamicSystemMessage(c->getId(), "ANIMAL_INTERLOCUTOR_HAVE_MAX");
invalidateExchange(); invalidateExchange();
return false; return false;
@ -11285,21 +11317,23 @@ void CCharacter::removeExchangeItems(vector<CGameItemPtr >& itemRemoved, vector<
// addExchangeItems // addExchangeItems
// //
//----------------------------------------------- //-----------------------------------------------
void CCharacter::addExchangeItems(CCharacter* trader,vector<CGameItemPtr >& itemToAdd, vector< CPetAnimal >& playerPetsAdd) void CCharacter::addExchangeItems(CCharacter* trader,vector<CGameItemPtr >& itemToAdd, vector< CPetAnimal >& playerPetsAdded)
{ {
// inform AI // inform AI
CPetSetOwner msgAI; CPetSetOwner msgAI;
bool updatePetDataBase = false; bool updatePetDataBase = false;
for( uint32 p = 0; p < playerPetsAdd.size(); ++p ) for( uint32 p = 0; p < playerPetsAdded.size(); ++p )
{ {
sint32 i = getFreePetSlot(); sint32 i = getFreePetSlot();
if( i >= 0 ) if( i >= 0 )
{ {
_PlayerPets[ i ] = playerPetsAdd[ p ]; _PlayerPets[ i ] = playerPetsAdded[ p ];
_PlayerPets[ i ].OwnerId = _Id; _PlayerPets[ i ].OwnerId = _Id;
initPetInventory(i);
if( _PlayerPets[ i ].PetStatus == CPetAnimal::waiting_spawn ) if( _PlayerPets[ i ].PetStatus == CPetAnimal::waiting_spawn )
{ {
spawnCharacterAnimal( i ); spawnCharacterAnimal( i );
@ -13567,7 +13601,7 @@ void CCharacter::sendUrl(const string &url, const string &salt)
if (!salt.empty()) if (!salt.empty())
{ {
string checksum = salt+url; string checksum = salt+url;
control = "&hmac="+getHMacSHA1((uint8*)&url[0], (uint32)url.size(), (uint8*)&salt[0], (uint32)salt.size()).toString();; control = "&hmac="+getHMacSHA1((uint8*)&url[0], (uint32)url.size(), (uint8*)&salt[0], (uint32)salt.size()).toString();
} }
nlinfo(url.c_str()); nlinfo(url.c_str());
@ -14309,16 +14343,14 @@ void CCharacter::setAuraFlagDates()
const NLMISC::TGameCycle time = CTickEventHandler::getGameCycle(); const NLMISC::TGameCycle time = CTickEventHandler::getGameCycle();
uint32 flag = BRICK_FLAGS::Aura - BRICK_FLAGS::BeginPowerFlags; uint32 flag = BRICK_FLAGS::Aura - BRICK_FLAGS::BeginPowerFlags;
if ( (_ForbidAuraUseEndDate > time) && (_ForbidAuraUseEndDate - time < 72000) ) if ( (_ForbidAuraUseEndDate < time) || (_ForbidAuraUseEndDate - time > 72000) )
{ {
_PowerFlagTicks[flag].StartTick = _ForbidAuraUseStartDate; _ForbidAuraUseStartDate = 0;
_PowerFlagTicks[flag].EndTick = _ForbidAuraUseEndDate; _ForbidAuraUseEndDate = 0;
}
else
{
_PowerFlagTicks[flag].StartTick = 0;
_PowerFlagTicks[flag].EndTick = 0;
} }
_PowerFlagTicks[flag].StartTick = _ForbidAuraUseStartDate;
_PowerFlagTicks[flag].EndTick = _ForbidAuraUseEndDate;
} // setAuraFlagDates // } // setAuraFlagDates //
@ -14605,28 +14637,32 @@ uint32 CCharacter::getCarriedWeight()
} }
//-------------------------------------------------------------- //--------------------------------------------------------------
// CCharacter::getResistScore() // CCharacter::getMagicResistance()
//--------------------------------------------------------------
uint32 CCharacter::getMagicResistance(RESISTANCE_TYPE::TResistanceType magicResistanceType) const
{
uint32 val = getUnclampedMagicResistance(magicResistanceType);
NLMISC::clamp( val, (uint32)0, (uint32)((_BaseResistance + MaxMagicResistanceBonus) * 100) );
return val;
}
//--------------------------------------------------------------
// CCharacter::getMagicResistance()
//-------------------------------------------------------------- //--------------------------------------------------------------
uint32 CCharacter::getMagicResistance(EFFECT_FAMILIES::TEffectFamily effectFamily) uint32 CCharacter::getMagicResistance(EFFECT_FAMILIES::TEffectFamily effectFamily)
{ {
RESISTANCE_TYPE::TResistanceType resistanceType = EFFECT_FAMILIES::getAssociatedResistanceType(effectFamily); RESISTANCE_TYPE::TResistanceType resistanceType = EFFECT_FAMILIES::getAssociatedResistanceType(effectFamily);
if(resistanceType==RESISTANCE_TYPE::None) return getMagicResistance(resistanceType);
return 0; }
else
return _MagicResistance[resistanceType];
} // getResistScore //
//-------------------------------------------------------------- //--------------------------------------------------------------
// CCharacter::getResistScore() // CCharacter::getMagicResistance()
//-------------------------------------------------------------- //--------------------------------------------------------------
uint32 CCharacter::getMagicResistance(DMGTYPE::EDamageType dmgType) uint32 CCharacter::getMagicResistance(DMGTYPE::EDamageType dmgType)
{ {
RESISTANCE_TYPE::TResistanceType resistanceType = DMGTYPE::getAssociatedResistanceType(dmgType); RESISTANCE_TYPE::TResistanceType resistanceType = DMGTYPE::getAssociatedResistanceType(dmgType);
if(resistanceType==RESISTANCE_TYPE::None) return getMagicResistance(resistanceType);
return 0; }
else
return _MagicResistance[resistanceType];
} // getResistScore //
//-------------------------------------------------------------- //--------------------------------------------------------------
// addPlayerToFriendList // addPlayerToFriendList
@ -14650,20 +14686,52 @@ void CCharacter::addPlayerToIgnoreList(const ucstring &name)
TCharConnectionState CCharacter::isFriendCharVisualyOnline(const NLMISC::CEntityId &friendId) TCharConnectionState CCharacter::isFriendCharVisualyOnline(const NLMISC::CEntityId &friendId)
{ {
TCharConnectionState ret = ccs_offline; TCharConnectionState ret = ccs_offline;
if (CEntityIdTranslator::getInstance()->isEntityOnline(friendId)) if (CEntityIdTranslator::getInstance()->isEntityOnline(friendId))
{ {
if ( PlayerManager.hasBetterCSRGrade(friendId, _Id, true)) if ( PlayerManager.hasBetterCSRGrade(friendId, _Id, true))
{
// better CSR grade return always 'offline' status // better CSR grade return always 'offline' status
return ccs_offline; return ccs_offline;
}
ret = ccs_online; ret = ccs_online;
} }
// Handle friend preference setting
CCharacter *friendChar = PlayerManager.getChar(friendId);
if (friendChar != NULL)
{
volatile TFriendVisibility friendMode = friendChar->getFriendVisibility();
switch (friendMode)
{
case VisibleToGuildOnly:
{
uint32 fgid = friendChar->getGuildId();
uint32 mgid = this->getGuildId();
bool inSameGuild = (mgid != 0) && (fgid == mgid);
if ( ! inSameGuild)
{
return ccs_offline;
}
}
break;
case VisibleToGuildAndFriends:
if (this->isIgnoredBy(friendId))
{
return ccs_offline;
}
break;
case VisibleToAll: // fallthrough
default:
break; // no-op
}
}
// Additional online check for ring shard : // Additional online check for ring shard :
// - a contact is online only if it is in the same ring session // - a contact is online only if it is in the same ring session
if (ret == ccs_online && IsRingShard) if (ret == ccs_online && IsRingShard)
{ {
CCharacter *friendChar = PlayerManager.getChar(friendId);
if (friendChar == NULL) // not found ! set offline if (friendChar == NULL) // not found ! set offline
ret = ccs_offline; ret = ccs_offline;
else else
@ -14849,7 +14917,7 @@ void CCharacter::addPlayerToFriendList(const NLMISC::CEntityId &id)
// if player not found // if player not found
if (id == CEntityId::Unknown) if (id == CEntityId::Unknown)
{ {
PHRASE_UTILITIES::sendDynamicSystemMessage( _EntityRowId, "OPERATION_OFFLINE"); PHRASE_UTILITIES::sendDynamicSystemMessage( _EntityRowId, "OPERATION_NOTEXIST");
return; return;
} }
@ -14921,12 +14989,12 @@ void CCharacter::addPlayerToLeagueList(const NLMISC::CEntityId &id)
// if player not found // if player not found
if (id == CEntityId::Unknown) if (id == CEntityId::Unknown)
{ {
PHRASE_UTILITIES::sendDynamicSystemMessage( _EntityRowId, "OPERATION_OFFLINE"); PHRASE_UTILITIES::sendDynamicSystemMessage( _EntityRowId, "OPERATION_NOTEXIST");
return; return;
} }
// check not already in list // check not already in list
const uint size = _LeagueList.size(); const uint size = (uint)_LeagueList.size();
for ( uint i =0 ; i < size ; ++i) for ( uint i =0 ; i < size ; ++i)
{ {
if ( _LeagueList[i].EntityId.getShortId() == id.getShortId()) if ( _LeagueList[i].EntityId.getShortId() == id.getShortId())
@ -14990,14 +15058,12 @@ void CCharacter::addPlayerToLeagueList(const NLMISC::CEntityId &id)
//-------------------------------------------------------------- //--------------------------------------------------------------
void CCharacter::addPlayerToIgnoreList(const NLMISC::CEntityId &id) void CCharacter::addPlayerToIgnoreList(const NLMISC::CEntityId &id)
{ {
// if player not found if (id == CEntityId::Unknown)
// Boris 2006-09-19 : allow adding offline player to ignore list {
// if (id == CEntityId::Unknown || PlayerManager.getChar(id)==NULL) // player not found => message
// { PHRASE_UTILITIES::sendDynamicSystemMessage( _EntityRowId, "OPERATION_NOTEXIST");
// // player not found => message return;
// PHRASE_UTILITIES::sendDynamicSystemMessage( _EntityRowId, "OPERATION_OFFLINE"); }
// return;
// }
// check not already ignored // check not already ignored
const uint size = (uint)_IgnoreList.size(); const uint size = (uint)_IgnoreList.size();
@ -15416,25 +15482,50 @@ void CCharacter::contactListRefChange(const NLMISC::CEntityId &id, TConctactList
} }
//--------------------------------------------------------------
// CCharacter::isIgnoredBy()
//--------------------------------------------------------------
bool CCharacter::isIgnoredBy(const NLMISC::CEntityId &id)
{
const uint size = (uint)_IsIgnoredBy.size();
for (uint i = 0; i < size; ++i)
{
if (_IsIgnoredBy[i].getShortId() == id.getShortId())
{
return true;
}
}
return false;
}
//--------------------------------------------------------------
// CCharacter::isFriendOf()
//--------------------------------------------------------------
bool CCharacter::isFriendOf(const NLMISC::CEntityId &id)
{
const uint size = (uint)_IsFriendOf.size();
for (uint i = 0 ; i < size ; ++i)
{
if (_IsFriendOf[i].getShortId() == id.getShortId())
{
return true;
}
}
return false;
}
//-------------------------------------------------------------- //--------------------------------------------------------------
// CCharacter::referencedAsFriendBy() // CCharacter::referencedAsFriendBy()
//-------------------------------------------------------------- //--------------------------------------------------------------
void CCharacter::referencedAsFriendBy( const NLMISC::CEntityId &id) void CCharacter::referencedAsFriendBy( const NLMISC::CEntityId &id)
{ {
// check this entity isn't already in the list if (isFriendOf(id))
const uint size = (uint)_IsFriendOf.size();
for ( uint i =0 ; i < size ; ++i)
{ {
if ( _IsFriendOf[i].getShortId() == id.getShortId()) return;
{
return;
}
} }
// not found -> add it // not found -> add it
_IsFriendOf.push_back(id); _IsFriendOf.push_back(id);
} }
//-------------------------------------------------------------- //--------------------------------------------------------------
@ -17454,6 +17545,18 @@ void CCharacter::pvpActionMade()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CCharacter::setPVPFlagDatabase() void CCharacter::setPVPFlagDatabase()
{ {
// Fix for when negative ticks were saved
if ( (_PVPRecentActionTime > CTickEventHandler::getGameCycle())
|| (_PVPFlagLastTimeChange > CTickEventHandler::getGameCycle())
|| (_PVPFlagTimeSettedOn > CTickEventHandler::getGameCycle() + TimeForSetPVPFlag) )
{
_PVPRecentActionTime = 0;
_PVPFlagLastTimeChange = 0;
_PVPFlagTimeSettedOn = 0;
_PVPSafeLastTimeChange = 0;
_PVPFlag = false;
}
uint32 activationTime; uint32 activationTime;
if( _PVPFlag == true ) if( _PVPFlag == true )
activationTime = _PVPFlagLastTimeChange + TimeForSetPVPFlag; activationTime = _PVPFlagLastTimeChange + TimeForSetPVPFlag;
@ -17788,6 +17891,7 @@ void CCharacter::setOutpostAlias( uint32 id )
CBankAccessor_PLR::getCHARACTER_INFO().getPVP_OUTPOST().setRIGHT_TO_BANISH(_PropertyDatabase, hasRightToBanish ); CBankAccessor_PLR::getCHARACTER_INFO().getPVP_OUTPOST().setRIGHT_TO_BANISH(_PropertyDatabase, hasRightToBanish );
CPVPManager2::getInstance()->setPVPModeInMirror(this); CPVPManager2::getInstance()->setPVPModeInMirror(this);
updatePVPClanVP();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -18539,48 +18643,49 @@ void CCharacter::updateMagicProtectionAndResistance()
_MaxAbsorption = (getSkillBaseValue(getBestSkill()) * MaxAbsorptionFactor) / 100; _MaxAbsorption = (getSkillBaseValue(getBestSkill()) * MaxAbsorptionFactor) / 100;
// magic resistance // magic resistance
sint32 baseResistance = (sint32)(_Skills._Skills[SKILLS::SF].MaxLvlReached * MagicResistFactorForCombatSkills) + MagicResistSkillDelta; _BaseResistance = (sint32)(_Skills._Skills[SKILLS::SF].MaxLvlReached * MagicResistFactorForCombatSkills) + MagicResistSkillDelta;
if( baseResistance < ((sint32)(_Skills._Skills[SKILLS::SM].MaxLvlReached * MagicResistFactorForMagicSkills) + MagicResistSkillDelta) )
baseResistance = (sint32)(_Skills._Skills[SKILLS::SM].MaxLvlReached * MagicResistFactorForMagicSkills) + MagicResistSkillDelta;
if( baseResistance < ((sint32)(_Skills._Skills[SKILLS::SH].MaxLvlReached * MagicResistFactorForForageSkills) + MagicResistSkillDelta) )
baseResistance = (sint32)(_Skills._Skills[SKILLS::SH].MaxLvlReached * MagicResistFactorForForageSkills) + MagicResistSkillDelta;
clamp(baseResistance, 0, 225);
sint32 magicResist = ((sint32)(_Skills._Skills[SKILLS::SM].MaxLvlReached * MagicResistFactorForMagicSkills) + MagicResistSkillDelta);
_BaseResistance = max(_BaseResistance, magicResist);
sint32 forageResist = ((sint32)(_Skills._Skills[SKILLS::SH].MaxLvlReached * MagicResistFactorForForageSkills) + MagicResistSkillDelta);
_BaseResistance = max(_BaseResistance, forageResist);
clamp(_BaseResistance, 0, 225);
// set up base
for( uint32 i = 0; i < RESISTANCE_TYPE::NB_RESISTANCE_TYPE; ++i ) for( uint32 i = 0; i < RESISTANCE_TYPE::NB_RESISTANCE_TYPE; ++i )
{ {
_MagicResistance[i]= (uint32)baseResistance * 100; _MagicResistance[i]= (uint32)_BaseResistance * 100;
}
switch(i) // correct for race
{ switch ( _Race)
case RESISTANCE_TYPE::Desert: {
if( _Race == EGSPD::CPeople::Fyros ) case EGSPD::CPeople::Fyros:
{ _MagicResistance[RESISTANCE_TYPE::Desert] += HominRacialResistance * 100;
_MagicResistance[i] += HominRacialResistance * 100;
}
break; break;
case RESISTANCE_TYPE::Forest:
if( _Race == EGSPD::CPeople::Matis ) case EGSPD::CPeople::Matis:
{ _MagicResistance[RESISTANCE_TYPE::Forest] += HominRacialResistance * 100;
_MagicResistance[i] += HominRacialResistance * 100;
}
break; break;
case RESISTANCE_TYPE::Lacustre:
if( _Race == EGSPD::CPeople::Tryker ) case EGSPD::CPeople::Tryker:
{ _MagicResistance[RESISTANCE_TYPE::Lacustre] += HominRacialResistance * 100;
_MagicResistance[i] += HominRacialResistance * 100;
}
break; break;
case RESISTANCE_TYPE::Jungle:
if( _Race == EGSPD::CPeople::Zorai ) case EGSPD::CPeople::Zorai:
{ _MagicResistance[RESISTANCE_TYPE::Jungle] += HominRacialResistance * 100;
_MagicResistance[i] += HominRacialResistance * 100;
}
break; break;
default: default:
break; break;
} }
// correct for current region
for( uint32 i = 0; i < RESISTANCE_TYPE::NB_RESISTANCE_TYPE; ++i )
{
_MagicResistance[i] = (uint32)((sint32)max( (sint32)0, ((sint32)_MagicResistance[i]) + getRegionResistanceModifier((RESISTANCE_TYPE::TResistanceType)i) * (sint32)100)); _MagicResistance[i] = (uint32)((sint32)max( (sint32)0, ((sint32)_MagicResistance[i]) + getRegionResistanceModifier((RESISTANCE_TYPE::TResistanceType)i) * (sint32)100));
clamp( _MagicResistance[i], (uint32)0, (uint32)((baseResistance + MaxMagicResistanceBonus) * 100) );
} }
// protection // protection
@ -18663,7 +18768,7 @@ void CCharacter::updateMagicProtectionAndResistance()
for (uint i=0; i<RESISTANCE_TYPE::NB_RESISTANCE_TYPE; ++i) for (uint i=0; i<RESISTANCE_TYPE::NB_RESISTANCE_TYPE; ++i)
{ {
CBankAccessor_PLR::getCHARACTER_INFO().getMAGIC_RESISTANCE().getArray(i).setVALUE(_PropertyDatabase, checkedCast<uint16>(_MagicResistance[i])); CBankAccessor_PLR::getCHARACTER_INFO().getMAGIC_RESISTANCE().getArray(i).setVALUE(_PropertyDatabase, checkedCast<uint16>(getUnclampedMagicResistance((RESISTANCE_TYPE::TResistanceType)i)));
} }
// _PropertyDatabase.setProp("CHARACTER_INFO:MAGIC_RESISTANCE:Desert", _MagicResistance[RESISTANCE_TYPE::Desert]); // _PropertyDatabase.setProp("CHARACTER_INFO:MAGIC_RESISTANCE:Desert", _MagicResistance[RESISTANCE_TYPE::Desert]);
// _PropertyDatabase.setProp("CHARACTER_INFO:MAGIC_RESISTANCE:Forest", _MagicResistance[RESISTANCE_TYPE::Forest]); // _PropertyDatabase.setProp("CHARACTER_INFO:MAGIC_RESISTANCE:Forest", _MagicResistance[RESISTANCE_TYPE::Forest]);
@ -20120,7 +20225,9 @@ void CCharacter::setEnterCriticalZoneProposalQueueId(uint32 queueId)
uint32 CCharacter::getMagicProtection( PROTECTION_TYPE::TProtectionType magicProtectionType ) const uint32 CCharacter::getMagicProtection( PROTECTION_TYPE::TProtectionType magicProtectionType ) const
{ {
uint32 val = getUnclampedMagicProtection(magicProtectionType); NLMISC::clamp( val, (uint32)0, MaxMagicProtection ); return val; uint32 val = getUnclampedMagicProtection(magicProtectionType);
NLMISC::clamp( val, (uint32)0, MaxMagicProtection );
return val;
} }
@ -20612,3 +20719,21 @@ void CCharacter::sendNpcMissionGiverTimer(bool force)
CUnifiedNetwork::getInstance()->send( NLNET::TServiceId(_Id.getDynamicId()), msgout ); CUnifiedNetwork::getInstance()->send( NLNET::TServiceId(_Id.getDynamicId()), msgout );
} }
} }
//------------------------------------------------------------------------------
bool CCharacter::initPetInventory(uint8 index)
{
// init pet inventory
const uint32 petMaxWeight = 0xFFFFFFFF; // no weight limit
const uint32 petMaxBulk = _PlayerPets[ index ].getAnimalMaxBulk();
const INVENTORIES::TInventory petInvId = (INVENTORIES::TInventory)(index + INVENTORIES::pet_animal);
CPetInventory *petInventory = dynamic_cast<CPetInventory*> ((CInventoryBase*)_Inventory[petInvId]);
if (petInventory)
{
petInventory->initPetInventory( index, petMaxWeight, petMaxBulk );
return true;
}
return false;
}

View file

@ -395,6 +395,15 @@ struct CXpProgressInfos
} }
}; };
enum TFriendVisibility
{
VisibleToAll = 0, // Visible to all people who have me on their friends list, even if I am ignoring them.
VisibleToGuildAndFriends, // Visible to people in my guild and those that have me on their friends list.
VisibleToGuildOnly, // Only visible to people in my guild.
NB_FRIEND_VISIBILITY
};
/** /**
* CCharacter * CCharacter
@ -1023,14 +1032,14 @@ public:
// Same but nearly empty // Same but nearly empty
void setDummyStartCharacteristics(); void setDummyStartCharacteristics();
/** /**
* Eval Specialization for return Characteristics value * Eval Specialization for return Characteristics value
* *
* \param value is the value to parse. * \param value is the value to parse.
* \param result is the result to fill if the value has been succesfully parsed. * \param result is the result to fill if the value has been succesfully parsed.
* \return UnknownValue if the value is not known, ValueError is the value evaluation failed or NoError * \return UnknownValue if the value is not known, ValueError is the value evaluation failed or NoError
* if it has been parsed. * if it has been parsed.
*/ */
virtual TReturnState evalValue (const char *value, double &result, uint32 userData); virtual TReturnState evalValue (const char *value, double &result, uint32 userData);
/// Add a pact /// Add a pact
@ -2259,6 +2268,9 @@ public:
// return unclamped magic resistance of a character // return unclamped magic resistance of a character
uint32 getUnclampedMagicResistance( RESISTANCE_TYPE::TResistanceType magicResistanceType ) const; uint32 getUnclampedMagicResistance( RESISTANCE_TYPE::TResistanceType magicResistanceType ) const;
// return clamped magic resistance of a character
uint32 getMagicResistance(RESISTANCE_TYPE::TResistanceType magicResistanceType) const;
/// return NbNonNullClassificationTypesSkillMod /// return NbNonNullClassificationTypesSkillMod
uint8 getNbNonNullClassificationTypesSkillMod() const; uint8 getNbNonNullClassificationTypesSkillMod() const;
@ -2381,6 +2393,7 @@ public:
uint32 getLastConnectedDate() const; uint32 getLastConnectedDate() const;
uint32 getPlayedTime() const; uint32 getPlayedTime() const;
uint32 getOrganization() const; uint32 getOrganization() const;
uint32 getOrganizationStatus() const;
const std::list<TCharacterLogTime>& getLastLogStats() const; const std::list<TCharacterLogTime>& getLastLogStats() const;
void updateConnexionStat(); void updateConnexionStat();
void setDisconnexionTime(); void setDisconnexionTime();
@ -2692,6 +2705,10 @@ private:
void contactListRefChange(const NLMISC::CEntityId &id, TConctactListAction actionType); void contactListRefChange(const NLMISC::CEntityId &id, TConctactListAction actionType);
/// return true if player is ignored by the given entity
bool isIgnoredBy(const NLMISC::CEntityId &id);
/// return true if given entity has player on friend list
bool isFriendOf(const NLMISC::CEntityId &id);
/// player is referenced as friend by the given entity /// player is referenced as friend by the given entity
void referencedAsFriendBy( const NLMISC::CEntityId &id); void referencedAsFriendBy( const NLMISC::CEntityId &id);
/// player is no longer referenced as friend by the given entity /// player is no longer referenced as friend by the given entity
@ -2767,7 +2784,7 @@ private:
void removeExchangeItems(std::vector<CGameItemPtr>& itemRemoved, std::vector< CPetAnimal >& PlayerPetsRemoved); void removeExchangeItems(std::vector<CGameItemPtr>& itemRemoved, std::vector< CPetAnimal >& PlayerPetsRemoved);
// add the items gained during an exchange // add the items gained during an exchange
void addExchangeItems(CCharacter* trader,std::vector<CGameItemPtr>& itemToAdd, std::vector< CPetAnimal >& PlayerPetsAdd); void addExchangeItems(CCharacter* trader,std::vector<CGameItemPtr>& itemToAdd, std::vector< CPetAnimal >& PlayerPetsAdded);
/// get creator name dynamic string Id /// get creator name dynamic string Id
uint32 getCreatorNameId( const NLMISC::CEntityId &creatorId); uint32 getCreatorNameId( const NLMISC::CEntityId &creatorId);
@ -2895,6 +2912,9 @@ private:
*/ */
double addXpToSkillInternal( double XpGain, const std::string& ContSkill, TAddXpToSkillMode addXpMode, std::map<SKILLS::ESkills,CXpProgressInfos> &gainBySkill ); double addXpToSkillInternal( double XpGain, const std::string& ContSkill, TAddXpToSkillMode addXpMode, std::map<SKILLS::ESkills,CXpProgressInfos> &gainBySkill );
/// Initialize the specified pet inventory, if it is valid
bool initPetInventory(uint8 index);
/////////////////// ///////////////////
// Public members // Public members
/////////////////// ///////////////////
@ -2948,6 +2968,12 @@ public:
void setFinalized(bool isFinalized) { _LoadingFinish = isFinalized; }; void setFinalized(bool isFinalized) { _LoadingFinish = isFinalized; };
bool isFinalized() const { return _LoadingFinish; }; bool isFinalized() const { return _LoadingFinish; };
void setFriendVisibility(TFriendVisibility val) { _FriendVisibility = val; }
const TFriendVisibility& getFriendVisibility() const { return _FriendVisibility; }
void setFriendVisibilitySave(uint8 val) { if (val < NB_FRIEND_VISIBILITY) _FriendVisibility = (TFriendVisibility)val; }
uint8 getFriendVisibilitySave() const { return (uint8)_FriendVisibility; }
////////////////// //////////////////
// Private members // Private members
////////////////// //////////////////
@ -3407,6 +3433,8 @@ private:
// current resistance for each type of magic resistance // current resistance for each type of magic resistance
uint32 _MagicResistance[RESISTANCE_TYPE::NB_RESISTANCE_TYPE]; uint32 _MagicResistance[RESISTANCE_TYPE::NB_RESISTANCE_TYPE];
sint32 _BaseResistance;
/// currently consumed item slot /// currently consumed item slot
sint32 _ConsumedItemSlot; sint32 _ConsumedItemSlot;
/// currently consumed item inventory /// currently consumed item inventory
@ -3516,6 +3544,8 @@ private:
TAIAlias _LastCreatedNpcGroup; TAIAlias _LastCreatedNpcGroup;
TFriendVisibility _FriendVisibility;
// :KLUDGE: ICDBStructNode non-const 'coz getName and getParent are not // :KLUDGE: ICDBStructNode non-const 'coz getName and getParent are not
// const methods. See CCDBSynchronised::getICDBStructNodeFromName for more // const methods. See CCDBSynchronised::getICDBStructNodeFromName for more
// info. // info.

View file

@ -902,6 +902,12 @@ inline uint32 CCharacter::getOrganization() const
} }
inline uint32 CCharacter::getOrganizationStatus() const
{
return _OrganizationStatus;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline const std::list<TCharacterLogTime>& CCharacter::getLastLogStats() const inline const std::list<TCharacterLogTime>& CCharacter::getLastLogStats() const

View file

@ -822,6 +822,13 @@ void CCharacter::moveItem(INVENTORIES::TInventory srcInvId, uint32 srcSlot, INVE
if ((!srcForm->DropOrSell && !canPutNonDropableItemInInventory(dstInvId)) || isAnActiveXpCatalyser(srcItem)) if ((!srcForm->DropOrSell && !canPutNonDropableItemInInventory(dstInvId)) || isAnActiveXpCatalyser(srcItem))
return; return;
// You cannot exchange genesis named items
if (srcItem->getPhraseId().find("genesis_") == 0 && !canPutNonDropableItemInInventory(dstInvId))
{
nlwarning("Character %s tries to move '%s' to inv %u", _Id.toString().c_str(), srcItem->getPhraseId().c_str(), dstInvId );
return;
}
// cannot move a pet animal ticket // cannot move a pet animal ticket
if (srcForm->Family == ITEMFAMILY::PET_ANIMAL_TICKET) if (srcForm->Family == ITEMFAMILY::PET_ANIMAL_TICKET)
return; return;
@ -3035,12 +3042,16 @@ void CCharacter::stopUseItem( bool isRingCatalyser )
} }
else else
{ {
PHRASE_UTILITIES::sendDynamicSystemMessage( _EntityRowId, "XP_CATALYSER_NO_MORE_ACTIVE"); CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( getId() ));
_RingXpCatalyserSlot = INVENTORIES::INVALID_INVENTORY_SLOT; BOMB_IF(p == NULL,"Failed to find player record for character: "<<getId().toString(),return);
// _PropertyDatabase.setProp( "CHARACTER_INFO:RING_XP_CATALYSER:Level", 0 ); if (p->isTrialPlayer()) {
CBankAccessor_PLR::getCHARACTER_INFO().getRING_XP_CATALYSER().setLevel(_PropertyDatabase, 0 ); PHRASE_UTILITIES::sendDynamicSystemMessage( _EntityRowId, "XP_CATALYSER_NO_MORE_ACTIVE");
// _PropertyDatabase.setProp( "CHARACTER_INFO:RING_XP_CATALYSER:Count", 0 ); _RingXpCatalyserSlot = INVENTORIES::INVALID_INVENTORY_SLOT;
CBankAccessor_PLR::getCHARACTER_INFO().getRING_XP_CATALYSER().setCount(_PropertyDatabase, 0 ); // _PropertyDatabase.setProp( "CHARACTER_INFO:RING_XP_CATALYSER:Level", 0 );
CBankAccessor_PLR::getCHARACTER_INFO().getRING_XP_CATALYSER().setLevel(_PropertyDatabase, 0 );
// _PropertyDatabase.setProp( "CHARACTER_INFO:RING_XP_CATALYSER:Count", 0 );
CBankAccessor_PLR::getCHARACTER_INFO().getRING_XP_CATALYSER().setCount(_PropertyDatabase, 0 );
}
} }
} }

View file

@ -570,6 +570,7 @@ static void prepareCharacterPositionForStore ( COfflineEntityState & state, cons
PROP2(Invisible, bool, getInvisibility(), setInvisibility(val)) \ PROP2(Invisible, bool, getInvisibility(), setInvisibility(val)) \
PROP2(Aggroable, sint8, getAggroableSave(), setAggroableSave(val)) \ PROP2(Aggroable, sint8, getAggroableSave(), setAggroableSave(val)) \
PROP2(GodMode, bool, getGodModeSave(), setGodModeSave(val)) \ PROP2(GodMode, bool, getGodModeSave(), setGodModeSave(val)) \
PROP2(FriendVisibility, uint8, getFriendVisibilitySave(), setFriendVisibilitySave(val)) \
//#pragma message( PERSISTENT_GENERATION_MESSAGE ) //#pragma message( PERSISTENT_GENERATION_MESSAGE )

View file

@ -2597,6 +2597,7 @@ NLMISC_COMMAND(setPriv,"set a privilege to a user using his user id, must be in
else if (p->havePriv(AlwaysInvisiblePriv)) else if (p->havePriv(AlwaysInvisiblePriv))
{ {
c->setWhoSeesMe(uint64(0)); c->setWhoSeesMe(uint64(0));
c->setInvisibility(true);
} }
} }
} }

View file

@ -1203,7 +1203,7 @@ void CDamageScoreManager::playerDeath(CCharacter * victimChar, const CCharacter
CCharacter * winnerChar = PlayerManager.getChar(players[k]); CCharacter * winnerChar = PlayerManager.getChar(players[k]);
BOMB_IF(winnerChar == NULL, "invalid winner!", continue); BOMB_IF(winnerChar == NULL, "invalid winner!", continue);
PVP_CLAN::TPVPClan winnerFaction; PVP_CLAN::TPVPClan winnerFaction = PVP_CLAN::None;
bool winnerGainFactionPoints = true; bool winnerGainFactionPoints = true;
if (!canPlayerWinPoints(winnerChar, victimChar)) if (!canPlayerWinPoints(winnerChar, victimChar))

View file

@ -231,7 +231,7 @@ void CPVPInterface::setPVPModeInMirror() const
if ( !TheDataset.isAccessible(_Owner->getEntityRowId()) ) if ( !TheDataset.isAccessible(_Owner->getEntityRowId()) )
return; return;
CMirrorPropValue<TYPE_PVP_MODE> propPvpMode( TheDataset, _Owner->getEntityRowId(), DSPropertyPVP_MODE ); CMirrorPropValue<TYPE_EVENT_FACTION_ID> propPvpMode( TheDataset, _Owner->getEntityRowId(), DSPropertyEVENT_FACTION_ID );
if (_PVPSession) if (_PVPSession)
{ {

View file

@ -393,9 +393,10 @@ void CPVPManager2::sendChannelUsers(TChanID channel, CCharacter * user, bool out
TDataSetRow senderRow = TheDataset.getDataSetRow(user->getId()); TDataSetRow senderRow = TheDataset.getDataSetRow(user->getId());
if (outputToSys) if (outputToSys)
{ {
CCharacter::sendDynamicSystemMessage( user->getId(), "WHO_CHANNEL_INTRO" ); string channelName = DynChatEGS.getChanNameFromID(channel);
//players = "Players in channel \"" + getUserDynChannel(channel) + "\": " + players;
SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal); SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
params[0].Literal = channelName;
CCharacter::sendDynamicSystemMessage( user->getId(), "WHO_CHANNEL_INTRO" );
params[0].Literal = players; params[0].Literal = players;
CCharacter::sendDynamicSystemMessage( user->getId(), "LITERAL", params ); CCharacter::sendDynamicSystemMessage( user->getId(), "LITERAL", params );
} }
@ -522,14 +523,14 @@ void CPVPManager2::removeFactionChannelForCharacter(TChanID channel, CCharacter
_CharacterUserChannels.insert(make_pair(user->getId(), currentChannels)); _CharacterUserChannels.insert(make_pair(user->getId(), currentChannels));
} }
} }
}
TChannelsCharacter::iterator cit = _UserChannelCharacters.find(channel); TChannelsCharacter::iterator cit = _UserChannelCharacters.find(channel);
if (cit != _UserChannelCharacters.end()) if (cit != _UserChannelCharacters.end())
{ {
std::vector<NLMISC::CEntityId> lst = _UserChannelCharacters[channel]; std::vector<NLMISC::CEntityId> lst = _UserChannelCharacters[channel];
lst.erase(find(lst.begin(), lst.end(), user->getId())); lst.erase(find(lst.begin(), lst.end(), user->getId()));
_UserChannelCharacters[channel] = lst; _UserChannelCharacters[channel] = lst;
}
} }
} }
} }
@ -642,13 +643,11 @@ void CPVPManager2::setPVPModeInMirror( const CCharacter * user ) const
} }
} }
CMirrorPropValue<TYPE_PVP_MODE> propPvpMode( TheDataset, user->getEntityRowId(), DSPropertyPVP_MODE ); //CMirrorPropValue<TYPE_PVP_MODE> propPvpMode( TheDataset, user->getEntityRowId(), DSPropertyPVP_MODE );
CMirrorPropValue<TYPE_EVENT_FACTION_ID> propPvpMode2( TheDataset, user->getEntityRowId(), DSPropertyEVENT_FACTION_ID ); CMirrorPropValue<TYPE_EVENT_FACTION_ID> propPvpMode( TheDataset, user->getEntityRowId(), DSPropertyEVENT_FACTION_ID );
if (propPvpMode.getValue() != pvpMode) if (propPvpMode.getValue() != pvpMode)
{ {
nlinfo("New pvp Mode : %d", pvpMode);
propPvpMode = pvpMode; propPvpMode = pvpMode;
propPvpMode2 = pvpMode;
} }
} }
@ -775,7 +774,6 @@ bool CPVPManager2::isCurativeActionValid( CCharacter * actor, CEntityBase * targ
PVP_RELATION::TPVPRelation pvpRelation = getPVPRelation( actor, target, true ); PVP_RELATION::TPVPRelation pvpRelation = getPVPRelation( actor, target, true );
bool actionValid; bool actionValid;
nlinfo("Pvp relation = %d", pvpRelation);
switch( pvpRelation ) switch( pvpRelation )
{ {
case PVP_RELATION::Ally : case PVP_RELATION::Ally :

View file

@ -45,6 +45,74 @@ using namespace NLNET;
namespace GUS namespace GUS
{ {
//-----------------------------------------------------------------------------
// cleanPath - convert a path to standardised format
//-----------------------------------------------------------------------------
CSString cleanPath(const CSString& path,bool addTrailingSlash)
{
CSString result;
// split the path up into its component elements
CVectorSString pathComponents;
path.unquoteIfQuoted().splitByOneOfSeparators("/\\",pathComponents,false,false,true,false,true);
// iterate over path components collapsing '.' and '..' entries
for (uint32 i=0;i<pathComponents.size();++i)
{
// skip "." entries
if (pathComponents[i]==".")
{
pathComponents[i].clear();
continue;
}
// deal with ".."
if (pathComponents[i]=="..")
{
// run back through our component list looking for an element to remove
uint32 j;
for (j=i;j--;)
{
if (!pathComponents[j].empty())
break;
}
// if we found an element then remove it and the '..' as well
if (j!=~0u)
{
pathComponents[j].clear();
pathComponents[i].clear();
}
continue;
}
}
// treat the special case where oriinal path started with a '/' or '//'
if (path.left(1)=="/" || path.left(1)=="\\")
{
result= (path.left(2).right(1)=="/" || path.left(2).right(1)=="\\")? "//": "/";
}
// concatenate the path bits
for (uint32 i=0;i<pathComponents.size();++i)
{
if (!pathComponents[i].empty())
{
result+= pathComponents[i];
result+= '/';
}
}
// if we're not supposed to have a trailing slash then get rid of the one that's added by default
if (addTrailingSlash==false && path.right(1)!='/' && path.right(1)!='\\')
{
result.resize(result.size()-1);
}
return result;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// private routines for layer 5 service tracking // private routines for layer 5 service tracking
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -39,6 +39,27 @@ namespace GUS
// handy utilities // handy utilities
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Clean a path performing the following operations:
// - convert '\\' characters to '/'
// - replace '//' strings in the middle of the path with '/'
// - remove '.' directory entries
// - colapse '..' directory entries (removing parent entries)
// - append a final '/' (optionally)
//
// examples:
// - a:/bcd/efg/ => a:/bcd/efg/ (no change)
// - a:\bcd\efg => a:/bcd/efg/
// - \bcd\\efg => /bcd/efg/
// - \\bcd\efg => //bcd/efg/
// - \bcd\.\efg => /bcd/efg/
// - \bcd\..\efg => /efg/
// - bcd\..\efg => efg/
// - bcd\..\..\efg => ../efg/
// - \bcd\..\..\efg => /efg/ (NOTE: the redundant '..' entry is lost due to leading '\')
//
NLMISC::CSString cleanPath(const NLMISC::CSString& path,bool addTrailingSlash);
// execute a command on a remote service // execute a command on a remote service
void executeRemoteCommand(NLNET::TServiceId sid,const NLMISC::CSString& cmdLine); void executeRemoteCommand(NLNET::TServiceId sid,const NLMISC::CSString& cmdLine);
void executeRemoteCommand(const char* serviceName,const NLMISC::CSString& cmdLine); void executeRemoteCommand(const char* serviceName,const NLMISC::CSString& cmdLine);