Changed: #1433 Merge changes from patch 1.13

This commit is contained in:
kervala 2012-03-04 14:01:11 +01:00
parent 41551e3026
commit 71b7cb9ef0
86 changed files with 4372 additions and 818 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -48,6 +48,7 @@ class CMissionStepKillFauna : public IMissionStepTemplate
{
struct CSubStep
{
string Dynamic;
CSheetId Sheet;
uint16 Quantity;
};
@ -56,7 +57,7 @@ class CMissionStepKillFauna : public IMissionStepTemplate
_SourceLine = line;
_Place = 0xFFFF;
bool ret = true;
if ( script.size() < 2 || script.size() > 3)
if (script.size() < 2 || script.size() > 3)
{
MISLOGSYNTAXERROR("<creature> <quantity> *[; <creature> <quantity>] [: <place>]");
return false;

View file

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

View file

@ -102,6 +102,8 @@ uint32 IMissionStepTemplate::sendRpStepText(CCharacter * user,const std::vector<
uint nbSteps = 0;
const std::string* textPtr = NULL;
_User = user;
if ( !_RoleplayText.empty() )
{
// build the param list
@ -143,6 +145,8 @@ uint32 IMissionStepTemplate::sendStepText(CCharacter * user,const std::vector<ui
uint nbSteps = 0;
const std::string* textPtr = NULL;
_User = user;
// build the param list
getTextParams(nbSteps,(const std::string *&)textPtr,params,stepStates);

View file

@ -41,7 +41,7 @@ public:
//@{
/// ctor
inline IMissionStepTemplate()
:_OOOStepIndex(0xFFFFFFFF),_Any(false),_Displayed(true),_IconDisplayedOnStepNPC(true),_IsInOverridenOOO(false) {}
:_OOOStepIndex(0xFFFFFFFF),_Any(false),_Displayed(true),_IconDisplayedOnStepNPC(true),_IsInOverridenOOO(false),_User(NULL) {}
//BRIANCODE my appologies, need access to this data from CMissionStepGiveItem
struct CSubStep
@ -164,7 +164,8 @@ protected:
bool _AddDefaultParams;
/// flag set to true if the step is in an OOO block which text wad overriden
bool _IsInOverridenOOO;
/// Player running the mission
CCharacter * _User;
};

View file

@ -1357,7 +1357,6 @@ uint32 CMissionTemplate::testPrerequisits( CCharacter * user, CPrerequisitInfos
returnValue = MISSION_DESC::PreReqFail;
logOnFail = false;*/
}
}
// check non replayable missions
if( !Tags.Replayable )
@ -1387,7 +1386,6 @@ uint32 CMissionTemplate::testPrerequisits( CCharacter * user, CPrerequisitInfos
logOnFail = false;*/
}
}
}
else
{
@ -1474,7 +1472,6 @@ uint32 CMissionTemplate::testPrerequisits( CCharacter * user, CPrerequisitInfos
}
if (guild->isMissionSuccessfull(templ->Alias))
break;
}
else if ( templ->Type == MISSION_DESC::Solo )
{
@ -1534,7 +1531,6 @@ uint32 CMissionTemplate::testPrerequisits( CCharacter * user, CPrerequisitInfos
break;
/*if (!guild || !guild->isMissionSuccessfull(templ->Alias))
break;*/
}
else if ( templ->Type == MISSION_DESC::Solo )
{
@ -1590,7 +1586,6 @@ uint32 CMissionTemplate::testPrerequisits( CCharacter * user, CPrerequisitInfos
{
/// todo guild mission
CGuild* guild = CGuildManager::getInstance()->getGuildFromId( user->getGuildId() );
if ( !guild )
{
@ -1606,7 +1601,6 @@ uint32 CMissionTemplate::testPrerequisits( CCharacter * user, CPrerequisitInfos
}
if (k != guild->getMissions().size())
break;
}
else if ( templ->Type == MISSION_DESC::Solo )
{
@ -1702,9 +1696,7 @@ uint32 CMissionTemplate::testPrerequisits( CCharacter * user, CPrerequisitInfos
if ( templ->Type == MISSION_DESC::Guild )
{
/// todo guild mission
CGuild* guild = CGuildManager::getInstance()->getGuildFromId( user->getGuildId() );
if(!guild)
break;
@ -1717,7 +1709,6 @@ uint32 CMissionTemplate::testPrerequisits( CCharacter * user, CPrerequisitInfos
}
if (k == guild->getMissions().size())
break;
}
else if ( templ->Type == MISSION_DESC::Solo )
{

View file

@ -1096,10 +1096,22 @@ public:
// this is a special user, store it in the appropriate container
_OnlineSpecialEntities[cci.getPrivilege()].insert(charEid);
}
// Update LastPlayedDate
ICharacter *character = ICharacter::getInterface(IPlayerManager::getInstance().getActiveChar(uint32(charEid.getShortId()>>4)), true);
if (character)
character->setLastConnectionDate(cci.getlastConnectionDate());
}
else
{
nldebug(" Char %s has disconnected", charEid.toString().c_str());
// Update LastPlayedDate
ICharacter *character = ICharacter::getInterface(IPlayerManager::getInstance().getActiveChar(uint32(charEid.getShortId()>>4)), true);
if (character)
character->setLastConnectionDate(0);
// this character disconnected
_OnlineEntities.erase(charEid);

View file

@ -84,7 +84,7 @@ CVariable<bool> UseProxyMoneyForOutpostCosts("egs", "UseProxyMoneyForOutpostCost
CVariable<uint32> OutpostStateTimeOverride("egs", "OutpostStateTimeOverride", "Each state can be set to a shorter time in seconds, 0 means default computed value", true, 0, true );
CVariable<uint32> OutpostJoinPvpTimer("egs", "OutpostJoinPvpTimer", "Max time the player has to answer the JoinPvp Window, in seconds", 10, 0, true );
CVariable<uint32> NumberDayFactorGuildNeedForChallengeOutpost("egs","NumberDayFactorGuildNeedForChallengeOutpost","Nombre de 'level outpost / factor' jours d'existance que la guilde doit avoir pour pouvoir challenger un outpost",10,0,true);
CVariable<sint32> NumberDaysMinusOutpostLevelForChallenge("egs","NumberDaysMinusOutpostLevelForChallenge", "Nombre à enlever au level du oupost pour avoir l'ancieneté requise pour challenger un outpost",50,0,true);
CVariable<sint32> NumberDaysMinusOutpostLevelForChallenge("egs","NumberDaysMinusOutpostLevelForChallenge", "Number to substract from outpost level to get oldness required to challenge an outpost",50,0,true);
extern CPlayerManager PlayerManager;
@ -1463,49 +1463,54 @@ PVP_RELATION::TPVPRelation COutpost::getPVPRelation( CCharacter * user, CEntityB
if( IsRingShard )
return PVP_RELATION::Neutral;
bool targetSafe = false;
bool actorSafe = false;
if( target->getOutpostAlias() == 0 )
{
return PVP_RELATION::Neutral;
}
else
{
CCharacter * pTarget = dynamic_cast<CCharacter*>(target);
if(pTarget)
if (pTarget == 0)
return PVP_RELATION::Unknown;
if (CPVPManager2::getInstance()->inSafeZone(pTarget->getPosition()))
{
if( CPVPManager2::getInstance()->inSafeZone( pTarget->getPosition() ) )
{
if( pTarget->getSafeInPvPSafeZone() )
{
return PVP_RELATION::NeutralPVP;
}
}
}
if( CPVPManager2::getInstance()->inSafeZone( user->getPosition() ) )
{
if( user->getSafeInPvPSafeZone() )
{
return PVP_RELATION::NeutralPVP;
}
if (pTarget->getSafeInPvPSafeZone())
targetSafe = true;
}
if( user->getOutpostAlias() != target->getOutpostAlias() )
if( CPVPManager2::getInstance()->inSafeZone(user->getPosition()))
{
if( user->getSafeInPvPSafeZone())
actorSafe = true;
}
// One is safe but not other => NeutralPVP
if ((targetSafe && !actorSafe) || (actorSafe && !targetSafe)) {
return PVP_RELATION::NeutralPVP;
}
else
if( user->getOutpostAlias() == target->getOutpostAlias() )
{
if( user->getOutpostSide() != target->getOutpostSide() )
{
if (!targetSafe && !actorSafe)
{
CPVPManager2::getInstance()->setPVPOutpostEnemyReminder( true );
return PVP_RELATION::Ennemy;
}
}
else
{
CPVPManager2::getInstance()->setPVPOutpostAllyReminder( true );
return PVP_RELATION::Ally;
}
}
}
return PVP_RELATION::NeutralPVP;
} // getPVPRelation //

View file

@ -210,7 +210,7 @@ CVariable<uint32> SpawnedDeadMektoubDelay("egs","SpawnedDeadMektoubDelay", "nb
CVariable<bool> ForceQuarteringRight("egs","ForceQuarteringRight", "Allow anyone to quarter a dead creature", false, 0, true );
CVariable<bool> AllowAnimalInventoryAccessFromAnyStable("egs", "AllowAnimalInventoryAccessFromAnyStable", "If true a player can access to his animal inventory (if the animal is inside a stable) from any stable over the world", true, 0, true );
CVariable<uint32> FreeTrialSkillLimit("egs", "FreeTrialSkillLimit", "Level limit for characters belonging to free trial accounts", 125,0,true);
CVariable<uint32> CraftFailureProbaMpLost("egs", "CraftFailureProbaMpLost", "Probabilité de destruction de chaque MP en cas d'echec du craft", 50,0,true);
CVariable<uint32> CraftFailureProbaMpLost("egs", "CraftFailureProbaMpLost", "Probability de destruction de chaque MP en cas d'echec du craft", 50,0,true);
// Number of login stats kept for a character
@ -411,6 +411,8 @@ CCharacter::CCharacter(): CEntityBase(false),
// pvp for player with privilege inactive
_PriviledgePvp = false;
// full pvp
_FullPvp = false;
// aggroable undefined
_Aggroable = true;
_AggroableOverride = -1;
@ -421,12 +423,17 @@ CCharacter::CCharacter(): CEntityBase(false),
for (uint i = 0 ; i < (PVP_CLAN::EndClans-PVP_CLAN::BeginClans+1); ++i)
_FactionPoint[i] = 0;
_PvpPoint = 0;
_PVPFlagLastTimeChange = 0;
_PVPFlagTimeSettedOn = 0;
_PvPDatabaseCounter = 0;
_PVPFlag = false;
_PVPRecentActionTime = 0;
_Organization = 0;
_OrganizationStatus = 0;
_OrganizationPoints = 0;
// do not start berserk
_IsBerserk = false;
@ -493,6 +500,9 @@ CCharacter::CCharacter(): CEntityBase(false),
///init teamId
_TeamId= CTEAM::InvalidTeamId;
///init LeagueId
_LeagueId = TChanID::Unknown;
// init combat flags
_CombatEventFlagTicks.resize(32);
for( uint i=0; i<32; ++i )
@ -641,6 +651,10 @@ CCharacter::CCharacter(): CEntityBase(false),
_CurrentSessionId = _SessionId;
_PvPSafeZoneActive = false;
_PVPSafeLastTimeChange = CTickEventHandler::getGameCycle();
_PVPSafeLastTime = false;
_PVPInSafeZoneLastTime = false;
// For client/server contact list communication
_ContactIdPool= 0;
@ -653,6 +667,10 @@ CCharacter::CCharacter(): CEntityBase(false),
_LastTickNpcControlUpdated = CTickEventHandler::getGameCycle();
_LastWebCommandIndex = 0;
_CustomMissionsParams.clear();
initDatabase();
} // CCharacter //
@ -773,55 +791,20 @@ void CCharacter::initPDStructs()
void CCharacter::updatePVPClanVP() const
{
TYPE_PVP_CLAN propPvpClanTemp = 0;
uint32 maxFameCiv = 0;
uint8 civOfMaxFame = 255;
uint32 maxFameCult = 0;
uint8 cultOfMaxFame = 255;
for (uint8 fameIdx = 0; fameIdx < 7; fameIdx++)
{
sint32 fame = CFameInterface::getInstance().getFameIndexed(_Id, fameIdx);
if (fameIdx < 4)
{
if ((uint32)abs(fame) >= maxFameCiv)
{
civOfMaxFame = fameIdx;
maxFameCiv = abs(fame);
}
}
if (_LeagueId != DYN_CHAT_INVALID_CHAN)
propPvpClanTemp = 1+(uint32)(_LeagueId.getShortId());
else
{
if ((uint32)abs(fame) >= maxFameCult)
{
cultOfMaxFame = fameIdx - 4;
maxFameCult = abs(fame);
}
}
propPvpClanTemp = 0;
if (fame >= PVPFameRequired*6000)
{
propPvpClanTemp |= (TYPE_PVP_CLAN(1) << (2*TYPE_PVP_CLAN(fameIdx)));
}
else if (fame <= -PVPFameRequired*6000)
{
propPvpClanTemp |= (TYPE_PVP_CLAN(1) << ((2*TYPE_PVP_CLAN(fameIdx))+1));
}
if (getPvPRecentActionFlag())
{
uint8 flagAlly = (_PVPFlagAlly & (1 << TYPE_PVP_CLAN(fameIdx))) >> TYPE_PVP_CLAN(fameIdx);
uint8 flagEnemy = (_PVPFlagEnemy & (1 << TYPE_PVP_CLAN(fameIdx))) >> TYPE_PVP_CLAN(fameIdx);
propPvpClanTemp |= flagAlly << (2*TYPE_PVP_CLAN(fameIdx));
propPvpClanTemp |= flagEnemy << ((2*TYPE_PVP_CLAN(fameIdx))+1);
}
}
propPvpClanTemp |= TYPE_PVP_CLAN(civOfMaxFame) << (2*TYPE_PVP_CLAN(7));
propPvpClanTemp |= TYPE_PVP_CLAN(cultOfMaxFame) << (2*TYPE_PVP_CLAN(8));
CMirrorPropValue<TYPE_PVP_CLAN> propPvpClan( TheDataset, TheDataset.getDataSetRow(_Id), DSPropertyPVP_CLAN );
propPvpClan = (uint32)propPvpClanTemp;
if (propPvpClan.getValue() != propPvpClanTemp)
{
propPvpClan = propPvpClanTemp;
propPvpClan.setChanged();
}
}
/*
TYPE_PVP_CLAN CCharacter::getPVPFamesAllies()
{
TYPE_PVP_CLAN propPvpClanTemp = 0;
@ -843,7 +826,7 @@ TYPE_PVP_CLAN CCharacter::getPVPFamesEnemies()
return propPvpClanTemp | _PVPFlagEnemy;
return propPvpClanTemp;
}
*/
//-----------------------------------------------
// addPropertiesToMirror :
@ -1464,6 +1447,29 @@ uint32 CCharacter::tickUpdate()
{
H_AUTO(CharacterUpdatePVPMode);
if (_PVPSafeLastTimeChange + 20 < CTickEventHandler::getGameCycle())
{
bool update = false;
_PVPSafeLastTimeChange = CTickEventHandler::getGameCycle();
if (_PVPSafeLastTime != getSafeInPvPSafeZone())
{
_PVPSafeLastTime = !_PVPSafeLastTime;
update = true;
}
if (_PVPInSafeZoneLastTime != CPVPManager2::getInstance()->inSafeZone(getPosition()))
{
_PVPInSafeZoneLastTime = !_PVPInSafeZoneLastTime;
update = true;
}
if (update) {
CPVPManager2::getInstance()->setPVPModeInMirror(this);
updatePVPClanVP();
}
}
if( _HaveToUpdatePVPMode )
{
const TGameCycle waitTime = _PVPFlag ? TimeForSetPVPFlag.get() : TimeForPVPFlagOff.get();
@ -2865,7 +2871,9 @@ void CCharacter::postLoadTreatment()
{
_PlayerPets[ i ].Slot = INVENTORIES::INVALID_INVENTORY_SLOT;
}
uint32 slot = _PlayerPets[ i ].initLinkAnimalToTicket( this );
sendPetCustomNameToClient(i);
uint32 slot = _PlayerPets[ i ].initLinkAnimalToTicket( this, i );
if( slot < INVENTORIES::NbPackerSlots )
{
tickets[ slot ] = true;
@ -3625,7 +3633,7 @@ void CCharacter::setTargetBotchatProgramm( CEntityBase * target, const CEntityId
// _PropertyDatabase.setProp( toString("TARGET:CONTEXT_MENU:MISSIONS_OPTIONS:%u:PLAYER_GIFT_NEEDED",i) , 0 );
CBankAccessor_PLR::getTARGET().getCONTEXT_MENU().getMISSIONS_OPTIONS().getArray(i).setPLAYER_GIFT_NEEDED(_PropertyDatabase, 0 );
// _PropertyDatabase.setProp( toString("TARGET:CONTEXT_MENU:MISSIONS_OPTIONS:%u:PRIORITY",i), 0 );
CBankAccessor_PLR::getTARGET().getCONTEXT_MENU().getMISSIONS_OPTIONS().getArray(i).setPRIORITY(_PropertyDatabase, 0 );
CBankAccessor_PLR::getTARGET().getCONTEXT_MENU().getMISSIONS_OPTIONS().getArray(i).setPRIORITY(_PropertyDatabase, 2 );
i++;
}
}
@ -4563,13 +4571,31 @@ bool CCharacter::fillFaberMaterialArray( vector<CFaberMsgItem>& materialsSelecte
lowerMaterialQuality = USHRT_MAX;
for( uint s = 0; s < materialsSelectedForFaber.size(); ++s )
{
bool bOk = false;
CInventoryPtr pInv = NULL;
if( materialsSelectedForFaber[ s ].getInvId() >= INVENTORIES::NUM_INVENTORY )
{
// Also allow crafting from player's room
if (materialsSelectedForFaber[ s ].getInvId() == INVENTORIES::player_room)
{
if (getRoomInterface().isValid() && getRoomInterface().canUseInventory(this, this))
{
pInv = getRoomInterface().getInventory();
bOk = true;
}
}
if ( ! bOk)
{
nlwarning("<CCharacter::fillFaberMaterialArray> CFaberMsgItem[%d] sended by client contains an invalid inventory index %d", s, materialsSelectedForFaber[ s ].getInvId() );
return false;
}
}
else
{
pInv = _Inventory[ materialsSelectedForFaber[ s ].getInvId() ];
}
CInventoryPtr pInv = _Inventory[ materialsSelectedForFaber[ s ].getInvId() ];
if( materialsSelectedForFaber[ s ].IndexInInv >= pInv->getSlotCount() )
{
nlwarning("<CCharacter::fillFaberMaterialArray> CFaberMsgItem[%d] sended by client contains an invalid index %d for inventory %d", s, materialsSelectedForFaber[ s ].IndexInInv, materialsSelectedForFaber[ s ].getInvId() );
@ -5170,6 +5196,9 @@ bool CCharacter::addCharacterAnimal( const CSheetId& PetTicket, uint32 Price, CG
{
_PlayerPets[ i ] = pet;
pet.ItemPtr->setPetIndex(i);
pet.Slot = ptr->getInventorySlot();
// init pet inventory
const uint32 petMaxWeight = 0xFFFFFFFF; // no weight limit
const uint32 petMaxBulk = _PlayerPets[ i ].getAnimalMaxBulk();
@ -5433,6 +5462,7 @@ bool CCharacter::spawnWaitingCharacterAnimalNear( uint index, const SGameCoordin
msg.CharacterMirrorRow = _EntityRowId;
msg.PetSheetId = _PlayerPets[ index ].PetSheetId;
msg.PetIdx = index;
msg.CustomName = _PlayerPets[ index ].CustomName;
msg.AIInstanceId = (uint16)destAIInstance;
CWorldInstances::instance().msgToAIInstance( msg.AIInstanceId, msg);
// The row will be received in AnimalSpawned()
@ -5544,6 +5574,7 @@ bool CCharacter::spawnCharacterAnimal(uint index )
msg.CharacterMirrorRow = _EntityRowId;
msg.PetSheetId = _PlayerPets[ index ].PetSheetId;
msg.PetIdx = index;
msg.CustomName = _PlayerPets[ index ].CustomName;
CVector pos;
pos.x = msg.Coordinate_X * 0.001f;
@ -6723,6 +6754,38 @@ void CCharacter::sendAnimalCommand( uint8 petIndexCode, uint8 command )
}
}
void CCharacter::setAnimalName( uint8 petIndex, ucstring customName )
{
if (petIndex < 0 || petIndex >= MAX_INVENTORY_ANIMAL)
{
nlwarning("<CCharacter::setAnimalName> Incorect animal index '%d'.", petIndex);
return;
}
CPetAnimal& animal = _PlayerPets[petIndex];
animal.setCustomName(customName);
sendPetCustomNameToClient(petIndex);
TDataSetRow row = animal.SpawnedPets;
NLNET::CMessage msgout("CHARACTER_NAME");
msgout.serial(row);
msgout.serial(customName);
sendMessageViaMirror("IOS", msgout);
}
//-----------------------------------------------------------------------------
void CCharacter::sendPetCustomNameToClient(uint8 petIndex)
{
uint32 textId = 0;
if (_PlayerPets[petIndex].CustomName.length() > 0)
{
SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
params[0].Literal= _PlayerPets[petIndex].CustomName;
uint32 userId = PlayerManager.getPlayerId(_Id);
textId = STRING_MANAGER::sendStringToUser(userId, "LITERAL", params);
}
CBankAccessor_PLR::getPACK_ANIMAL().getBEAST(petIndex).setNAME(_PropertyDatabase, textId);
}
//-----------------------------------------------
@ -6842,6 +6905,7 @@ double CCharacter::addXpToSkillInternal( double XpGain, const std::string& ContS
}
// check whether this character is on a free trial account
bool bFreeTrialLimitReached = false;
CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( getId() ));
BOMB_IF(p == NULL,"Failed to find player record for character: "<<getId().toString(),return 0.0);
if (p->isTrialPlayer())
@ -6853,7 +6917,7 @@ double CCharacter::addXpToSkillInternal( double XpGain, const std::string& ContS
SM_STATIC_PARAMS_1(params, STRING_MANAGER::skill);
params[0].Enum = skillEnum;
PHRASE_UTILITIES::sendDynamicSystemMessage(getEntityRowId(), "PROGRESS_FREE_TRIAL_LIMIT", params);
return 0.0;
bFreeTrialLimitReached = true;
}
}
@ -6893,6 +6957,11 @@ double CCharacter::addXpToSkillInternal( double XpGain, const std::string& ContS
// update death penalty
_DeathPenalties->addXP( *this, skillEnum, XpGain);
if (bFreeTrialLimitReached)
{
return 0.0;
}
// if no remaining XPGain, return
if (XpGain == 0.0f)
return 0.0;
@ -8800,7 +8869,7 @@ void CCharacter::setDatabase()
_IneffectiveAuras.activate();
_ConsumableOverdoseEndDates.activate();
// init the RRPs
RingRewardPoints.initDb();
//RingRewarsdPoints.initDb();
}// setDatabase //
@ -8862,7 +8931,7 @@ void CCharacter::startTradeItemSession( uint16 session )
nlwarning("fame %u is INVALID",(uint)bot->getRace() );
fame = MinFameToTrade;
}
else if ( fame < MinFameToTrade )
else if ( fame < MinFameToTrade && bot->getOrganization() != getOrganization() )
{
SM_STATIC_PARAMS_1(params, STRING_MANAGER::bot);
params[0].setEIdAIAlias( _CurrentInterlocutor, CAIAliasTranslator::getInstance()->getAIAlias(_CurrentInterlocutor) );
@ -8961,14 +9030,13 @@ void CCharacter::startTradePhrases(uint16 session)
return;
}
// *** Check the player has sufficient fame to Trade with Bot.
sint32 fame = CFameInterface::getInstance().getFameIndexed( _Id, bot->getForm()->getFaction() );
if ( fame == NO_FAME )
{
nlwarning("fame %u is INVALID",(uint)bot->getRace() );
}
if ( fame < MinFameToTrade )
if ( fame < MinFameToTrade && bot->getOrganization() != getOrganization() )
{
SM_STATIC_PARAMS_1(params, STRING_MANAGER::bot);
params[0].setEIdAIAlias( _CurrentInterlocutor, CAIAliasTranslator::getInstance()->getAIAlias(_CurrentInterlocutor) );
@ -9738,7 +9806,7 @@ void CCharacter::sellItem( INVENTORIES::TInventory inv, uint32 slot, uint32 quan
nlwarning("fame %u is INVALID",(uint)bot->getRace() );
fame = MinFameToTrade;
}
else if ( fame < MinFameToTrade )
else if ( fame < MinFameToTrade && bot->getOrganization() != getOrganization() )
{
SM_STATIC_PARAMS_1(params, STRING_MANAGER::bot);
params[0].setEIdAIAlias( _CurrentInterlocutor, CAIAliasTranslator::getInstance()->getAIAlias(_CurrentInterlocutor) );
@ -10087,6 +10155,84 @@ void CCharacter::initFactionPointDb()
}
}
//-----------------------------------------------
// setPvpPoint : set the number of pvp point
//
//-----------------------------------------------
void CCharacter::setPvpPoint(uint32 nbPt)
{
_PvpPoint = nbPt;
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(0).setVALUE(_PropertyDatabase, nbPt );
}
//-----------------------------------------------
// getPvpPoint : get the number of pvp point
//
//-----------------------------------------------
uint32 CCharacter::getPvpPoint()
{
return _PvpPoint;
}
//-----------------------------------------------------------------------------
void CCharacter::initPvpPointDb()
{
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(0).setVALUE(_PropertyDatabase, _PvpPoint );
}
//-----------------------------------------------------------------------------
void CCharacter::setOrganization(uint32 org)
{
if (org == _Organization)
return;
_Organization = org;
_OrganizationStatus = 0;
_OrganizationPoints = 0;
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(1).setVALUE(_PropertyDatabase, _Organization );
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(2).setVALUE(_PropertyDatabase, _OrganizationStatus );
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(3).setVALUE(_PropertyDatabase, _OrganizationPoints );
}
//-----------------------------------------------------------------------------
void CCharacter::setOrganizationStatus(uint32 status)
{
_OrganizationStatus = status;
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(2).setVALUE(_PropertyDatabase, _OrganizationStatus );
}
//-----------------------------------------------------------------------------
void CCharacter::changeOrganizationStatus(sint32 status)
{
if (status < 0 && abs(status) > _OrganizationStatus)
_OrganizationStatus = 0;
else
_OrganizationStatus += status;
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(2).setVALUE(_PropertyDatabase, _OrganizationStatus );
}
//-----------------------------------------------------------------------------
void CCharacter::changeOrganizationPoints(sint32 points)
{
if (points < 0 && abs(points) > _OrganizationPoints)
_OrganizationPoints = 0;
else
_OrganizationPoints += points;
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(3).setVALUE(_PropertyDatabase, _OrganizationPoints );
}
//-----------------------------------------------------------------------------
void CCharacter::initOrganizationInfos()
{
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(1).setVALUE(_PropertyDatabase, _Organization );
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(2).setVALUE(_PropertyDatabase, _OrganizationStatus );
CBankAccessor_PLR::getUSER().getRRPS_LEVELS(3).setVALUE(_PropertyDatabase, _OrganizationPoints );
}
//-----------------------------------------------------------------------------
void CCharacter::sendFactionPointGainMessage(PVP_CLAN::TPVPClan clan, uint32 fpGain)
{
@ -10176,6 +10322,16 @@ void CCharacter::exchangeProposal()
return;
}
// If not a privileged player and in ignorelist, don't trade
if ( !haveAnyPrivilege() && c->hasInIgnoreList( getId() ) )
{
params.resize(1);
params[0].Type = STRING_MANAGER::player;
params[0].setEIdAIAlias( c->getId(), CAIAliasTranslator::getInstance()->getAIAlias(c->getId()) );
CCharacter::sendDynamicSystemMessage(_EntityRowId, "EXCHANGE_DECLINE", params);
return;
}
//set the target's exchange asker, and inform the target
c->_ExchangeAsker = _Id;
@ -11666,7 +11822,7 @@ bool CCharacter::processMissionEventList( std::list< CMissionEvent* > & eventLis
// If the mission is not for guild members we just instanciate it
if (!missionForGuild)
CMissionManager::getInstance()->instanciateMission(this, mission, giver ,eventList, mainMission);
CMissionManager::getInstance()->instanciateMission(this, mission, giver, eventList, mainMission);
else
{
// We find the guild and each guild members and we instanciate the mission for them
@ -11681,7 +11837,7 @@ bool CCharacter::processMissionEventList( std::list< CMissionEvent* > & eventLis
nlwarning( "<MISSIONS>cant find user %s", it->first.toString().c_str() );
continue;
}
CMissionManager::getInstance()->instanciateMission(guildUser, mission, giver ,eventList, mainMission);
CMissionManager::getInstance()->instanciateMission(guildUser, mission, giver, eventList, mainMission);
}
}
}
@ -13430,7 +13586,45 @@ void CCharacter::sendUrl(const string &url, const string &salt)
PlayerManager.sendImpulseToClient(getId(), "USER:POPUP", titleId, textId);
}
void CCharacter::validateDynamicMissionStep(const string &url)
{
sendUrl(url+"&player_eid="+getId().toString()+"&event=mission_step_finished", getSalt());
}
/// set custom mission param
void CCharacter::setCustomMissionParams(const string &missionName, const string &params)
{
_CustomMissionsParams[missionName] = params;
}
/// add custom mission param
void CCharacter::addCustomMissionParam(const string &missionName, const string &param)
{
if (!_CustomMissionsParams.empty() && _CustomMissionsParams.find(missionName) != _CustomMissionsParams.end())
_CustomMissionsParams[missionName] += ","+param;
else
_CustomMissionsParams[missionName] = param;
}
/// get custom mission params
vector<string> CCharacter::getCustomMissionParams(const string &missionName)
{
vector<string> params;
if (_CustomMissionsParams.empty())
{
return params;
}
if (!_CustomMissionsParams.empty() && _CustomMissionsParams.find(missionName) != _CustomMissionsParams.end())
{
if (!_CustomMissionsParams[missionName].empty())
NLMISC::splitString(_CustomMissionsParams[missionName], ",", params);
}
return params;
}
// !!! Deprecated !!!
void CCharacter::addWebCommandCheck(const string &url, const string &data, const string &salt)
{
uint webCommand = getWebCommandCheck(url);
@ -13494,6 +13688,7 @@ void CCharacter::addWebCommandCheck(const string &url, const string &data, const
}
}
// !!! Deprecated !!!
uint CCharacter::getWebCommandCheck(const string &url)
{
CInventoryPtr inv = getInventory(INVENTORIES::bag);
@ -13528,6 +13723,7 @@ uint CCharacter::getWebCommandCheck(const string &url)
return INVENTORIES::NbBagSlots;
}
// !!! Deprecated !!!
uint CCharacter::checkWebCommand(const string &url, const string &data, const string &hmac, const string &salt)
{
if (salt.empty())
@ -14650,7 +14846,7 @@ void CCharacter::addRoomAccessToPlayer(const NLMISC::CEntityId &id)
//--------------------------------------------------------------
void CCharacter::addPlayerToFriendList(const NLMISC::CEntityId &id)
{
// if player not found
/*// if player not found
if (id == CEntityId::Unknown || PlayerManager.getChar(id)==NULL)
{
if ( ! (IShardUnifierEvent::getInstance() && IShardUnifierEvent::getInstance()->isCharacterOnlineAbroad(id)))
@ -14659,7 +14855,7 @@ void CCharacter::addPlayerToFriendList(const NLMISC::CEntityId &id)
PHRASE_UTILITIES::sendDynamicSystemMessage( _EntityRowId, "OPERATION_OFFLINE");
return;
}
}
}*/
// check not already in list
const uint size = (uint)_FriendsList.size();
@ -14721,6 +14917,82 @@ void CCharacter::addPlayerToFriendList(const NLMISC::CEntityId &id)
}
//--------------------------------------------------------------
// CCharacter::addPlayerToLeagueList() // unused, need more tests
//--------------------------------------------------------------
void CCharacter::addPlayerToLeagueList(const NLMISC::CEntityId &id)
{
// if player not found
/*if (id == CEntityId::Unknown || PlayerManager.getChar(id)==NULL)
{
if ( ! (IShardUnifierEvent::getInstance() && IShardUnifierEvent::getInstance()->isCharacterOnlineAbroad(id)))
{
// player not found => message
PHRASE_UTILITIES::sendDynamicSystemMessage( _EntityRowId, "OPERATION_OFFLINE");
return;
}
}*/
// check not already in list
const uint size = _LeagueList.size();
for ( uint i =0 ; i < size ; ++i)
{
if ( _LeagueList[i].EntityId.getShortId() == id.getShortId())
{
return;
}
}
if(haveAnyPrivilege() == false && PlayerManager.haveAnyPriv(id))
return; // a character without privilege can't add one with privilege.
uint32 playerId = PlayerManager.getPlayerId(id);
// check the two char aren't from the same account
if (playerId == PlayerManager.getPlayerId(_Id))
{
egs_chinfo("Char %s tried to add %s in his friend list but they are from the same account->return", _Id.toString().c_str(), id.toString().c_str());
return;
}
// reference count
contactListRefChange( id, AddedAsLeague);
// add the char to friends
CContactId contactId;
contactId.EntityId= id;
contactId.ContactId= _ContactIdPool++; // create a new Id for client/server communication
_LeagueList.push_back(contactId);
// send create message to client
CMessage msgout( "IMPULSION_ID" );
msgout.serial( _Id );
CBitMemStream bms;
if ( ! GenericMsgManager.pushNameToStream( "TEAM:CONTACT_CREATE", bms) )
{
nlwarning("<CEntityBase::addPlayerToFriendList> Msg name TEAM:CONTACT_CREATE not found");
return;
}
TCharConnectionState onlineStatus = ccs_online;
uint32 nameId = CEntityIdTranslator::getInstance()->getEntityNameStringId(id);
uint8 listIndex = 2;
bms.serial(contactId.ContactId);
bms.serial(nameId);
bms.serialShortEnum(onlineStatus);
bms.serial(listIndex);
msgout.serialBufferWithSize((uint8*)bms.buffer(), bms.length());
CUnifiedNetwork::getInstance()->send( NLNET::TServiceId(_Id.getDynamicId()), msgout );
}
//--------------------------------------------------------------
// CCharacter::addPlayerToIgnoreList()
//--------------------------------------------------------------
@ -14822,6 +15094,23 @@ void CCharacter::removePlayerFromFriendListByIndex(uint16 index)
contactListRefChange( id, RemovedFromFriends);
}
//--------------------------------------------------------------
// CCharacter::removePlayerFromFriendListByIndex() // unused, need more tests
//--------------------------------------------------------------
void CCharacter::removePlayerFromLeagueListByIndex(uint16 index)
{
if (index >= _LeagueList.size())
return;
const CEntityId id = _LeagueList[index].EntityId;
uint32 contactId= _LeagueList[index].ContactId;
// remove entry
_LeagueList.erase(_LeagueList.begin() + index);
sendRemoveContactMessage(contactId, 2);
contactListRefChange( id, RemovedFromLeague);
}
//--------------------------------------------------------------
// CCharacter::removePlayerFromIgnoreListByIndex()
//--------------------------------------------------------------
@ -14901,6 +15190,25 @@ void CCharacter::removePlayerFromFriendListByEntityId(const NLMISC::CEntityId &i
}
}
//--------------------------------------------------------------
// CCharacter::removePlayerFromLeagueListByEntityId() // unused, need more tests
//--------------------------------------------------------------
void CCharacter::removePlayerFromLeagueListByEntityId(const NLMISC::CEntityId &id)
{
if (id == NLMISC::CEntityId::Unknown)
return;
for ( uint i = 0 ; i < _LeagueList.size() ; ++i)
{
if ( _LeagueList[i].EntityId.getShortId() == id.getShortId() )
{
removePlayerFromLeagueListByIndex(i);
break;
}
}
}
//--------------------------------------------------------------
// CCharacter::removePlayerFromIgnoreListByEntityId()
//--------------------------------------------------------------
@ -14934,6 +15242,22 @@ void CCharacter::removePlayerFromFriendListByContactId(uint32 contactId)
}
}
//--------------------------------------------------------------
// CCharacter::removePlayerFromFriendListByContactId() unused, need more tests
//--------------------------------------------------------------
void CCharacter::removePlayerFromLeagueListByContactId(uint32 contactId)
{
for ( uint i = 0 ; i < _LeagueList.size() ; ++i)
{
if ( _LeagueList[i].ContactId == contactId )
{
removePlayerFromLeagueListByIndex(i);
break;
}
}
}
//--------------------------------------------------------------
// CCharacter::removePlayerFromIgnoreListByContactId()
//--------------------------------------------------------------
@ -15329,6 +15653,15 @@ void CCharacter::sendRemoveContactMessage(uint32 contactId, uint8 listNumber)
CUnifiedNetwork::getInstance()->send( NLNET::TServiceId(_Id.getDynamicId()), msgout );
} // sendRemoveContactMessage //
//--------------------------------------------------------------
// CCharacter::setLastConnectionDate()
//--------------------------------------------------------------
void CCharacter::setLastConnectionDate(uint32 date)
{
_LastConnectedDate = date;
}
//--------------------------------------------------------------
// CCharacter::destroyCharacter()
//--------------------------------------------------------------
@ -15476,8 +15809,6 @@ void CCharacter::onConnection()
{
// Add all handledAIGroups for all missions of the player
spawnAllHandledAIGroup();
// add character to event channel if event occurs
CGameEventManager::getInstance().addCharacterToChannelEvent( this );
// update for the unified entity locator
if (IShardUnifierEvent::getInstance() != NULL)
@ -15874,6 +16205,7 @@ void CCharacter::sendEmote( const NLMISC::CEntityId& id, MBEHAV::EBehaviour beha
uint32 txtId = STRING_MANAGER::sendStringToClient( targetRow, phraseCont->TargetTarget, params );
// send emote message to IOS
NLNET::CMessage msgout("EMOTE_PLAYER");
msgout.serial( const_cast<TDataSetRow&>( getEntityRowId() ) );
msgout.serial( targetRow );
msgout.serial(txtId);
sendMessageViaMirror("IOS", msgout);
@ -15884,7 +16216,8 @@ void CCharacter::sendEmote( const NLMISC::CEntityId& id, MBEHAV::EBehaviour beha
uint32 txtId = STRING_MANAGER::sendStringToClient(getEntityRowId(), *self, params );
// send emote message to IOS
NLNET::CMessage msgout("EMOTE_PLAYER");
msgout.serial( const_cast<TDataSetRow&>( getEntityRowId() ) );
msgout.serial( const_cast<TDataSetRow&>( getEntityRowId() ) ); // sender
msgout.serial( const_cast<TDataSetRow&>( getEntityRowId() ) ); // receiver
msgout.serial(txtId);
sendMessageViaMirror("IOS", msgout);
@ -16226,7 +16559,14 @@ NLMISC::TGameCycle CCharacter::getMissionLastSuccess(const CMissionTemplate & te
{
std::map< TAIAlias, TMissionHistory >::iterator it(_MissionHistories.find(templ.Alias));
if (it != _MissionHistories.end())
{
TGameCycle lastSuccessDate = it->second.LastSuccessDate;
if (lastSuccessDate > CTickEventHandler::getGameCycle())
return 0;
return it->second.LastSuccessDate;
}
return 0;
}
@ -17049,6 +17389,9 @@ void CCharacter::setPVPFlag( bool pvpFlag )
// set the new pvp flag and time last change for apply timer delay before this change become effective
if( pvpFlag == false )
{
if (_PVPFlagTimeSettedOn > CTickEventHandler::getGameCycle())
_PVPFlagTimeSettedOn = CTickEventHandler::getGameCycle() - TimeForResetPVPFlag;
if( _PVPFlagTimeSettedOn + TimeForResetPVPFlag > CTickEventHandler::getGameCycle() )
{
// we need wait a minimal of time before reset your pvp tag
@ -17146,13 +17489,6 @@ void CCharacter::setPVPRecentActionFlag(CCharacter *target)
_PVPRecentActionTime = CTickEventHandler::getGameCycle();
if (target != NULL)
{
_PVPFlagAlly |= target->getPVPFamesAllies();
_PVPFlagEnemy |= target->getPVPFamesEnemies();
updatePVPClanVP();
}
// _PropertyDatabase.setProp("CHARACTER_INFO:PVP_FACTION_TAG:FLAG_PVP_TIME_LEFT", _PVPRecentActionTime + PVPActionTimer );
CBankAccessor_PLR::getCHARACTER_INFO().getPVP_FACTION_TAG().setFLAG_PVP_TIME_LEFT(_PropertyDatabase, _PVPRecentActionTime + PVPActionTimer );
@ -17880,7 +18216,7 @@ void CPetAnimal::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
}
//-----------------------------------------------------------------------------
uint32 CPetAnimal::initLinkAnimalToTicket( CCharacter * c )
uint32 CPetAnimal::initLinkAnimalToTicket( CCharacter * c, uint8 index )
{
if( c )
{
@ -17888,6 +18224,8 @@ uint32 CPetAnimal::initLinkAnimalToTicket( CCharacter * c )
if( ( ItemPtr != 0 ) && ( ItemPtr->getStaticForm() != NULL ) && ( ItemPtr->getStaticForm()->Family == ITEMFAMILY::PET_ANIMAL_TICKET ) )
{
// Slot = ItemPtr->getLocSlot();
ItemPtr->setPetIndex(index);
ItemPtr->setCustomName(CustomName);
Slot = ItemPtr->getInventorySlot();
return Slot;
}
@ -17900,6 +18238,8 @@ uint32 CPetAnimal::initLinkAnimalToTicket( CCharacter * c )
{
// Slot = ItemPtr->getLocSlot();
Slot = ItemPtr->getInventorySlot();
ItemPtr->setPetIndex(index);
ItemPtr->setCustomName(CustomName);
return Slot;
}
else
@ -17916,7 +18256,6 @@ uint32 CPetAnimal::initLinkAnimalToTicket( CCharacter * c )
return INVENTORIES::INVALID_INVENTORY_SLOT;
}
//-----------------------------------------------
// getAnimalMaxBulk
//-----------------------------------------------
@ -18697,8 +19036,42 @@ void CCharacter::teleportCharacter( sint32 x, sint32 y)
void CCharacter::setTeamId(uint16 id)
{
_TeamId = id;
updatePVPClanVP();
}
void CCharacter::setLeagueId(TChanID id, bool removeIfEmpty)
{
ucstring name = CEntityIdTranslator::getInstance()->getByEntity(getId());
CEntityIdTranslator::removeShardFromName(name);
// Remove old dynamic channel
if (_LeagueId != DYN_CHAT_INVALID_CHAN)
{
CPVPManager2::getInstance()->broadcastMessage(_LeagueId, string("<INFO>"), name+" -->[]");
PHRASE_UTILITIES::sendDynamicSystemMessage(getEntityRowId(), "TEAM_QUIT_LEAGUE");
DynChatEGS.removeSession(_LeagueId, getEntityRowId());
vector<CEntityId> players;
bool isEmpty = DynChatEGS.getPlayersInChan(_LeagueId, players);
if (isEmpty)
{
if (removeIfEmpty)
DynChatEGS.removeChan(_LeagueId);
}
}
if (id != DYN_CHAT_INVALID_CHAN)
{
PHRASE_UTILITIES::sendDynamicSystemMessage(getEntityRowId(), "TEAM_JOIN_LEAGUE");
DynChatEGS.addSession(id, getEntityRowId(), true);
CPVPManager2::getInstance()->broadcastMessage(id, string("<INFO>"), "<-- "+name);
}
_LeagueId = id;
updatePVPClanVP();
}
//------------------------------------------------------------------------------
@ -18707,6 +19080,12 @@ void CCharacter::setTeamInvitor(const NLMISC::CEntityId & invitorId)
_TeamInvitor = invitorId;
}
//------------------------------------------------------------------------------
void CCharacter::setLeagueInvitor(const NLMISC::CEntityId & invitorId)
{
_LeagueInvitor = invitorId;
}
//------------------------------------------------------------------------------
@ -19871,6 +20250,13 @@ void CCharacter::setPriviledgePVP( bool b )
_PriviledgePvp = b;
}
//------------------------------------------------------------------------------
void CCharacter::setFullPVP( bool b )
{
_FullPvp = b;
}
//------------------------------------------------------------------------------

View file

@ -21,6 +21,7 @@
// Game Share
#include "game_share/bot_chat_types.h"
#include "game_share/brick_flags.h"
#include "server_share/pet_interface_msg.h"
#include "game_share/power_types.h"
#include "game_share/roles.h"
#include "game_share/temp_inventory_mode.h"
@ -297,6 +298,7 @@ struct CPetAnimal
bool IsMounted;
bool IsTpAllowed;
bool spawnFlag;
ucstring CustomName;
// ctor
CPetAnimal();
@ -305,10 +307,12 @@ struct CPetAnimal
void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
// init found ticket item pointer with slot
uint32 initLinkAnimalToTicket( CCharacter * c );
uint32 initLinkAnimalToTicket( CCharacter * c, uint8 index);
// get the max bulk of the animal inventory
uint32 getAnimalMaxBulk();
void setCustomName(const ucstring& customName) { CustomName = customName; }
};
/**
@ -416,6 +420,10 @@ private:
RemoveFriend,
RemoveIgnored,
AddedAsLeague,
RemovedFromLeague,
RemoveLeague,
NB_CONTACT_LIST_ACTIONS,
UnknownContactListAction= NB_CONTACT_LIST_ACTIONS,
};
@ -738,6 +746,9 @@ public:
// return the season in which is the current character
uint8 getRingSeason() const { return _RingSeason;}
/// get the League id
TChanID getLeagueId() const { return _LeagueId;}
// \name Team related methods
@ -746,10 +757,16 @@ public:
uint16 getTeamId() const;
/// set the team Id of this player
void setTeamId(uint16 id);
/// set the League id
void setLeagueId(TChanID id, bool removeIfEmpty=false);
/// get team invitor
const NLMISC::CEntityId & getTeamInvitor() const;
/// set team invitor
void setTeamInvitor(const NLMISC::CEntityId & invitorId);
/// get League invitor
const NLMISC::CEntityId & getLeagueInvitor() const;
/// set League invitor
void setLeagueInvitor(const NLMISC::CEntityId & invitorId);
//@}
/// Set fighting target
@ -975,6 +992,11 @@ public:
// return the index of a player pet, or -1 if not found
sint32 getPlayerPet( const TDataSetRow& petRowId ) const;
// Set the name of the animal
void setAnimalName( uint8 petIndex, ucstring customName );
void sendPetCustomNameToClient(uint8 petIndex);
// near character's pets are TP with player (continent tp)
void allowNearPetTp();
bool isNearPetTpIsAllowed() const;
@ -1151,6 +1173,12 @@ public:
/// get the number of faction point given a faction
uint32 getFactionPoint(PVP_CLAN::TPVPClan clan);
/// set the number of pvp point
void setPvpPoint(uint32 nbPt);
/// get the number of pvp point given a faction
uint32 getPvpPoint();
/// set the SDB path where player wins HoF points in PvP (if not empty)
void setSDBPvPPath(const std::string & sdbPvPPath);
@ -1160,6 +1188,15 @@ public:
/// init faction point in client database
void initFactionPointDb();
/// init pvp point in client database
void initPvpPointDb();
void initOrganizationInfos();
void setOrganization(uint32 org);
void setOrganizationStatus(uint32 status);
void changeOrganizationStatus(sint32 status);
void changeOrganizationPoints(sint32 points);
/// send faction point gain phrase to the client
void sendFactionPointGainMessage(PVP_CLAN::TPVPClan clan, uint32 fpGain);
/// send faction point gain kill phrase to the client
@ -1614,6 +1651,18 @@ public:
/// send custom url
void sendUrl(const std::string &url, const std::string &salt);
/// set custom mission param
void setCustomMissionParams(const std::string &missionName, const std::string &params);
/// add custom mission param
void addCustomMissionParam(const std::string &missionName, const std::string &param);
/// get custom mission params
std::vector<std::string> getCustomMissionParams(const std::string &missionName);
/// validate dynamic mission step sending url
void validateDynamicMissionStep(const std::string &url);
/// add web command validation check
void addWebCommandCheck(const std::string &url, const std::string &data, const std::string &salt);
@ -1856,15 +1905,18 @@ public:
/// add a player to friend list by name
void addPlayerToFriendList(const ucstring &name);
/// add a player to friend list by id
void addPlayerToFriendList(const NLMISC::CEntityId &id);
/// add a player to ignore list by name
void addPlayerToIgnoreList(const ucstring &name);
/// add a player to ignore list by Id
void addPlayerToIgnoreList(const NLMISC::CEntityId &id);
/// add a player to league list by id
void addPlayerToLeagueList(const NLMISC::CEntityId &id);
/// add a player to friend list by id
void addPlayerToFriendList(const NLMISC::CEntityId &id);
/// get a player from friend or ignore list, by contact id
const NLMISC::CEntityId &getFriendByContactId(uint32 contactId);
const NLMISC::CEntityId &getIgnoreByContactId(uint32 contactId);
@ -1885,6 +1937,9 @@ public:
/// remove room acces to player
void removeRoomAccesToPlayer(const NLMISC::CEntityId &id, bool kick);
/// remove player from league list
void removePlayerFromLeagueListByContactId(uint32 contactId);
void removePlayerFromLeagueListByEntityId(const NLMISC::CEntityId &id);
/// remove player from ignore list
void removePlayerFromIgnoreListByContactId(uint32 contactId);
@ -1923,6 +1978,9 @@ public:
/// player is going online or offline
void online(bool onlineStatus);
/// player last connection date (from SU, exactly like on mysql db)
void setLastConnectionDate(uint32 date);
/// player is permanently erased, unreferenced it from all contact lists
void destroyCharacter();
@ -2230,6 +2288,8 @@ public:
// priviledge PVP mode
void setPriviledgePVP( bool b );
bool priviledgePVP();
// full PVP mode
void setFullPVP( bool b );
/// set the current PVP zone where the player is
void setCurrentPVPZone(TAIAlias alias);
/// get the current PVP zone where the player is
@ -2246,6 +2306,8 @@ public:
void openPVPVersusDialog() const;
/// get priviledgePvp
bool getPriviledgePVP() const {return _PriviledgePvp;};
/// get fullPvp
bool getFullPVP() const {return _FullPvp;};
/// get character pvp flag
bool getPVPFlag( bool updatePVPModeInMirror = true ) const;
/// change pvp flag
@ -2274,7 +2336,7 @@ public:
/// Set an allegiance to neutral from indetermined status, used for process message from client want set it's allegiance to neutral when it's idetermined, over case are managed by missions.
void setAllegianceFromIndeterminedStatus(PVP_CLAN::TPVPClan allegiance);
/// true if pvp safe zone active for character
bool getSafeInPvPSafeZone();
bool getSafeInPvPSafeZone() const;
/// set pvp safe zone to true
void setPvPSafeZoneActive();
/// clear pvp zone safe flag
@ -2316,7 +2378,9 @@ public:
/// character log stats accessors
uint32 getFirstConnectedTime() const;
uint32 getLastConnectedTime() const;
uint32 getLastConnectedDate() const;
uint32 getPlayedTime() const;
uint32 getOrganization() const;
const std::list<TCharacterLogTime>& getLastLogStats() const;
void updateConnexionStat();
void setDisconnexionTime();
@ -2339,7 +2403,7 @@ public:
bool isAnActiveXpCatalyser( CGameItemPtr item );
void setShowFactionChannelsMode(TChanID channel, bool s);
bool showFactionChannelsMode(TChanID channel) const;
bool showFactionChannelsMode(TChanID channel);
// from offline command
void contactListRefChangeFromCommand(const NLMISC::CEntityId &id, const std::string &operation);
@ -2635,6 +2699,8 @@ private:
/// remove player from friend list
void removePlayerFromFriendListByIndex(uint16 index);
/// remove player from league list
void removePlayerFromLeagueListByIndex(uint16 index);
/// remove player from ignore list
void removePlayerFromIgnoreListByIndex(uint16 index);
@ -2934,6 +3000,12 @@ private:
uint32 _FactionPoint[PVP_CLAN::EndClans-PVP_CLAN::BeginClans+1];
uint32 _PvpPoint;
uint32 _Organization;
uint32 _OrganizationStatus;
uint32 _OrganizationPoints;
/// SDB path where player wins HoF points in PvP (if not empty)
std::string _SDBPvPPath;
@ -2944,9 +3016,14 @@ private:
/// if this player has an invitation for another team, keep the team here
NLMISC::CEntityId _TeamInvitor;
/// if this player has an invitation for League, keep the invitor here
NLMISC::CEntityId _LeagueInvitor;
// id of the current team
CMirrorPropValueAlice< uint16, CPropLocationPacked<2> > _TeamId;
TChanID _LeagueId;
/// temp values used to test if team bars need an update or not
mutable uint8 _OldHpBarSentToTeam;
mutable uint8 _OldSapBarSentToTeam;
@ -3178,6 +3255,11 @@ private:
/// nb of users channels
uint8 _NbUserChannels;
/// last webcommand index
uint32 _LastWebCommandIndex;
std::map<std::string, std::string> _CustomMissionsParams;
// for a power/combat event, stores start and end ticks
struct CFlagTickRange {
@ -3243,6 +3325,8 @@ private:
// friends list
std::vector<CContactId> _FriendsList;
// league list
std::vector<CContactId> _LeagueList;
// ignore list
std::vector<CContactId> _IgnoreList;
// list of players for whom this player is in the friendlist (to update online status and to remove from players list if this char is permanently deleted)
@ -3380,8 +3464,14 @@ private:
CPVPInterface *_PVPInterface;
// set pvp mode for priviledge player
bool _PriviledgePvp;
// set full pvp mode for player
bool _FullPvp;
// flag PVP, true for player involved in Faction PVP and other PVP
bool _PVPFlag;
// time of last change in pvp safe
NLMISC::TGameCycle _PVPSafeLastTimeChange;
bool _PVPSafeLastTime;
bool _PVPInSafeZoneLastTime;
// time of last change in pvp flag (for prevent change PVP flag exploits)
NLMISC::TGameCycle _PVPFlagLastTimeChange;
// time of pvp flag are setted to on (for prevent change PVP flag exploits)
@ -3571,7 +3661,8 @@ private:
std::set<NLMISC::CEntityId> _EntitiesToSaveWithMe;
uint32 _FirstConnectedTime; //first connected time in second since midnight (00:00:00), January 1, 1970
uint32 _LastConnectedTime; //last connected time in second since midnight (00:00:00), January 1, 1970
uint32 _LastConnectedTime; //last connected time in second since midnight (00:00:00), January 1, 1970 (change each tick update)
uint32 _LastConnectedDate; //last connected time in second since midnight (00:00:00), January 1, 1970 (never change after login, exactly like in mysql db)
uint32 _PlayedTime; //cumulated played time in second
mutable std::list<TCharacterLogTime> _LastLogStats; //keep n login/duration/logoff time
@ -3625,6 +3716,11 @@ private:
/// General god flag for persistence
bool _GodModeSave;
public:
void setWebCommandIndex(uint32 index) { _LastWebCommandIndex = index;}
uint32 getWebCommandIndex() const { return _LastWebCommandIndex;}
bool getInvisibility() const { return _Invisibility;}
/// Set the invisibility flag, NB : just for persistence, do not change nothing.
void setInvisibility(bool invisible)

View file

@ -2357,7 +2357,7 @@ void CPlayerManager::broadcastMessageUpdate()
msg= msg.replace("$seconds$",secondsStr.c_str());
msg= msg.replace("$minutes$",minutesStr.c_str());
msg= msg.replace("$hours$",hoursStr.c_str());
nlinfo("braodcasting message: %s",msg.c_str());
nlinfo("broadcasting message: %s",msg.c_str());
SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
params[0].Literal.fromUtf8(msg);

View file

@ -1095,14 +1095,14 @@ void CDamageScoreManager::playerDeath(CCharacter * victimChar, const CCharacter
nlassert(victimChar != NULL);
PVP_CLAN::TPVPClan victimFaction;
bool victimLosesFactionPoints;
if (!playerInFactionPvP(victimChar, &victimFaction, &victimLosesFactionPoints))
return;
// PVP_CLAN::TPVPClan victimFaction;
bool victimLosesFactionPoints = false;
// if (!playerInFactionPvP(victimChar, &victimFaction, &victimLosesFactionPoints))
// return;
PVP_CLAN::TPVPClan finalBlowerFaction;
if (!playerInFactionPvP(finalBlower, &finalBlowerFaction))
return;
// PVP_CLAN::TPVPClan finalBlowerFaction;
// if (!playerInFactionPvP(finalBlower, &finalBlowerFaction))
// return;
// check if victim and final blower are in PvP Faction (by tag or by a pvp versus zone)
/* if(!CPVPManager2::getInstance()->factionWarOccurs(victimFaction, finalBlowerFaction))
@ -1204,9 +1204,13 @@ void CDamageScoreManager::playerDeath(CCharacter * victimChar, const CCharacter
BOMB_IF(winnerChar == NULL, "invalid winner!", continue);
PVP_CLAN::TPVPClan winnerFaction;
bool winnerGainFactionPoints;
if(!playerInFactionPvP(winnerChar, &winnerFaction, &winnerGainFactionPoints))
continue; // can be in Duel or in other pvp mode.
bool winnerGainFactionPoints = true;
if (!canPlayerWinPoints(winnerChar, victimChar))
continue;
//if(!playerInFactionPvP(winnerChar, &winnerFaction, &winnerGainFactionPoints))
// continue; // can be in Duel or in other pvp mode.
CRewardedKills::CRewardedKiller * noPointPlayer = getRewardedKiller(winnerChar->getId(), noPointPlayers);
if (noPointPlayer != NULL)
@ -1227,9 +1231,27 @@ void CDamageScoreManager::playerDeath(CCharacter * victimChar, const CCharacter
if (winnerGainFactionPoints)
{
// Compute Fames delta
sint32 fameFactor = 0;
for (uint8 fameIdx = 0; fameIdx < 7; fameIdx++)
{
sint32 victimFame = CFameInterface::getInstance().getFameIndexed(victimChar->getId(), fameIdx);
sint32 winnerFame = CFameInterface::getInstance().getFameIndexed(winnerChar->getId(), fameIdx);
if ( (victimFame >= 25*6000 && winnerFame <= -25*6000) ||
(winnerFame >= 25*6000 && victimFame <= -25*6000) )
fameFactor++;
if ( (victimFame >= 25*6000 && winnerFame >= 25*6000) ||
(victimFame <= -25*6000 && winnerFame <= -25*6000) )
fameFactor--;
}
clamp(fameFactor, 0, 3);
nlinfo("points = %d * %d", fpPerPlayer, fameFactor);
// player gains faction points
changePlayerFactionPoints(winnerChar, winnerFaction, sint32(fpPerPlayer));
winnerChar->sendFactionPointGainKillMessage(winnerFaction, fpPerPlayer, victimChar->getId());
changePlayerPvpPoints(winnerChar, sint32(fpPerPlayer) * fameFactor);
winnerChar->sendFactionPointGainKillMessage(winnerFaction, fpPerPlayer * fameFactor, victimChar->getId());
}
// player gains HoF points
@ -1237,13 +1259,14 @@ void CDamageScoreManager::playerDeath(CCharacter * victimChar, const CCharacter
// and a way for known if an episode occurs (and specs for known if other episode pemrti to win HoF point...)
//changePlayerHoFPoints(winnerChar, sint32(hofpPerPlayer));
/*
// PvP faction winner HOF reward
CPVPManager2::getInstance()->characterKillerInPvPFaction( winnerChar, winnerFaction, (sint32)fpPerPlayer );
if( finalBlower == winnerChar )
{
CPVPManager2::getInstance()->finalBlowerKillerInPvPFaction( winnerChar, winnerFaction, victimChar );
}
*/
rewardedKillers.push_back(winnerChar->getId());
nbRewardedMembers++;
}
@ -1273,7 +1296,7 @@ void CDamageScoreManager::playerDeath(CCharacter * victimChar, const CCharacter
hofpLoss = uint32(double(hofpLoss) * PVPHoFPointLossFactor.get() + 0.5);
// keep the point loss to apply if the victim respawn
CPointLoss pointLoss;
/*CPointLoss pointLoss;
pointLoss.PlayerLosesFactionPoints = victimLosesFactionPoints;
pointLoss.PlayerFaction = victimFaction;
pointLoss.FactionPointLoss = fpLoss;
@ -1282,8 +1305,8 @@ void CDamageScoreManager::playerDeath(CCharacter * victimChar, const CCharacter
_PointLossByPlayer[victimChar->getId()] = pointLoss;
// PvP faction looser lost
CPVPManager2::getInstance()->characterKilledInPvPFaction( victimChar, victimFaction, -(sint32) fpLoss );
//CPVPManager2::getInstance()->characterKilledInPvPFaction( victimChar, victimFaction, -(sint32) fpLoss );
*/
// delete the score table of the victim
removeDamageScoreTable(victimChar->getEntityRowId());
}
@ -1429,6 +1452,7 @@ void CDamageScoreManager::playerRespawn(CCharacter * victimChar)
const CPointLoss & pointLoss = (*it).second;
/*
if (pointLoss.PlayerLosesFactionPoints)
{
// victim loses faction points
@ -1438,6 +1462,7 @@ void CDamageScoreManager::playerRespawn(CCharacter * victimChar)
// victim loses HoF points
changePlayerHoFPoints(victimChar, -sint32(pointLoss.HoFPointLoss));
*/
// remove the applied entry
_PointLossByPlayer.erase(it);
@ -1684,9 +1709,9 @@ bool CDamageScoreManager::playerInFactionPvP(const CCharacter * playerChar, PVP_
return true;
}
}
else if( playerChar->getPVPFlag() )
else if( playerChar->getPVPFlag(false) )
{
pair<PVP_CLAN::TPVPClan, PVP_CLAN::TPVPClan> allegiance = playerChar->getAllegiance();
/*pair<PVP_CLAN::TPVPClan, PVP_CLAN::TPVPClan> allegiance = playerChar->getAllegiance();
if( (allegiance.first != PVP_CLAN::Neutral) && (allegiance.first != PVP_CLAN::None) )
{
if (faction)
@ -1695,7 +1720,7 @@ bool CDamageScoreManager::playerInFactionPvP(const CCharacter * playerChar, PVP_
*withFactionPoints = true;
return true;
}
/*if ( allegiance.second != PVP_CLAN::Neutral)
if ( allegiance.second != PVP_CLAN::Neutral)
{
if (faction)
*faction = allegiance.second;
@ -1703,10 +1728,45 @@ bool CDamageScoreManager::playerInFactionPvP(const CCharacter * playerChar, PVP_
*withFactionPoints = true;
return true;
}*/
return true;
}
return false;
}
bool CDamageScoreManager::canPlayerWinPoints(const CCharacter * winnerChar, CCharacter * victimeChar) const
{
// Don't win points if in duel
if ( winnerChar->getDuelOpponent() && (winnerChar->getDuelOpponent()->getId() == victimeChar->getId()) )
return false;
if (victimeChar->getPVPRecentActionFlag())
nlinfo("PVP recent flag");
// Only win points if victime is Flag
if( winnerChar->getPVPFlag(false))
{
if ( true/*victimeChar->getPVPRecentActionFlag()*/ )
{
nlinfo("Teams : %d, %d", winnerChar->getTeamId(), victimeChar->getTeamId());
// Don't win points if in same Team
if ( winnerChar->getTeamId() != CTEAM::InvalidTeamId && victimeChar->getTeamId() != CTEAM::InvalidTeamId && (winnerChar->getTeamId() == victimeChar->getTeamId()) )
return false;
// Don't win points if in same Guild
nlinfo("Guild : %d, %d", winnerChar->getGuildId(), victimeChar->getGuildId());
if ( winnerChar->getGuildId() != 0 && victimeChar->getGuildId() != 0 && (winnerChar->getGuildId() == victimeChar->getGuildId()) )
return false;
// Don't win points if in same League
if ( winnerChar->getLeagueId() != DYN_CHAT_INVALID_CHAN && victimeChar->getLeagueId() != DYN_CHAT_INVALID_CHAN && (winnerChar->getLeagueId() == victimeChar->getLeagueId()) )
return false;
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
uint32 CDamageScoreManager::computeFactionPointsForWinner(const CDamageScoreTable::CWinner & winner, uint32 victimSkillValue)
{
@ -1795,6 +1855,28 @@ sint32 CDamageScoreManager::changePlayerFactionPoints(CCharacter * playerChar, P
return fpDelta;
}
//-----------------------------------------------------------------------------
sint32 CDamageScoreManager::changePlayerPvpPoints(CCharacter * playerChar, sint32 fpDelta)
{
nlassert(playerChar != NULL);
if (fpDelta == 0)
return 0;
uint32 points = playerChar->getPvpPoint();
// player cannot have negative pvp points
fpDelta = max(fpDelta, -sint32(points));
points += fpDelta;
// set the new pvp points
playerChar->setPvpPoint(points);
return fpDelta;
}
//-----------------------------------------------------------------------------
void CDamageScoreManager::changePlayerHoFPoints(CCharacter * playerChar, sint32 hofpDelta)
{

View file

@ -42,7 +42,7 @@ typedef uint16 TTeamId;
/**
* A damage score table keeps all damages done by a player/team/creature on a player
*
* \author Sébastien 'kxu' Guignot
* \author Sebastien 'kxu' Guignot
* \author Nevrax France
* \date 2005
*/
@ -193,7 +193,7 @@ private:
* It permits to find all players wounded by an entity (player/team/creature)
* ie to find all players on which the entity has a damage score.
*
* \author Sébastien 'kxu' Guignot
* \author Sebastien 'kxu' Guignot
* \author Nevrax France
* \date 2005
*/
@ -229,7 +229,7 @@ private:
/**
* It keeps kills that have been rewarded and which cannot be rewarded again for a lapse of time.
*
* \author Sébastien 'kxu' Guignot
* \author Sebastien 'kxu' Guignot
* \author Nevrax France
* \date 2005
*/
@ -273,7 +273,7 @@ private:
* and keeps their damage scores on each attacked player.
* It also gives faction and HoF points to players.
*
* \author Sébastien 'kxu' Guignot
* \author Sebastien 'kxu' Guignot
* \author Nevrax France
* \date 2005
*/
@ -342,6 +342,8 @@ private:
/// return true if the given action is curative
bool isCurativeAction(const TReportAction & action) const;
bool canPlayerWinPoints(const CCharacter * winnerChar, CCharacter * victimeChar) const;
/// return true if the given player is in 'faction PvP' (in a faction PvP zone)
/// \param faction : if not NULL return the faction of the player in the PvP zone where he is
/// \param gainFactionPoints : if not NULL return true if the zone gives faction points or not
@ -357,6 +359,10 @@ private:
/// \return the applied delta (a negative delta may have been modified up to zero to keep faction points positive)
sint32 changePlayerFactionPoints(CCharacter * playerChar, PVP_CLAN::TPVPClan faction, sint32 fpDelta);
/// add/remove pvp points to a player
/// \return the applied delta (a negative delta may have been modified up to zero to keep pvp points positive)
sint32 changePlayerPvpPoints(CCharacter * playerChar, sint32 fpDelta);
/// add/remove HoF points to a player and his guild if his SDB PvP path is defined
void changePlayerHoFPoints(CCharacter * playerChar, sint32 hofpDelta);
@ -388,7 +394,7 @@ private:
/**
* This is the interface for the character progression in PvP
*
* \author Sébastien 'kxu' Guignot
* \author Sebastien 'kxu' Guignot
* \author Nevrax France
* \date 2005
*/

View file

@ -39,6 +39,13 @@ PVP_RELATION::TPVPRelation CPVPFaction::getPVPRelation( CCharacter * actor, CEnt
CPVPManager2::getInstance()->setPVPFactionAllyReminder( false );
CPVPManager2::getInstance()->setPVPFactionEnemyReminder( false );
bool isAlly = false;
bool targetSafe = false;
bool actorSafe = false;
bool targetInSafeZone = false;
bool actorInSafeZone = false;
// Check actor and target validity
if (actor == 0 || target == 0)
{
@ -50,70 +57,85 @@ PVP_RELATION::TPVPRelation CPVPFaction::getPVPRelation( CCharacter * actor, CEnt
if (pTarget == 0)
return PVP_RELATION::Unknown;
// if target is not tagged then he's neutral
if (!pTarget->getPVPFlag() && !pTarget->getPvPRecentActionFlag())
return PVP_RELATION::Neutral;
// Check safe zones
if (CPVPManager2::getInstance()->inSafeZone(pTarget->getPosition()))
{
targetInSafeZone = true;
if (pTarget->getSafeInPvPSafeZone())
return PVP_RELATION::NeutralPVP;
targetSafe = true;
}
if( CPVPManager2::getInstance()->inSafeZone(actor->getPosition()))
{
actorInSafeZone = true;
if( actor->getSafeInPvPSafeZone())
actorSafe = true;
}
// Target is not tagged => Neutral
if (!pTarget->getPVPFlag() && !pTarget->getPvPRecentActionFlag())
return PVP_RELATION::Neutral;
// Actor is not tagged => Check target
if (!actor->getPVPFlag() && !actor->getPvPRecentActionFlag())
{
// Target flag => NeutralPVP
if (pTarget->getPvPRecentActionFlag())
return PVP_RELATION::NeutralPVP;
else
return PVP_RELATION::Neutral;
}
// In same Team => Ally
if ((pTarget->getTeamId() != CTEAM::InvalidTeamId) && (actor->getTeamId() != CTEAM::InvalidTeamId) && (actor->getTeamId() == pTarget->getTeamId()))
{
isAlly = true;
}
// In Same League => Ally
if ((pTarget->getLeagueId() != DYN_CHAT_INVALID_CHAN) && (actor->getLeagueId() != DYN_CHAT_INVALID_CHAN) && (actor->getLeagueId() == pTarget->getLeagueId()))
{
isAlly = true;
}
// In same Guild and not Leagued => Ally
if ((pTarget->getGuildId() != 0) && (actor->getGuildId() != 0) && (actor->getGuildId() == pTarget->getGuildId()) && (pTarget->getLeagueId() == DYN_CHAT_INVALID_CHAN) && (actor->getLeagueId() == DYN_CHAT_INVALID_CHAN))
{
isAlly = true;
}
if (isAlly)
{
// One is in safe zone but not other => NeutralPVP
if ((targetInSafeZone && !actorInSafeZone) || (actorInSafeZone && !targetInSafeZone))
{
return PVP_RELATION::NeutralPVP;
}
// Check fames
if( actor->getPVPFlag() || actor->getPvPRecentActionFlag() )
// One is safe but not other => NeutralPVP
if (targetSafe != actorSafe)
{
// In same Team
if ((pTarget->getTeamId() != CTEAM::InvalidTeamId) && (actor->getTeamId() != CTEAM::InvalidTeamId) && (actor->getTeamId() == pTarget->getTeamId()))
{
CPVPManager2::getInstance()->setPVPFactionAllyReminder( true );
return PVP_RELATION::Ally;
return PVP_RELATION::NeutralPVP;
}
// In same Guild
if ((pTarget->getGuildId() != 0) && (actor->getGuildId() != 0) && (actor->getGuildId() == pTarget->getGuildId()))
{
CPVPManager2::getInstance()->setPVPFactionAllyReminder( true );
return PVP_RELATION::Ally;
}
// check if he's an ennemy
if ((actor->getPVPFamesAllies() & pTarget->getPVPFamesEnemies()) || (actor->getPVPFamesEnemies() & pTarget->getPVPFamesAllies()))
{
// Actor can heal an ennemi if not PvPRecentActionFlaged
if (curative && !pTarget->getPvPRecentActionFlag())
{
return PVP_RELATION::Neutral;
}
else
{
CPVPManager2::getInstance()->setPVPFactionEnemyReminder(true);
return PVP_RELATION::Ennemy;
}
}
// check if he's an ally
else if ((actor->getPVPFamesAllies() & pTarget->getPVPFamesAllies()) || (actor->getPVPFamesEnemies() & pTarget->getPVPFamesEnemies()))
{
CPVPManager2::getInstance()->setPVPFactionAllyReminder(true);
return PVP_RELATION::Ally;
}
}
else
// If one is safe => NeutralPVP
if (targetSafe || actorSafe)
{
// Check if actor is not PvPFlag and try to heal a PvPRecentActionFlag
if (curative && pTarget->getPvPRecentActionFlag())
return PVP_RELATION::NeutralPVP;
}
// default is neutral
return PVP_RELATION::Neutral;
//
if ((targetInSafeZone && !pTarget->getPvPRecentActionFlag()) || (actorInSafeZone && !actor->getPvPRecentActionFlag()))
{
return PVP_RELATION::NeutralPVP;
}
CPVPManager2::getInstance()->setPVPFactionEnemyReminder(true);
return PVP_RELATION::Ennemy;
}

View file

@ -26,6 +26,7 @@
#include "game_share/utils.h"
#include "game_share/msg_client_server.h"
#include "game_share/fame.h"
#include "game_share/send_chat.h"
#include "pvp_manager/pvp_manager_2.h"
#include "pvp_manager/pvp_manager.h"
@ -176,6 +177,21 @@ TChanID CPVPManager2::getUserDynChannel( const std::string& channelName)
return DYN_CHAT_INVALID_CHAN;
}
std::string CPVPManager2::getUserDynChannel(const TChanID& channelId)
{
TMAPExtraFactionChannel::iterator it;
for (it = _UserChannel.begin(); it != _UserChannel.end(); ++it)
{
if ((*it).second == channelId)
{
return (*it).first;
}
}
// should not get here
nlassert(false);
return "";
}
const std::string & CPVPManager2::getPassUserChannel( TChanID channelId)
{
// Search in user channels
@ -353,7 +369,7 @@ void CPVPManager2::broadcastMessage(TChanID channel, const ucstring& speakerName
sendMessageViaMirror("IOS", msgout);
}
void CPVPManager2::sendChannelUsers(TChanID channel, CCharacter * user)
void CPVPManager2::sendChannelUsers(TChanID channel, CCharacter * user, bool outputToSys)
{
std::vector<NLMISC::CEntityId> lst;
@ -361,21 +377,40 @@ void CPVPManager2::sendChannelUsers(TChanID channel, CCharacter * user)
if(it != _UserChannelCharacters.end())
{
lst = (*it).second;
string players = "";
ucstring players;
uint32 shardId = CEntityIdTranslator::getInstance()->getEntityShardId(user->getId());
for (uint i = 0; i < lst.size(); i++)
{
players += "\n"+CEntityIdTranslator::getInstance()->getByEntity(lst[i]).toString();
ucstring name = CEntityIdTranslator::getInstance()->getByEntity(lst[i]);
if (shardId == CEntityIdTranslator::getInstance()->getEntityShardId(lst[i]))
{
// Same shard, remove shard from name
CEntityIdTranslator::removeShardFromName(name);
}
players += "\n" + name ;
}
TDataSetRow senderRow = TheDataset.getDataSetRow(user->getId());
if (outputToSys)
{
CCharacter::sendDynamicSystemMessage( user->getId(), "WHO_CHANNEL_INTRO" );
//players = "Players in channel \"" + getUserDynChannel(channel) + "\": " + players;
SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
params[0].Literal = players;
CCharacter::sendDynamicSystemMessage( user->getId(), "LITERAL", params );
}
else
{
CMessage msgout("DYN_CHAT:SERVICE_TELL");
msgout.serial(channel);
ucstring users = ucstring("<USERS>");
msgout.serial(const_cast<ucstring&>(users));
TDataSetRow senderRow = TheDataset.getDataSetRow(user->getId());
msgout.serial(senderRow);
ucstring txt = ucstring(players);
msgout.serial(const_cast<ucstring&>(txt));
sendMessageViaMirror( "IOS", msgout);
sendMessageViaMirror("IOS", msgout);
}
}
}
@ -559,10 +594,10 @@ void CPVPManager2::playerTeleports(CCharacter * user)
void CPVPManager2::setPVPModeInMirror( const CCharacter * user ) const
{
nlassert(user);
uint8 pvpMode = 0;
TYPE_PVP_MODE pvpMode = 0;
// Full pvp
if ( user->getPriviledgePVP() )
if ( user->getFullPVP() )
{
pvpMode |= PVP_MODE::PvpChallenge;
}
@ -588,6 +623,16 @@ void CPVPManager2::setPVPModeInMirror( const CCharacter * user ) const
pvpMode |= PVP_MODE::PvpDuel;
}
}
// in Safe zone
{
if (CPVPManager2::getInstance()->inSafeZone(user->getPosition()))
{
pvpMode |= PVP_MODE::PvpZoneSafe;
if (user->getSafeInPvPSafeZone())
pvpMode |= PVP_MODE::PvpSafe;
}
}
// pvp session (i.e everything else)
{
if ( user->getPVPInterface().isValid() )
@ -598,7 +643,13 @@ void CPVPManager2::setPVPModeInMirror( const CCharacter * user ) const
}
CMirrorPropValue<TYPE_PVP_MODE> propPvpMode( TheDataset, user->getEntityRowId(), DSPropertyPVP_MODE );
CMirrorPropValue<TYPE_EVENT_FACTION_ID> propPvpMode2( TheDataset, user->getEntityRowId(), DSPropertyEVENT_FACTION_ID );
if (propPvpMode.getValue() != pvpMode)
{
nlinfo("New pvp Mode : %d", pvpMode);
propPvpMode = pvpMode;
propPvpMode2 = pvpMode;
}
}
//----------------------------------------------------------------------------
@ -648,22 +699,16 @@ PVP_RELATION::TPVPRelation CPVPManager2::getPVPRelation( CCharacter * actor, CEn
CCharacter * pTarget = dynamic_cast<CCharacter*>(target);
if( pTarget )
{
// priviledgePVP is Full PVP, only ally of teammates anf guildmates
if (pTarget->priviledgePVP() || actor->priviledgePVP())
// Full PVP is ennemy of everybody
if (pTarget->getFullPVP() || actor->getFullPVP())
{
if ((pTarget->getTeamId() != CTEAM::InvalidTeamId) && (actor->getTeamId() != CTEAM::InvalidTeamId) && (actor->getTeamId() == pTarget->getTeamId()))
return PVP_RELATION::Ally;
if ((pTarget->getGuildId() != 0) && (actor->getGuildId() != 0) && (actor->getGuildId() == pTarget->getGuildId()))
return PVP_RELATION::Ally;
return PVP_RELATION::Ennemy;
}
if( IsRingShard )
return relation; // disable PVP on Ring shards (only if target is a CCharacter, because we must let attack NPCs)
// //////////////////////////////////////////////////////
////////////////////////////////////////////////////////
// temp : until new manager is finished we have to check the char pvp session too
IPVP * pvpSession = pTarget->getPVPInterface().getPVPSession();
if( pvpSession )
@ -713,8 +758,8 @@ PVP_RELATION::TPVPRelation CPVPManager2::getPVPRelation( CCharacter * actor, CEn
if( relationTmp == PVP_RELATION::NeutralPVP )
relation = PVP_RELATION::NeutralPVP;
// Check if ally (neutralpvp has priority over ally)
if( relationTmp == PVP_RELATION::Ally && relation != PVP_RELATION::NeutralPVP )
// Check if ally (neutralpvp and active has priority over ally)
if (relationTmp == PVP_RELATION::Ally && relation != PVP_RELATION::NeutralPVP)
relation = PVP_RELATION::Ally;
}
@ -730,6 +775,7 @@ bool CPVPManager2::isCurativeActionValid( CCharacter * actor, CEntityBase * targ
PVP_RELATION::TPVPRelation pvpRelation = getPVPRelation( actor, target, true );
bool actionValid;
nlinfo("Pvp relation = %d", pvpRelation);
switch( pvpRelation )
{
case PVP_RELATION::Ally :
@ -757,11 +803,12 @@ bool CPVPManager2::isCurativeActionValid( CCharacter * actor, CEntityBase * targ
if( actionValid && !checkMode )
{
CCharacter * pTarget = dynamic_cast<CCharacter*>(target);
if(pTarget)
actor->clearSafeInPvPSafeZone();
//if(pTarget)
// actor->clearSafeInPvPSafeZone();
// propagate faction pvp flag
if( pvpRelation == PVP_RELATION::Ally )
if( pvpRelation == PVP_RELATION::Ally)
{
if( _PVPFactionAllyReminder )
{
@ -782,10 +829,6 @@ bool CPVPManager2::isCurativeActionValid( CCharacter * actor, CEntityBase * targ
{
actor->refreshOutpostLeavingTimer();
}
// propagate full pvp
if( pTarget->priviledgePVP() )
actor->setPriviledgePVP(true);
}
}
return actionValid;
@ -832,7 +875,13 @@ bool CPVPManager2::isOffensiveActionValid( CCharacter * actor, CEntityBase * tar
{
CCharacter * pTarget = dynamic_cast<CCharacter*>(target);
if(pTarget)
{
if (actor->getDuelOpponent() == pTarget) // No _PVPFactionEnemyReminder when in duel
CPVPManager2::getInstance()->setPVPFactionAllyReminder(false);
else
actor->clearSafeInPvPSafeZone();
}
if( _PVPFactionEnemyReminder )
{
actor->setPVPRecentActionFlag();
@ -886,10 +935,20 @@ bool CPVPManager2::canApplyAreaEffect(CCharacter* actor, CEntityBase * areaTarge
if( actionValid )
{
/* if ((pTarget->getGuildId() != 0) && (actor->getGuildId() != 0) && (actor->getGuildId() != pTarget->getGuildId()))
return false;
*/
if( areaTarget->getId().getType() == RYZOMID::player )
{
CCharacter * pTarget = dynamic_cast<CCharacter*>(areaTarget);
if(pTarget)
if (!offensive)
{
if (actor->getTeamId() != pTarget->getTeamId() && actor->getLeagueId() != pTarget->getLeagueId() )
return false;
}
if(pTarget && offensive)
actor->clearSafeInPvPSafeZone();
// set faction flag
if( offensive && _PVPFactionEnemyReminder )
@ -1096,6 +1155,11 @@ void CPVPManager2::createExtraFactionChannel(const std::string & channelName)
TChanID CPVPManager2::createUserChannel(const std::string & channelName, const std::string & pass)
{
// Don't allow channels called "GM" (to not clash with the /who gm command)
if (NLMISC::nlstricmp( channelName.c_str() , "GM" ) == 0)
{
return DYN_CHAT_INVALID_CHAN;
}
TMAPExtraFactionChannel::iterator it = _UserChannel.find(channelName);
if( it == _UserChannel.end() )
@ -1244,6 +1308,14 @@ void CPVPManager2::askForDuel( const NLMISC::CEntityId & userId )
return;
}
// If not a privileged player and in ignorelist, cannot duel
if ( !user->haveAnyPrivilege() && target->hasInIgnoreList( user->getId() ) )
{
params[0].setEIdAIAlias( target->getId(), CAIAliasTranslator::getInstance()->getAIAlias(target->getId()) );
CCharacter::sendDynamicSystemMessage(userId, "DUEL_REFUSE_INVITATION", params);
return;
}
// remove previous invitation, and check that user is not invited
bool problem = false;

View file

@ -76,10 +76,12 @@ public:
void onIOSMirrorUp();
/// callback called at each tick
void tickUpdate();
/// return dynamic channel TChanID attribued to a faction
/// return dynamic channel TChanID attributed to a faction
TChanID getFactionDynChannel( const std::string& channelName );
/// return dynamic channel TChanID attribued to an user
/// return user dynamic channel TChanID
TChanID getUserDynChannel( const std::string& channelName);
/// return user dynamic channel name
std::string getUserDynChannel(const TChanID& channelId);
/// return dynamic channel TChanID attribued to a faction
const std::string &getPassUserChannel( TChanID channelId);
/// return dynamic channel TChanID character must have, DYN_CHAT_INVALID_CHAN if he must don't have faction channel
@ -91,7 +93,7 @@ public:
// brodcast message to channel
void broadcastMessage(TChanID channel, const ucstring& speakerName ,const ucstring& txt);
// send list of users to player
void sendChannelUsers(TChanID channel, CCharacter * user);
void sendChannelUsers(TChanID channel, CCharacter * user, bool outputToSys = false);
// add faction channel to character if needed
void addFactionChannelToCharacter(TChanID channel, CCharacter * user, bool writeRight = true, bool userChannel = false);
// remove faction channel for character

View file

@ -63,6 +63,15 @@ namespace PVP_ZONE_TYPE
} // namespace PVP_ZONE_TYPE
//----------------------------------------------------------------------------
static inline bool inSameLeague(CCharacter * c1, CCharacter * c2)
{
if (c1 == NULL || c2 == NULL)
return false;
return ( c1 == c2 ) || ( c1->getLeagueId() != DYN_CHAT_INVALID_CHAN && c1->getLeagueId() == c2->getLeagueId() );
}
//----------------------------------------------------------------------------
static inline bool inSameTeam(CCharacter * c1, CCharacter * c2)
{
@ -372,35 +381,47 @@ PVP_RELATION::TPVPRelation CPVPFreeZone::getPVPRelation( CCharacter * user, CEnt
nlassert(user);
nlassert(target);
if( target->getId().getType() != RYZOMID::player )
CCharacter * pTarget = dynamic_cast<CCharacter*>(target);
bool targetSafe = false;
bool actorSafe = false;
if (target->getId().getType() != RYZOMID::player)
{
return PVP_RELATION::Unknown;
}
// if target is in same zone then he's an ennemy or ally
if ( _Users.find( target->getEntityRowId() ) != _Users.end() )
if (CPVPManager2::getInstance()->inSafeZone(pTarget->getPosition()))
{
if( inSameTeam( user, (CCharacter *)target ) )
if (pTarget->getSafeInPvPSafeZone())
targetSafe = true;
}
if (CPVPManager2::getInstance()->inSafeZone(user->getPosition()))
{
if( user->getSafeInPvPSafeZone())
actorSafe = true;
}
if ((targetSafe && !actorSafe) || (actorSafe && !targetSafe)) {
return PVP_RELATION::NeutralPVP;
}
// In same Zone
if (_Users.find( target->getEntityRowId() ) != _Users.end())
{
// In Same Team or League => Ally
if (inSameTeam( user, pTarget ) || inSameLeague( user, pTarget ))
{
return PVP_RELATION::Ally;
}
else
{
// If both not in safe zone => Ennemy
if (!targetSafe && !actorSafe)
return PVP_RELATION::Ennemy;
}
}
// if target is in free pvp then he's neutral pvp
const CCharacter * targetChar = static_cast<const CCharacter*>(target);
if( targetChar->getPVPInterface().isValid() )
{
if( targetChar->getPVPInterface().getPVPSession()->getPVPMode() == PVP_MODE::PvpZoneFree );
{
return PVP_RELATION::NeutralPVP;
}
}
return PVP_RELATION::Neutral;
}
//----------------------------------------------------------------------------
@ -1135,36 +1156,53 @@ PVP_RELATION::TPVPRelation CPVPGuildZone::getPVPRelation( CCharacter * user, CEn
nlassert(user);
nlassert(target);
// target has to be a char
CCharacter *targetChar = dynamic_cast<CCharacter*>(target);
if ( !targetChar )
CCharacter * pTarget = dynamic_cast<CCharacter*>(target);
bool targetSafe = false;
bool actorSafe = false;
if( target->getId().getType() != RYZOMID::player )
{
return PVP_RELATION::Unknown;
}
// check that target is in the same zone than user (discards bots)
if (CPVPManager2::getInstance()->inSafeZone(pTarget->getPosition()))
{
if (pTarget->getSafeInPvPSafeZone())
targetSafe = true;
}
if( CPVPManager2::getInstance()->inSafeZone(user->getPosition()))
{
if( user->getSafeInPvPSafeZone())
actorSafe = true;
}
if ((targetSafe && !actorSafe) || (actorSafe && !targetSafe)) {
return PVP_RELATION::NeutralPVP;
}
// if target is in same zone then he's an ennemy or ally
if ( _Users.find( target->getEntityRowId() ) != _Users.end() )
{
if ( inSameGuild(targetChar,user) || inSameTeam( targetChar, user) )
// In Same Team or League => Ally
if (inSameTeam( user, pTarget ) || inSameLeague( user, pTarget ))
{
return PVP_RELATION::Ally;
}
else
// in same Guild and not in Leagues => Ally
if (inSameGuild( user, pTarget ) && user->getLeagueId() == DYN_CHAT_INVALID_CHAN && pTarget->getLeagueId() == DYN_CHAT_INVALID_CHAN)
{
return PVP_RELATION::Ally;
}
// If both not in safe zone => Ennemy
if (!targetSafe && !actorSafe)
return PVP_RELATION::Ennemy;
}
}
// if target is in guild pvp then he's neutral pvp
if( targetChar->getPVPInterface().isValid() )
{
if( targetChar->getPVPInterface().getPVPSession()->getPVPMode() == PVP_MODE::PvpZoneGuild )
{
return PVP_RELATION::NeutralPVP;
}
}
return PVP_RELATION::Neutral;
}
/*

View file

@ -155,6 +155,12 @@ void CTradeBase::copy( IItemTrade * itt )
else _ItemPtr = 0;
}
TGameCycle CItemForSale::getGameCycleLeft() const
{
TGameCycle dt = CTickEventHandler::getGameCycle() - _StartSaleCycle;
return (TGameCycle) ( (sint32) std::max( (sint32)0, (sint32)( ((sint32) MaxGameCycleSaleStore) - (sint32)( dt + _ItemPtr->getTotalSaleCycle() ) ) ) );
}
//-----------------------------------------------------------------------------
//uint32 CTradeBase::getFactionPointPrice() const
//{

View file

@ -202,7 +202,8 @@ public:
void setAvailable( bool a );
// return game cycle left for item in store
NLMISC::TGameCycle getGameCycleLeft() const { return (NLMISC::TGameCycle) ( (sint32) std::max( (sint32)0, (sint32)( ((sint32) MaxGameCycleSaleStore) - ( ( CTickEventHandler::getGameCycle() - _StartSaleCycle ) + _ItemPtr->getTotalSaleCycle() ) ) ) ); }
// NLMISC::TGameCycle getGameCycleLeft() const { return (NLMISC::TGameCycle) ( (sint32) std::max( (sint32)0, (sint32)( ((sint32) MaxGameCycleSaleStore) - ( ( CTickEventHandler::getGameCycle() - _StartSaleCycle ) + _ItemPtr->getTotalSaleCycle() ) ) ) ); }
NLMISC::TGameCycle getGameCycleLeft() const;
// get quantity
uint32 getQuantity() const { return _Quantity; }

View file

@ -57,6 +57,7 @@ void CTeam::init( CCharacter* leader, uint16 teamId )
_ValidityFlags.Fake = false;
_NbMembers = 1;
_TeamId = teamId;
_LeagueId = leader->getLeagueId();
_LeaderId = leader->getId();
_TeamMembers.push_back(_LeaderId);
// init the team chat group
@ -120,6 +121,12 @@ void CTeam::release()
PROGRESSIONPVE::CCharacterProgressionPVE::getInstance()->disbandTeam(_TeamId, _TeamMembers);
PROGRESSIONPVP::CCharacterProgressionPVP::getInstance()->disbandTeam(_TeamId, _TeamMembers);
if (_LeagueId != DYN_CHAT_INVALID_CHAN)
{
DynChatEGS.removeChan(_LeagueId);
}
_LeagueId = DYN_CHAT_INVALID_CHAN;
_TeamId = CTEAM::InvalidTeamId;
_TeamMembers.clear();
_NbMembers = 0;
@ -167,7 +174,8 @@ void CTeam::addCharacter(CCharacter *newCharacter)
else
{
// newCharacter->_PropertyDatabase.setProp( "GROUP:SUCCESSOR_INDEX", 1 );
CBankAccessor_PLR::getGROUP().setSUCCESSOR_INDEX(newCharacter->_PropertyDatabase, 1);
uint8 index = getSuccessorIndex();
CBankAccessor_PLR::getGROUP().setSUCCESSOR_INDEX(newCharacter->_PropertyDatabase, index);
}
// update all member's DB
@ -283,6 +291,9 @@ void CTeam::addCharacter(CCharacter *newCharacter)
// set the character team
newCharacter->setTeamId(_TeamId);
// set the character alliance
newCharacter->setLeagueId(_LeagueId);
// Add character to chat group
TGroupId idGroupe = CHAT_GROUPS_IDS::getTeamChatGroupId(_TeamId);
CMessage msgout("ADD_TO_GROUP");
@ -383,6 +394,7 @@ void CTeam::removeCharacter( CCharacter * player )
///\todo give him a player team Id
player->setTeamId( CTEAM::InvalidTeamId );
player->setLeagueId(DYN_CHAT_INVALID_CHAN);
player->updateTargetingChars();
// tell progression system this player has been removed from his team
@ -410,13 +422,19 @@ void CTeam::removeCharacter( CCharacter * player )
clearPlayerTeamDB( *_TeamMembers.begin() );
CCharacter * lastPlayer = PlayerManager.getOnlineChar( *_TeamMembers.begin() );
if ( lastPlayer )
{
lastPlayer->setTeamId( CTEAM::InvalidTeamId );
lastPlayer->setLeagueId(DYN_CHAT_INVALID_CHAN);
}
else
{
nlwarning("<CTeam removeCharacter> charId %s not found in the team", (*_TeamMembers.begin()).toString().c_str() );
return;
}
// remove league
setLeague("");
// remove the team chat group
TGroupId idGroupe = CHAT_GROUPS_IDS::getTeamChatGroupId(_TeamId);
CMessage msgRemoveGroup("REMOVE_GROUP");
@ -437,80 +455,26 @@ void CTeam::removeCharacter( CCharacter * player )
// if that was the leader, get another one
else if ( _LeaderId == charId )
{
_LeaderId = _SuccessorId;
_SuccessorId = CEntityId::Unknown;
for (list<CEntityId>::const_iterator it = _TeamMembers.begin(); it != _TeamMembers.end(); ++it)
{
if ( (*it) != _LeaderId )
{
_SuccessorId = (*it );
break;
setLeader(_SuccessorId);
}
}
// switch dyn chat speaker
CMissionManager::getInstance()->switchDynChatSpeaker(player,_LeaderId);
// inform the new leader
SM_STATIC_PARAMS_1(params1, STRING_MANAGER::player);
params1[0].setEId( charId );
PHRASE_UTILITIES::sendDynamicSystemMessage(TheDataset.getDataSetRow(_LeaderId), "TEAM_YOU_NEW_LEADER", params1);
// inform the group
SM_STATIC_PARAMS_2(params, STRING_MANAGER::player, STRING_MANAGER::player);
params[0].setEId( charId );
params[1].setEId( _LeaderId );
set<CEntityId> exclude;
exclude.insert( _LeaderId );
exclude.insert( charId );
sendDynamicMessageToMembers("TEAM_NEW_LEADER", params, exclude);
// update leader DB
CCharacter *leader = PlayerManager.getOnlineChar( _LeaderId );
if (leader)
{
// leader->_PropertyDatabase.setProp( "GROUP:LEADER_INDEX", -1 );
CBankAccessor_PLR::getGROUP().setLEADER_INDEX(leader->_PropertyDatabase, 0xf);
// leader->_PropertyDatabase.setProp( "GROUP:SUCCESSOR_INDEX", 0 );
CBankAccessor_PLR::getGROUP().setSUCCESSOR_INDEX(leader->_PropertyDatabase, 0);
}
else
nlwarning("<CTeam removeCharacter> invalid new leader %s", _LeaderId.toString().c_str() );
}
// if that was the successor, inform the new one
/* else if ( formerPos == 1 && _NbMembers > 2)
{
list<CEntityId>::iterator itTmp = _TeamMembers.begin();
++itTmp;
const CEntityId & successorId = *(itTmp);
CCharacter *successor = PlayerManager.getOnlineChar( successorId );
if (successor)
{
successor->_PropertyDatabase.setProp( "GROUP:SUCCESSOR_INDEX", -1 );
}
else
nlwarning("<CTeam removeCharacter> invalid new successor %s", successorId.toString().c_str() );
}
*/
else if ( _SuccessorId == charId )
{
for (list<CEntityId>::const_iterator it = _TeamMembers.begin(); it != _TeamMembers.end(); ++it)
{
if ( (*it) != _LeaderId )
{
_SuccessorId = (*it );
CCharacter *successor = PlayerManager.getOnlineChar( _SuccessorId );
if (successor)
{
// successor->_PropertyDatabase.setProp( "GROUP:SUCCESSOR_INDEX", -1 );
CBankAccessor_PLR::getGROUP().setSUCCESSOR_INDEX(successor->_PropertyDatabase, 0xf);
// The current successor dropped from team; set it to the next in line after leader
setSuccessor(1);
}
else
{
// A random member dropped from team; make sure the current successor is shown currectly
// in all team lists.
uint8 index = 0;
for (std::list<NLMISC::CEntityId>::iterator it = _TeamMembers.begin() ; it != _TeamMembers.end() ; ++it)
{
if (_SuccessorId == (*it))
break;
++index;
}
}
// Don't show a message because the successor hasn't actually changed.
setSuccessor(index, false);
}
for (std::list<NLMISC::CEntityId>::iterator it = _TeamMembers.begin() ; it != _TeamMembers.end() ; ++it)
@ -607,9 +571,106 @@ void CTeam::removeCharacter( CCharacter * player )
}// CTeam removeCharacter
void CTeam::setSuccessor( uint8 memberIdx )
void CTeam::setLeague(const string &leagueName)
{
TChanID chanId = _LeagueId;
if (_LeagueId != DYN_CHAT_INVALID_CHAN)
{
// Remove players from previous channel
_LeagueId = DYN_CHAT_INVALID_CHAN;
updateLeague();
// Remove channel if empty
vector<CEntityId> players;
if (!DynChatEGS.getPlayersInChan(chanId, players))
DynChatEGS.removeChan(chanId);
}
if (!leagueName.empty())
{
_LeagueId = DynChatEGS.addChan("league_"+toString(DynChatEGS.getNextChanID()), leagueName);
if (_LeagueId == DYN_CHAT_INVALID_CHAN)
{
nlinfo("Error channel creation !!!");
return;
}
// set historic size of the newly created channel
DynChatEGS.setHistoricSize(_LeagueId, 100);
}
updateLeague();
}
void CTeam::updateLeague()
{
for (list<CEntityId>::iterator it = _TeamMembers.begin() ; it != _TeamMembers.end() ; ++it)
{
CCharacter * ch = PlayerManager.getOnlineChar((*it));
if (ch != NULL && ch->getLeagueId() != _LeagueId)
{
ch->setLeagueId(_LeagueId);
}
}
}
uint8 CTeam::getSuccessorIndex()
{
list<CEntityId>::const_iterator it = _TeamMembers.begin();
uint8 i = 0;
for (; it != _TeamMembers.end(); ++it)
{
if ( (*it) == _SuccessorId )
break;
++i;
}
return i;
}
void CTeam::setLeader(CEntityId id, bool bMessage)
{
_LeaderId = id;
// Move new leader to top of list
_TeamMembers.remove(_LeaderId);
_TeamMembers.insert(_TeamMembers.begin(), _LeaderId);
// inform the new leader
SM_STATIC_PARAMS_1(params1, STRING_MANAGER::player);
params1[0].setEId( id );
PHRASE_UTILITIES::sendDynamicSystemMessage(TheDataset.getDataSetRow(_LeaderId), "TEAM_YOU_NEW_LEADER", params1);
// inform the group
SM_STATIC_PARAMS_2(params, STRING_MANAGER::player, STRING_MANAGER::player);
params[0].setEId( id );
params[1].setEId( _LeaderId );
set<CEntityId> exclude;
exclude.insert( _LeaderId );
exclude.insert( id );
sendDynamicMessageToMembers("TEAM_NEW_LEADER", params, exclude);
// New leader was successor, choose a new successor
if (id == _SuccessorId)
{
_SuccessorId = CEntityId::Unknown;
// Set the new successor to next in line
setSuccessor(1);
}
// update leader DB
CCharacter *leader = PlayerManager.getOnlineChar( _LeaderId );
if (leader)
{
// switch dyn chat speaker
CMissionManager::getInstance()->switchDynChatSpeaker(leader, _LeaderId);
CBankAccessor_PLR::getGROUP().setLEADER_INDEX(leader->_PropertyDatabase, 0xf);
}
else
nlwarning("<CTeam setLeader> invalid new leader %s", _LeaderId.toString().c_str() );
}
void CTeam::setLeader(uint8 memberIdx, bool bMessage)
{
/*
list<CEntityId>::const_iterator it = _TeamMembers.begin();
uint8 i = 0;
for (; it != _TeamMembers.end(); ++it)
@ -623,98 +684,58 @@ void CTeam::setSuccessor( uint8 memberIdx )
nlwarning("invalid team member %u : count is %u", memberIdx,_TeamMembers.size() );
return;
}
_SuccessorId = (*it);
SM_STATIC_PARAMS_1( params,STRING_MANAGER::player );
params[0].EId = (*it );
sendDynamicMessageToMembers("TEAM_NEW_SUCCESSOR",params);
CEntityId newLeaderId = (*it);
setLeader(newLeaderId, bMessage);
}
for (std::list<CEntityId>::const_iterator it = _TeamMembers.begin() ; it != _TeamMembers.end() ; ++it)
void CTeam::setSuccessor( uint8 memberIdx, bool bMessage)
{
list<CEntityId>::const_iterator it = _TeamMembers.begin();
uint8 i = 0;
for (; it != _TeamMembers.end(); ++it)
{
uint8 hp, sap, stamina;
uint32 nameId;
CCharacter* character = PlayerManager.getOnlineChar( (*it) );
if (character != NULL)
{
// update the current character team slot
///\todo: can be done outside the loop
if ( newCharacter->getPhysScores()._PhysicalScores[ SCORES::hit_points ].Max != 0)
hp = (uint8) ( ( float(TeamMembersStatusMaxValue) * ( newCharacter->getPhysScores()._PhysicalScores[ SCORES::hit_points ].Current ) ) / ( newCharacter->getPhysScores()._PhysicalScores[ SCORES::hit_points ].Max ) );
else
hp = 0;
if ( newCharacter->getPhysScores()._PhysicalScores[ SCORES::sap ].Max != 0)
sap = (uint8) ( ( float(TeamMembersStatusMaxValue) * ( newCharacter->getPhysScores()._PhysicalScores[ SCORES::sap ].Current ) ) / ( newCharacter->getPhysScores()._PhysicalScores[ SCORES::sap ].Max ) );
else
sap = 0;
if ( newCharacter->getPhysScores()._PhysicalScores[ SCORES::stamina ].Max != 0)
stamina = (uint8) ( ( float(TeamMembersStatusMaxValue) * ( newCharacter->getPhysScores()._PhysicalScores[ SCORES::stamina ].Current ) ) / ( newCharacter->getPhysScores()._PhysicalScores[ SCORES::stamina ].Max ) );
else
stamina = 0;
CMirrorPropValueRO<uint32> nameIndexValue1( TheDataset, newCharacter->getId(), "NameIndex" );
nameId = nameIndexValue1();
sprintf(buffer, "GROUP:%d:HP",position );
character->_PropertyDatabase.setProp( buffer, hp );
sprintf(buffer, "GROUP:%d:SAP",position );
character->_PropertyDatabase.setProp( buffer, sap );
sprintf(buffer, "GROUP:%d:STA",position );
character->_PropertyDatabase.setProp( buffer, stamina );
sprintf(buffer, "GROUP:%d:NAME",position );
character->_PropertyDatabase.setProp( buffer, nameId );
sprintf(buffer, "GROUP:%d:UID",position );
character->_PropertyDatabase.setProp( buffer, newCharacter->getEntityRowId().getCompressedIndex() );
sprintf(buffer, "GROUP:%d:PRESENT",position );
character->_PropertyDatabase.setProp( buffer, (uint8)1 );
// update the new character team slot corresponding to character
if ( character->getPhysScores()._PhysicalScores[ SCORES::hit_points ].Max != 0)
hp = (uint8) ( ( float(TeamMembersStatusMaxValue) * ( character->getPhysScores()._PhysicalScores[ SCORES::hit_points ].Current ) ) / ( character->getPhysScores()._PhysicalScores[ SCORES::hit_points ].Max ) );
else
hp = 0;
if ( character->getPhysScores()._PhysicalScores[ SCORES::sap ].Max != 0)
sap = (uint8) ( ( float(TeamMembersStatusMaxValue) * ( character->getPhysScores()._PhysicalScores[ SCORES::sap ].Current ) ) / ( character->getPhysScores()._PhysicalScores[ SCORES::sap ].Max ) );
else
sap = 0;
if ( character->getPhysScores()._PhysicalScores[ SCORES::stamina ].Max != 0)
stamina = (uint8) ( ( float(TeamMembersStatusMaxValue) * ( character->getPhysScores()._PhysicalScores[ SCORES::stamina ].Current ) ) / ( character->getPhysScores()._PhysicalScores[ SCORES::stamina ].Max ) );
else
stamina = 0;
CMirrorPropValueRO<uint32> nameIndexValue2( TheDataset, character->getId(), "NameIndex" );
nameId = nameIndexValue2();
sprintf(buffer, "GROUP:%d:HP",i );
newCharacter->_PropertyDatabase.setProp( buffer, hp );
sprintf(buffer, "GROUP:%d:SAP",i );
newCharacter->_PropertyDatabase.setProp( buffer, sap );
sprintf(buffer, "GROUP:%d:STA",i );
newCharacter->_PropertyDatabase.setProp( buffer, stamina );
sprintf(buffer, "GROUP:%d:NAME",i );
newCharacter->_PropertyDatabase.setProp( buffer, nameId );
sprintf(buffer, "GROUP:%d:UID",i );
newCharacter->_PropertyDatabase.setProp( buffer, character->getEntityRowId().getCompressedIndex() );
sprintf(buffer, "GROUP:%d:PRESENT",i );
newCharacter->_PropertyDatabase.setProp( buffer, (uint8)1 );
}
else
nlwarning("<CTeam::addCharacter> Unknown character %s", (*it).toString().c_str() );
if ( i == memberIdx )
break;
++i;
}
*/
if ( it == _TeamMembers.end() )
{
nlwarning("invalid team member %u : count is %u", memberIdx,_TeamMembers.size() );
return;
}
_SuccessorId = (*it);
i = 0;
for (it = _TeamMembers.begin() ; it != _TeamMembers.end() ; ++it)
{
CCharacter * ch = PlayerManager.getOnlineChar( (*it) );
if (ch)
{
// If this char is the successor, don't show
if (i == memberIdx)
{
CBankAccessor_PLR::getGROUP().setSUCCESSOR_INDEX(ch->_PropertyDatabase, 0xf);
}
else if (i < memberIdx)
{
// If the successor comes after this player in the list,
// bump it up one.
CBankAccessor_PLR::getGROUP().setSUCCESSOR_INDEX(ch->_PropertyDatabase, memberIdx - 1);
}
else
{
CBankAccessor_PLR::getGROUP().setSUCCESSOR_INDEX(ch->_PropertyDatabase, memberIdx);
}
}
++i;
}
if (bMessage)
{
SM_STATIC_PARAMS_1( params,STRING_MANAGER::player );
params[0].setEIdAIAlias(_SuccessorId, CAIAliasTranslator::getInstance()->getAIAlias(_SuccessorId));
sendDynamicMessageToMembers("TEAM_NEW_SUCCESSOR", params);
}
}
//---------------------------------------------------
@ -1130,22 +1151,65 @@ CMissionTeam* CTeam::getMissionByAlias( TAIAlias missionAlias )
return NULL;
}
void CTeam::updateMembersDb()
{
for (std::list<NLMISC::CEntityId>::iterator it = _TeamMembers.begin() ; it != _TeamMembers.end() ; ++it)
{
uint8 hp, sap, stamina;
uint32 nameId;
uint pos = 0;
CCharacter * ch1 = PlayerManager.getOnlineChar( (*it) );
if (ch1->getId() == _LeaderId)
{
CBankAccessor_PLR::getGROUP().setLEADER_INDEX(ch1->_PropertyDatabase, 0xf);
}
else
{
CBankAccessor_PLR::getGROUP().setLEADER_INDEX(ch1->_PropertyDatabase, 0);
}
///\todo log if nothing
if (ch1)
{
for (std::list<NLMISC::CEntityId>::iterator it2 = _TeamMembers.begin() ; it2 != _TeamMembers.end() ; ++it2)
{
if ( (*it) == (*it2) )
continue;
CBankAccessor_PLR::TGROUP::TArray &groupItem = CBankAccessor_PLR::getGROUP().getArray(pos);
CCharacter * ch2 = PlayerManager.getOnlineChar( (*it2) );
if (ch2 != NULL)
{
// update new char for old char
if ( ch2->getPhysScores()._PhysicalScores[ SCORES::hit_points ].Max != 0)
hp = (uint8) ( ( float(TeamMembersStatusMaxValue) * ( ch2->getPhysScores()._PhysicalScores[ SCORES::hit_points ].Current ) ) / ( ch2->getPhysScores()._PhysicalScores[ SCORES::hit_points ].Max ) );
else
hp = 0;
if ( ch2->getPhysScores()._PhysicalScores[ SCORES::sap ].Max != 0)
sap = (uint8) ( ( float(TeamMembersStatusMaxValue) * ( ch2->getPhysScores()._PhysicalScores[ SCORES::sap ].Current ) ) / ( ch2->getPhysScores()._PhysicalScores[ SCORES::sap ].Max ) );
else
sap = 0;
if ( ch2->getPhysScores()._PhysicalScores[ SCORES::stamina ].Max != 0)
stamina = (uint8) ( ( float(TeamMembersStatusMaxValue) * ( ch2->getPhysScores()._PhysicalScores[ SCORES::stamina ].Current ) ) / ( ch2->getPhysScores()._PhysicalScores[ SCORES::stamina ].Max ) );
else
stamina = 0;
CMirrorPropValueRO<uint32> nameIndexValue( TheDataset, ch2->getId(), "NameIndex" );
nameId = nameIndexValue();
groupItem.setHP(ch1->_PropertyDatabase, hp);
groupItem.setSAP(ch1->_PropertyDatabase, sap);
groupItem.setSTA(ch1->_PropertyDatabase, stamina);
groupItem.setNAME(ch1->_PropertyDatabase, nameId);
groupItem.setUID(ch1->_PropertyDatabase, ch2->getEntityRowId().getCompressedIndex());
groupItem.setPRESENT(ch1->_PropertyDatabase, true);
}
pos++;
}
}
}
}

View file

@ -23,6 +23,7 @@
#include "game_share/misc_const.h"
#include "game_share/string_manager_sender.h"
#include "game_share/scores.h"
#include "game_share/dyn_chat.h"
#include "mission_manager/mission_event.h"
#include "mission_manager/ai_alias_translator.h"
#include "team_manager/reward_sharing.h"
@ -73,10 +74,41 @@ public:
void removeCharacter( CCharacter * newChar );
/**
* set the successor of the team leader
* \param memberIdx is the index of the member in hte team
* return the index of team leader successor
*
*/
void setSuccessor( uint8 memberIdx );
uint8 getSuccessorIndex(void);
/**
* set the League
* \param leagueName is the name of League
*/
void setLeague(const std::string &leagueName);
/**
* update the League (set LeagueId to all teammates)
*/
void updateLeague();
/**
* set the team leader
* \param id is the Entity ID of the member in the team
* \param bMessage whether to show the message
*/
void setLeader(NLMISC::CEntityId id, bool bMessage = true);
/**
* set the team leader
* \param memberIdx is the index of the member in the team
* \param bMessage whether to show the message
*/
void setLeader(uint8 memberIdx, bool bMessage = true);
/**
* set the successor of the team leader
* \param memberIdx is the index of the member in the team
* \param bMessage whether to show the message
*/
void setSuccessor( uint8 memberIdx, bool bMessage = true );
/**
* get the leader of the team
@ -84,6 +116,12 @@ public:
*/
inline const NLMISC::CEntityId & getLeader() const { return _LeaderId; }
/**
* get the successor of the team
* \return successor Id
*/
inline const NLMISC::CEntityId & getSuccessor() const { return _SuccessorId; }
///\return number of team members
inline uint8 getTeamSize() const { return _NbMembers; }
@ -108,6 +146,12 @@ public:
///\return the team id
inline uint16 getTeamId() const { return _TeamId; }
///\return the League id
inline TChanID getLeagueId() const { return _LeagueId; }
///\return the League id
inline void setLeagueId(TChanID id) { _LeagueId = id; }
/// send a message to the team
void sendDynamicMessageToMembers(const std::string &msgName, const TVectorParamCheck &params, const std::set<NLMISC::CEntityId> &excluded) const;
inline void sendDynamicMessageToMembers(const std::string &msgName, const TVectorParamCheck &params) const
@ -171,7 +215,8 @@ public:
CMissionTeam* getMissionByAlias( TAIAlias missionAlias );
/*
void updateMembersDb();
/*
bool processMissionStepEvent(std::list< const CMissionEvent* > & eventList, uint missionIndex, uint32 stepIndex );
bool processMissionEvent( std::list< const CMissionEvent* > & eventList, uint missionIndex, uint32 stepIndex );
*/
@ -204,6 +249,9 @@ private:
///\id of the team
uint16 _TeamId;
///\id of the League (it's id of channel)
TChanID _LeagueId;
/// Team Members. The index of an entity in the container is its position
std::list<NLMISC::CEntityId> _TeamMembers;
@ -212,6 +260,7 @@ private:
/// id of the team leader
NLMISC::CEntityId _LeaderId;
/// successor id
NLMISC::CEntityId _SuccessorId;

View file

@ -71,6 +71,195 @@ void CTeamManager::addAllTeamsToChatGroup()
}
} // addAllTeamsToChatGroup //
//---------------------------------------------------
// leagueJoinProposal :
//---------------------------------------------------
void CTeamManager::joinLeagueProposal( CCharacter * leader, const CEntityId &targetId)
{
//check already done
nlassert(leader);
const NLMISC::CEntityId &leaderId = leader->getId();
if (targetId == leaderId )
{
CCharacter::sendDynamicSystemMessage( leader->getId(),"INVALID_LEAGUE_TARGET" );
return;
}
// get targeted player
CCharacter *invitedPlayer = PlayerManager.getOnlineChar( targetId );
if ( invitedPlayer == NULL )
{
CCharacter::sendDynamicSystemMessage( leader->getId(),"INVALID_LEAGUE_TARGET" );
return;
}
// god player are forbidden to team
if (leader->godMode() || invitedPlayer->godMode())
{
nlwarning("<CTeamManager joinLeagueProposal> Player %s invited %s, but at least on of them is god, forbidden",
leaderId.toString().c_str(),
targetId.toString().c_str());
CCharacter::sendDynamicSystemMessage( leader->getId(),"TEAM_GOD_FORBIDDEN" );
return;
}
TInviteRetCode code = isLeagueInvitableBy(invitedPlayer,leader);
if ( code == AlreadyInvited )
{
CCharacter::sendDynamicSystemMessage( leader->getId(),"LEAGUE_ALREADY_INVITED" );
return;
}
else if ( code == AlreadyInLeague )
{
CTeam * team = getRealTeam( invitedPlayer->getTeamId() );
CCharacter::sendDynamicSystemMessage( leader->getId(),"LEAGUE_ALREADY_IN_LEAGUE" );
return;
}
else if ( code == NotLeader )
{
CTeam * team = getRealTeam( invitedPlayer->getTeamId() );
joinLeagueProposal(leader, team->getLeader());
return;
}
else if ( code == CantInvite )
{
CCharacter::sendDynamicSystemMessage( leader->getId(),"LEAGUE_INVITOR_NOT_LEADER" );
return;
}
/// the invitor must not be in the ignore list of the target
if(invitedPlayer->hasInIgnoreList(leaderId))
{
SM_STATIC_PARAMS_1( params1, STRING_MANAGER::player );
params1[0].setEIdAIAlias( targetId, CAIAliasTranslator::getInstance()->getAIAlias( targetId) );
// Use the standard "player declines your offer". Don't use specific message because
// maybe not a good idea to inform a player that someone ignores him
CCharacter::sendDynamicSystemMessage( leaderId, "TEAM_DECLINE", params1 );
return;
}
//set the target's invitor
invitedPlayer->setLeagueInvitor(leaderId);
CEntityId msgTargetEId = targetId;
//send the appropriate string to the client
SM_STATIC_PARAMS_1(params, STRING_MANAGER::player);
params[0].setEIdAIAlias( leaderId, CAIAliasTranslator::getInstance()->getAIAlias(leaderId) );
uint32 txt = STRING_MANAGER::sendStringToClient(TheDataset.getDataSetRow(targetId), "LEAGUE_PROPOSAL", params );
CMessage msgout( "IMPULSION_ID" );
msgout.serial( const_cast<CEntityId&>(msgTargetEId) );
CBitMemStream bms;
nlverify ( GenericMsgManager.pushNameToStream( "PVP_CHALLENGE:INVITATION", bms) );
bms.serial( txt );
msgout.serialBufferWithSize((uint8*)bms.buffer(), bms.length());
sendMessageViaMirror( NLNET::TServiceId(msgTargetEId.getDynamicId()), msgout );
params[0].setEIdAIAlias( targetId, CAIAliasTranslator::getInstance()->getAIAlias( targetId ) );
PHRASE_UTILITIES::sendDynamicSystemMessage(leader->getEntityRowId(), "LEAGUE_INVITE", params);
leader->updateTarget();
}
//---------------------------------------------------
// joinLeagueDecline :
//---------------------------------------------------
void CTeamManager::joinLeagueDecline( const NLMISC::CEntityId &charId)
{
CCharacter * invited = PlayerManager.getOnlineChar(charId);
if ( invited == NULL )
{
nlwarning("<CTeamManager joinLeagueDecline>Invalid char %s",charId.toString().c_str());
return;
}
invited->setAfkState(false);
if ( invited->getLeagueInvitor() == CEntityId::Unknown )
{
nlwarning("<CTeamManager joinLeagueDecline>character %s has an Invalid invitor",charId.toString().c_str());
return;
}
//inform both players
SM_STATIC_PARAMS_1(params, STRING_MANAGER::player);
params[0].setEIdAIAlias( charId, CAIAliasTranslator::getInstance()->getAIAlias( charId) );
PHRASE_UTILITIES::sendDynamicSystemMessage(TheDataset.getDataSetRow(invited->getTeamInvitor()), "LEAGUE_DECLINE", params);
params[0].setEIdAIAlias( invited->getTeamInvitor(), CAIAliasTranslator::getInstance()->getAIAlias( invited->getTeamInvitor() ) );
PHRASE_UTILITIES::sendDynamicSystemMessage(invited->getEntityRowId(), "LEAGUE_YOU_DECLINE", params);
//cancel the proposal
invited->setLeagueInvitor( CEntityId::Unknown );
} // joinLeagueDecline //
//---------------------------------------------------
// joinLeagueAccept :
//---------------------------------------------------
void CTeamManager::joinLeagueAccept( const NLMISC::CEntityId &charId)
{
// get the invited char
CCharacter * invited = PlayerManager.getOnlineChar(charId);
if ( invited == NULL )
{
nlwarning("<CTeamManager joinLeagueAccept>Invalid char %s",charId.toString().c_str());
return;
}
// get the invitor id
const NLMISC::CEntityId & invitorId = invited->getLeagueInvitor();
if ( invitorId == CEntityId::Unknown )
{
nlwarning("<CTeamManager joinLeagueAccept>character %s has an Invalid invitor",charId.toString().c_str());
return;
}
//get the invitor char
CCharacter * invitor = PlayerManager.getOnlineChar(invitorId);
if ( invitor == NULL )
{
nlwarning("<CTeamManager joinLeagueAccept>character %s, Invalid invitor id %s",charId.toString().c_str(),invitorId.toString().c_str());
invited->setLeagueInvitor( CEntityId::Unknown );
return;
}
invitor->setAfkState(false);
//cancel the proposal
invited->setLeagueInvitor( CEntityId::Unknown );
CTeam *teamInvitor;
CTeam *teamInvited;
//if the invited player had a fake team, remove it
teamInvited = getRealTeam(invited->getTeamId());
teamInvitor = getRealTeam(invitor->getTeamId());
if ( !teamInvitor )
{
nlwarning("<CTeamManager joinLeagueAccept>character %s, invitor id %s, the invited or invitor player is not in a valid team. ",charId.toString().c_str(),invitor->getId().toString().c_str() );
return;
}
// check that the invitor team have league else create them
if (teamInvitor->getLeagueId() == DYN_CHAT_INVALID_CHAN )
{
teamInvitor->setLeague("League");
}
if (teamInvited) {
const string playerName = CEntityIdTranslator::getInstance()->getByEntity(invited->getId()).toString();
CPVPManager2::getInstance()->broadcastMessage(teamInvitor->getLeagueId(), string("<TEAM>"), "<-- "+playerName);
teamInvited->setLeagueId(teamInvitor->getLeagueId());
teamInvited->updateLeague();
} else {
const string playerName = CEntityIdTranslator::getInstance()->getByEntity(invited->getId()).toString();
CPVPManager2::getInstance()->broadcastMessage(teamInvitor->getLeagueId(), string("<PLAYER>"), "<-- "+playerName);
invited->setLeagueId(teamInvitor->getLeagueId(), true);
}
} // joinLeagueAccept //
//---------------------------------------------------
// joinProposal :
//---------------------------------------------------
@ -90,7 +279,7 @@ void CTeamManager::joinProposal( CCharacter * leader, const CEntityId &targetId)
CCharacter *invitedPlayer = PlayerManager.getOnlineChar( targetId );
if ( invitedPlayer == NULL )
{
CCharacter::sendDynamicSystemMessage( leader->getId(),"INVALID_TEAM_TARGET" );
CCharacter::sendDynamicSystemMessage( leader->getId(),"INVALID_LEAGUE_TARGET" );
return;
}
@ -117,7 +306,7 @@ void CTeamManager::joinProposal( CCharacter * leader, const CEntityId &targetId)
}
else if ( code == CantInviteEnemy )
{
CCharacter::sendDynamicSystemMessage( leader->getId(),"TEAM_CANT_INVITE_ENEMIE" );
CCharacter::sendDynamicSystemMessage( leader->getId(),"TEAM_CANT_INVITE_ENEMY" );
return;
}
else if ( code == CantInvite )
@ -423,7 +612,7 @@ void CTeamManager::removeCharacter( const CEntityId &charId )
{
const list<CEntityId> &members = team->getTeamMembers();
CEntityId eId(*(++members.begin()));
CEntityId eId(team->getSuccessor());
params[0].setEIdAIAlias( eId, CAIAliasTranslator::getInstance()->getAIAlias(eId) );
PHRASE_UTILITIES::sendDynamicSystemMessage(TheDataset.getDataSetRow(charId), "TEAM_YOU_LEAVE_LEADER", params);
}
@ -505,6 +694,48 @@ void CTeamManager::removeFakeTeam(CCharacter * player)
nlwarning("<CTeamManager removeFakeTeam> char %s the team id %d is out of bounds (nb teams = %d)",player->getId().toString().c_str(),player->getTeamId(),_Teams.size());
}// removeFakeTeam
//---------------------------------------------------
// isLeagueInvitableBy :
//---------------------------------------------------
CTeamManager::TInviteRetCode CTeamManager::isLeagueInvitableBy(CCharacter * invited, CCharacter * invitor )
{
// check must be done before
nlassert( invited );
nlassert( invitor );
if ( !TheDataset.isAccessible(invited->getEntityRowId()) || !TheDataset.isAccessible(invitor->getEntityRowId()))
return CantInvite;
// check that the invitor is in team
CTeam * team = getRealTeam( invitor->getTeamId() );
if (!team)
return CantInvite;
// check that the invitor is the leader
if (team->getLeader() != invitor->getId() )
return CantInvite;
// check that the invited don't have league
if (invited->getLeagueId() != DYN_CHAT_INVALID_CHAN)
return AlreadyInLeague;
// check if target is not already invited
if( invited->getLeagueInvitor() != CEntityId::Unknown )
return AlreadyInvited;
// get the target team
team = getRealTeam( invited->getTeamId() );
if (!team)
return NotInTeam;
// check that the invited is the leader
if (team->getLeader() != invited->getId() )
return NotLeader;
return Ok;
}
//---------------------------------------------------
// processMissionTeamEvent :
//---------------------------------------------------
@ -519,6 +750,7 @@ CTeamManager::TInviteRetCode CTeamManager::isInvitableBy(CCharacter * invited, C
{
return AlreadyInvited;
}
// get the target team, which must be fake
CTeam * team = getRealTeam( invited->getTeamId() );
if( team )
@ -528,7 +760,8 @@ CTeamManager::TInviteRetCode CTeamManager::isInvitableBy(CCharacter * invited, C
// check that the invitor is alone or a group leader
team = getRealTeam( invitor->getTeamId() );
if ( team && team->getLeader()!= invitor->getId() )
if (team && team->getLeader()!= invitor->getId())
{
return CantInvite;
}
@ -538,9 +771,9 @@ CTeamManager::TInviteRetCode CTeamManager::isInvitableBy(CCharacter * invited, C
return CantInvite;
// cannot invite enemy in faction PvP zones
if( CPVPManager2::getInstance()->isOffensiveActionValid( invited, invitor, true ) )
/* if( CPVPManager2::getInstance()->isOffensiveActionValid( invited, invitor, true ) )
if( invited->getPvPRecentActionFlag() || invitor->getPvPRecentActionFlag() )
return CantInviteEnemy;
return CantInviteEnemy;*/
return Ok;
}

View file

@ -31,7 +31,7 @@ class CCharacter;
///\todo: avoid team reallocation problems?
///\todo: check if we have to remove team from IOS if crash/shutdown
///\todo successor index sert à rien???
///\todo successor index is useful ?
/**
* CTeamManager
@ -47,9 +47,12 @@ public:
{
AlreadyInvited,
AlreadyInTeam,
AlreadyInLeague,
CantInviteEnemy,
CantInvite,
Ok,
NotInTeam,
NotLeader,
};
/// default constructor
CTeamManager()
@ -58,6 +61,13 @@ public:
/// add all created to chat groups
void addAllTeamsToChatGroup();
/// player leaderId invites player targetId to join his League. Only leaders can invite other leaders
void joinLeagueProposal( CCharacter * leader, const NLMISC::CEntityId &targetId );
/// player charId declines an invitation
void joinLeagueDecline( const NLMISC::CEntityId &charId );
/// player charId accepts an invitation
void joinLeagueAccept( const NLMISC::CEntityId &charId );
/// player leaderId invites plyer targetId to join his team. Only leaders can invite
void joinProposal( CCharacter * leader, const NLMISC::CEntityId &targetId );
@ -104,6 +114,13 @@ public:
*/
TInviteRetCode isInvitableBy(CCharacter * invited, CCharacter * invitor );
/**
* \param invited: character being invited
* \param invitor: character inviting the other one
* \return true if the invited is invitable by the invitor
*/
TInviteRetCode isLeagueInvitableBy(CCharacter * invited, CCharacter * invitor );
/**
* PvP attack occurs in a team
* \param actor is the attacker character

View file

@ -248,9 +248,9 @@ public :
* \param target is the id of the target char
* \param phraseId is the phrase id (uint32)
*/
void sendEmoteTextToPlayer( const TDataSetRow& target,uint32 phraseId )
void sendEmoteTextToPlayer( const TDataSetRow& sender, const TDataSetRow& target, uint32 phraseId )
{
sendChat2Ex( CChatGroup::say, target, phraseId );
sendChat2Ex( CChatGroup::say, target, phraseId, sender );
}
/**

View file

@ -495,8 +495,8 @@ void CInputOutputService::scanMirrorChanges()
if (entityId.getType() == RYZOMID::player)
{
// init event faction ID in mirror
CMirrorPropValue<TYPE_EVENT_FACTION_ID> propEventFactionId( TheDataset, entityIndex, DSPropertyEVENT_FACTION_ID );
propEventFactionId = 0;
//CMirrorPropValue<TYPE_EVENT_FACTION_ID> propEventFactionId( TheDataset, entityIndex, DSPropertyEVENT_FACTION_ID );
//propEventFactionId = 0;
}
entityIndex = DataSet->getNextAddedEntity();
@ -620,7 +620,7 @@ void CInputOutputService::addCharacterName( const TDataSetRow& chId, const ucstr
if( itInfos == _NameToInfos.end() )
{
// New name does not exist
charInfos->ShortName = ucstring(name);
charInfos->ShortName.fromUtf8(name);
}
// Save the old name only if new name is not found (and the player is getting original name back)

View file

@ -709,8 +709,8 @@ static void cbCharacterEventFaction(CMessage& msgin, const string &serviceName,
else
ci->UntranslatedEventFactionId = SM->storeString( eventFaction );
CMirrorPropValue<TYPE_EVENT_FACTION_ID> propEventFactionId( TheDataset, chId, DSPropertyEVENT_FACTION_ID );
propEventFactionId = SM->translateEventFaction( ci->UntranslatedEventFactionId );
// CMirrorPropValue<TYPE_EVENT_FACTION_ID> propEventFactionId( TheDataset, chId, DSPropertyEVENT_FACTION_ID );
// propEventFactionId = SM->translateEventFaction( ci->UntranslatedEventFactionId );
}
else
{
@ -1513,12 +1513,14 @@ void cbEmoteCrowd( CMessage& msgin, const string &serviceName, TServiceId servic
//-----------------------------------------------
void cbEmoteSolePlayer( CMessage& msgin, const string &serviceName, TServiceId serviceId )
{
TDataSetRow sender;
TDataSetRow target;
uint32 phraseId;
msgin.serial(sender);
msgin.serial(target);
msgin.serial(phraseId);
CChatManager &cm = IOS->getChatManager();
cm.sendEmoteTextToPlayer( target,phraseId );
cm.sendEmoteTextToPlayer(sender, target, phraseId );
}
@ -1567,6 +1569,10 @@ void cbSetPhrase( CMessage& msgin, const string &serviceName, TServiceId service
SM->setPhrase(msgin);
}
void cbSetPhraseLang( CMessage& msgin, const string& serviceName, TServiceId serviceId )
{
SM->setPhraseLang(msgin);
}
//-----------------------------------------------
// Add a new channel in the dyn chat
@ -2048,6 +2054,7 @@ TUnifiedCallbackItem CbIOSArray[]=
{ "CUSTOM_EMOTE", cbCustomEmote }, // EGS wants IOS to dispatch an emote custom text to all users around
{ "SET_PHRASE", cbSetPhrase }, // AIS wants IOS to change a phrase content
{ "SET_PHRASE_LANG", cbSetPhraseLang }, // AIS or EGS wants IOS to change a phrase content for a language
{ "UPDATE_AIALIAS", cbUpdateAIAlias},

View file

@ -231,7 +231,8 @@ public:
{
static const string NAME("name");
if (rep.Format != NAME)
CSString format = rep.Format;
if (format.left(4) != NAME)
{
// can't replace this parameter, write a del char
const static string s("\010");
@ -270,7 +271,8 @@ public:
if (playerInfo != 0)
{
static const string NAME("name");
if (rep.Format != NAME)
CSString format = rep.Format;
if (format.left(4) != NAME)
{
// can't replace this parameter, write a del char
const static string s("\010");

View file

@ -1110,6 +1110,30 @@ void CStringManager::setPhrase(NLNET::CMessage &message)
setPhrase(phraseName, phraseContent);
}
/*
* Replace a phrase in specified language (message handler)
*/
void CStringManager::setPhraseLang(NLNET::CMessage &message)
{
std::string phraseName;
ucstring phraseContent;
std::string langString;
try
{
message.serial(phraseName);
message.serial(phraseContent);
message.serial(langString);
}
catch( Exception& e )
{
nlwarning("<setPhrase> %s",e.what());
return;
}
TLanguages lang = checkLanguageCode(langString);
setPhrase(phraseName, phraseContent, lang);
}
/*
* Replace a phrase in default language(s)
*/

View file

@ -673,6 +673,7 @@ public:
}
void setPhrase(NLNET::CMessage &message);
void setPhraseLang(NLNET::CMessage &message);
void setPhrase(std::string const& phraseName, ucstring const& phraseContent);
void setPhrase(std::string const& phraseName, ucstring const& phraseContent, TLanguages language);
/// Returns the language used in the setPhrase command.

View file

@ -1799,8 +1799,8 @@ void CStringManager::reloadEventFactions(NLMISC::CLog * log, std::string fileNam
{
if ( TheDataset.isAccessible(ci->DataSetIndex) )
{
CMirrorPropValue<TYPE_EVENT_FACTION_ID> propEventFactionId( TheDataset, ci->DataSetIndex, DSPropertyEVENT_FACTION_ID );
propEventFactionId = SM->translateEventFaction( ci->UntranslatedEventFactionId );
// CMirrorPropValue<TYPE_EVENT_FACTION_ID> propEventFactionId( TheDataset, ci->DataSetIndex, DSPropertyEVENT_FACTION_ID );
// propEventFactionId = SM->translateEventFaction( ci->UntranslatedEventFactionId );
}
}
}

View file

@ -273,8 +273,10 @@ namespace ENTITYLOC
uint32 _CharId;
// Type of the event : true for a connection, false otherwise
bool _Connection;
// The privilege of the character (e.g :GM:)
// The privilege of the character (e.g :GM:DEV:)
std::string _Privilege;
// Last Connection Date
uint32 _lastConnectionDate;
public:
// The character id of the character
uint32 getCharId() const
@ -300,7 +302,7 @@ namespace ENTITYLOC
_Connection = value;
}
// The privilege of the character (e.g :GM:)
// The privilege of the character (e.g :GM:DEV:)
std::string getPrivilege() const
{
return _Privilege;
@ -311,13 +313,26 @@ namespace ENTITYLOC
_Privilege = value;
}
// Last Connection Date
uint32 getlastConnectionDate() const
{
return _lastConnectionDate;
}
void setlastConnectionDate(uint32 value)
{
_lastConnectionDate = value;
}
bool operator == (const TCharConnectionEvent &other) const
{
return _CharId == other._CharId
&& _Connection == other._Connection
&& _Privilege == other._Privilege;
&& _Privilege == other._Privilege
&& _lastConnectionDate == other._lastConnectionDate;
}
@ -332,6 +347,7 @@ namespace ENTITYLOC
s.serial(_CharId);
s.serial(_Connection);
s.serial(_Privilege);
s.serial(_lastConnectionDate);
}

View file

@ -70,7 +70,8 @@
<property type="uint32" name="CharId" doc="The character id the the character"/>
<property type="bool" name="Connection" doc="Type of the event : true for a connection, false otherwise"/>
<property type="std::string" name="Privilege" doc="The privilege of the character (e.g :GM:)"/>
<property type="std::string" name="Privilege" doc="The privilege of the character (e.g :GM:DEV:)"/>
<property type="uint32" name="lastConnectionDate" doc="Last Connection Date"/>
</class>

View file

@ -503,6 +503,26 @@ public:
virtual void callback (const std::string &name, NLNET::TServiceId id) {}
};
//----------------------------------------------------------------------------
// AIS -> EGS send bot url information
//----------------------------------------------------------------------------
class CCreatureSetUrlMsg : public CMirrorTransportClass
{
public:
std::vector<TDataSetRow> Entities;
std::string ActionName;
std::string Url;
virtual void description ()
{
className ("CCreatureSetUrlMsg");
propertyCont ("Entities", PropDataSetRow, Entities);
property ("ActionName", PropString, std::string(), ActionName);
property ("Url", PropString, std::string(), Url);
}
virtual void callback (const std::string &name, NLNET::TServiceId id) {}
};
//----------------------------------------------------------------------------
// AIS -> EGS send despawn of aiinstance
//----------------------------------------------------------------------------
@ -582,6 +602,27 @@ public:
virtual void callback (const std::string &name, NLNET::TServiceId id) {}
};
//----------------------------------------------------------------------------
// AIS -> EGS ais change creature Max HP
//----------------------------------------------------------------------------
class CChangeCreatureMaxHPMsg : public CMirrorTransportClass
{
public:
std::vector<TDataSetRow> Entities;
std::vector<uint32> MaxHp;
std::vector<uint8> SetFull;
virtual void description ()
{
className ("CChangeCreatureMaxHPMsg");
propertyCont ("Entities", PropDataSetRow, Entities);
propertyCont ("MaxHp", PropUInt32, MaxHp);
propertyCont ("SetFull", PropUInt8, SetFull);
}
virtual void callback (const std::string &name, NLNET::TServiceId id) {}
};
//----------------------------------------------------------------------------
// AIS -> EGS ais change creature HP
//----------------------------------------------------------------------------

View file

@ -47,7 +47,7 @@ std::string buildChatDebugString(const std::vector<uint32> &ShopCategories,
class CNpcChatProfile
{
public:
CNpcChatProfile() : /*_guildCreator(false),*/ /*_dynamicMissionGiver(false),*/ _FilterExplicitActionTradeByPlayerRace(false),
CNpcChatProfile() : /*_guildCreator(false),*/ /*_dynamicMissionGiver(false),*/ _Organization(0), _FilterExplicitActionTradeByPlayerRace(false),
_ExplicitActionSPType(EGSPD::CSPType::Unknown), _FilterExplicitActionTradeByBotRace(true){}
CNpcChatProfile(const CNpcChatProfile &other0,const CNpcChatProfile &other1);
virtual ~CNpcChatProfile() {}
@ -84,6 +84,7 @@ public:
const std::string &getWebPageName() const { return _WebPageName; }
const NLMISC::CSheetId &getOutpost() const { return _Outpost; }
const uint32 getOrganization() const { return _Organization; }
protected:
std::vector< RYMSG::TExplicitSale > _ExplicitSales;
@ -125,6 +126,8 @@ protected:
std::vector<std::string> _OptionalProperties;
NLMISC::CSheetId _Outpost;
uint32 _Organization;
};
//----------------------------------------------------------------

View file

@ -42,6 +42,7 @@ public:
uint16 PetIdx; // must be returned to EGS with CPetSpawnConfirmationMsg class
sint32 Coordinate_X, Coordinate_Y, Coordinate_H; //For NEAR_POINT mode
float Heading; //For NEAR_POINT mode
ucstring CustomName;
virtual void description ()
{
@ -55,6 +56,7 @@ public:
property ("Coordinate_Y", PropSInt32, (sint32)0, Coordinate_Y);
property ("Coordinate_H", PropSInt32, (sint32)0, Coordinate_H);
property ("Heading", PropFloat, 0.0f, Heading);
property ("CustomName", PropUCString, ucstring(""), CustomName);
}
virtual void callback (const std::string &name, NLNET::TServiceId id) {};

View file

@ -23,10 +23,10 @@ namespace PVP_RELATION
{
enum TPVPRelation
{
Neutral,
NeutralPVP,
Ally,
Ennemy,
Neutral, // Only Heal, no propagation
NeutralPVP, // No Heal, No attack
Ally, // Only heal, propagation
Ennemy, // Only attack, propagation
Unknown
};

View file

@ -582,6 +582,8 @@ namespace ENTITYLOC
void _charConnected(NLNET::IModuleProxy *sender, uint32 charId, uint32 lastDisconnectionDate, uint32 shardId)
{
uint32 lastConnectionDate = CTime::getSecondsSince1970();
TCharMap::iterator it(_ConnectedChars.find(charId));
if (it != _ConnectedChars.end())
{
@ -605,7 +607,7 @@ namespace ENTITYLOC
ci.CharName = toLower(fullName);
// update the last played date
character->setLastPlayedDate(CTime::getSecondsSince1970());
character->setLastPlayedDate(lastConnectionDate);
character->update(_RingDB);
}
@ -634,6 +636,7 @@ namespace ENTITYLOC
cce.setCharId(charId);
cce.setConnection(true);
cce.setPrivilege(privilege);
cce.setlastConnectionDate(lastConnectionDate);
connections.push_back(cce);
CEntityLocatorClientProxy::broadcast_connectionEvents(_ClientTracker.getTrackedModules().begin(), _ClientTracker.getTrackedModules().end(),
@ -658,7 +661,7 @@ namespace ENTITYLOC
if (character !=NULL)
{
// update the last played date
character->setLastPlayedDate(CTime::getSecondsSince1970());
character->setLastPlayedDate(0);
character->update(_RingDB);
}