Changed: #1135 Merge changes from Ryzom patch 1.10

hg/feature/sound
kervala 14 years ago
parent 5512b47d68
commit f32bb4cfb7

@ -359,6 +359,13 @@ CCharacterCL::CCharacterCL()
_EventFactionId = 0; _EventFactionId = 0;
_PvpMode = PVP_MODE::None; _PvpMode = PVP_MODE::None;
_PvpClan = PVP_CLAN::None; _PvpClan = PVP_CLAN::None;
for (uint8 i = 0; i < PVP_CLAN::NbClans; i++)
{
_PvpAllies[i] = false;
_PvpEnemies[i] = false;
}
_OutpostId = 0; _OutpostId = 0;
_OutpostSide = OUTPOSTENUMS::UnknownPVPSide; _OutpostSide = OUTPOSTENUMS::UnknownPVPSide;
@ -1853,12 +1860,16 @@ void CCharacterCL::updateVisualPropertyPvpMode(const NLMISC::TGameCycle &/* game
//----------------------------------------------- //-----------------------------------------------
void CCharacterCL::updateVisualPropertyPvpClan(const NLMISC::TGameCycle &/* gameCycle */, const sint64 &prop) void CCharacterCL::updateVisualPropertyPvpClan(const NLMISC::TGameCycle &/* gameCycle */, const sint64 &prop)
{ {
_PvpClan = PVP_CLAN::TPVPClan(prop); // get fames signs from prop
if (_PvpClan >= PVP_CLAN::NbClans) for (uint8 fameIdx = 0; fameIdx < 7; fameIdx++)
{ {
//nlwarning("updateVisualPropertyPvpClan: received invalid PvP clan: %"NL_I64"u", prop); _PvpAllies[fameIdx] = prop & (1 << 2*fameIdx);
_PvpClan = PVP_CLAN::None; _PvpEnemies[fameIdx] = prop & (1 << ((2*fameIdx)+1));
} }
_ClanCivMaxFame = PVP_CLAN::TPVPClan((prop & (0x03 << 2*7)) >> 2*7);
_ClanCultMaxFame = PVP_CLAN::TPVPClan(4 + ((prop & (0x03 << 2*8)) >> 2*8));
buildInSceneInterface(); buildInSceneInterface();
} // updateVisualPropertyPvpClan // } // updateVisualPropertyPvpClan //

@ -372,6 +372,44 @@ public:
void setPvpMode(uint8 mode) { _PvpMode=mode; } void setPvpMode(uint8 mode) { _PvpMode=mode; }
virtual PVP_CLAN::TPVPClan getPvpClan() const { return _PvpClan; } virtual PVP_CLAN::TPVPClan getPvpClan() const { return _PvpClan; }
void setPvpClan(PVP_CLAN::TPVPClan clan) { _PvpClan=clan; } void setPvpClan(PVP_CLAN::TPVPClan clan) { _PvpClan=clan; }
virtual PVP_CLAN::TPVPClan getClanCivMaxFame() const { return _ClanCivMaxFame; }
void setClanCivMaxFame(PVP_CLAN::TPVPClan clan) { _ClanCivMaxFame=clan; }
virtual PVP_CLAN::TPVPClan getClanCultMaxFame() const { return _ClanCultMaxFame; }
void setClanCultMaxFame(PVP_CLAN::TPVPClan clan) { _ClanCultMaxFame=clan; }
virtual bool isPvpAlly(uint8 faction) const { if (faction < PVP_CLAN::NbClans) return _PvpAllies[faction]; else return false; }
virtual bool isPvpEnnemy(uint8 faction) const { if (faction < PVP_CLAN::NbClans) return _PvpEnemies[faction]; else return false; }
virtual bool isPvpMarauder() const
{
for (uint8 i = 0; i < 4; i++)
if (!_PvpEnemies[i])
return false;
return true;
}
virtual bool isPvpTrytonist() const
{
if (_PvpEnemies[4] && _PvpEnemies[6])
return true;
return false;
}
virtual bool isPvpPrimas() const
{
if (_PvpAllies[4] && _PvpAllies[6])
return true;
return false;
}
virtual bool isPvpRanger() const
{
for (uint8 i = 0; i < 4; i++)
if (!_PvpAllies[i])
return false;
return true;
}
virtual uint16 getOutpostId() const { return _OutpostId; } virtual uint16 getOutpostId() const { return _OutpostId; }
virtual OUTPOSTENUMS::TPVPSide getOutpostSide() const { return _OutpostSide; } virtual OUTPOSTENUMS::TPVPSide getOutpostSide() const { return _OutpostSide; }
@ -690,6 +728,10 @@ protected:
uint32 _EventFactionId; uint32 _EventFactionId;
uint8 _PvpMode; uint8 _PvpMode;
PVP_CLAN::TPVPClan _PvpClan; PVP_CLAN::TPVPClan _PvpClan;
PVP_CLAN::TPVPClan _ClanCivMaxFame;
PVP_CLAN::TPVPClan _ClanCultMaxFame;
bool _PvpAllies[PVP_CLAN::NbClans];
bool _PvpEnemies[PVP_CLAN::NbClans];
uint16 _OutpostId; uint16 _OutpostId;
OUTPOSTENUMS::TPVPSide _OutpostSide; OUTPOSTENUMS::TPVPSide _OutpostSide;

@ -40,6 +40,7 @@
#include "game_share/generic_xml_msg_mngr.h" #include "game_share/generic_xml_msg_mngr.h"
#include "game_share/msg_client_server.h" #include "game_share/msg_client_server.h"
#include "game_share/chat_group.h" #include "game_share/chat_group.h"
#include "interface_v3/skill_manager.h"
using namespace std; using namespace std;
using namespace NLMISC; using namespace NLMISC;
@ -948,19 +949,29 @@ void CClientChatManager::buildTellSentence(const ucstring &sender, const ucstrin
else else
{ {
ucstring name = CEntityCL::removeTitleAndShardFromName(sender); ucstring name = CEntityCL::removeTitleAndShardFromName(sender);
ucstring csr;
// special case where there is only a title, very rare case for some NPC // special case where there is only a title, very rare case for some NPC
if (name.empty()) if (name.empty())
{ {
// we need the gender to display the correct title // we need the gender to display the correct title
CCharacterCL *entity = dynamic_cast<CCharacterCL*>(EntitiesMngr.getEntityByName(sender, true, true)); CCharacterCL *entity = dynamic_cast<CCharacterCL*>(EntitiesMngr.getEntityByName(sender, true, true));
bool bWoman = entity && entity->getGender() == GSGENDER::female; bool bWoman = entity && entity->getGender() == GSGENDER::female;
name = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(CEntityCL::getTitleFromName(sender), bWoman); name = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(CEntityCL::getTitleFromName(sender), bWoman);
}
else
{
// Does the char have a CSR title?
csr = CHARACTER_TITLE::isCsrTitle(CEntityCL::getTitleFromName(sender)) ? ucstring("(CSR) ") : ucstring("");
} }
result = name + ucstring(" ") + CI18N::get("tellsYou") + ucstring(": ") + msg; ucstring cur_time;
if (CInterfaceManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_TIMES_IN_CHAT_CB", false)->getValueBool())
{
cur_time = CInterfaceManager::getTimestampHuman();
}
result = cur_time + csr + name + ucstring(" ") + CI18N::get("tellsYou") + ucstring(": ") + msg;
} }
} }
@ -992,27 +1003,41 @@ void CClientChatManager::buildChatSentence(TDataSetIndex /* compressedSenderInde
// Format the sentence with the provided sender name // Format the sentence with the provided sender name
ucstring senderName = CEntityCL::removeTitleAndShardFromName(sender); ucstring senderName = CEntityCL::removeTitleAndShardFromName(sender);
// Add time if not a &bbl&
ucstring cur_time;
if (cat.toString() != "&bbl&")
{
if (CInterfaceManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_TIMES_IN_CHAT_CB", false)->getValueBool())
{
cur_time = CInterfaceManager::getTimestampHuman();
}
}
ucstring csr;
// Does the char have a CSR title?
csr = CHARACTER_TITLE::isCsrTitle(CEntityCL::getTitleFromName(sender)) ? ucstring("(CSR) ") : ucstring("");
if (UserEntity && senderName == UserEntity->getDisplayName()) if (UserEntity && senderName == UserEntity->getDisplayName())
{ {
// the player talks // The player talks
switch(type) switch(type)
{ {
case CChatGroup::shout: case CChatGroup::shout:
result = cat + CI18N::get("youShout") + ucstring(" : ") + finalMsg; result = cat + cur_time + csr + CI18N::get("youShout") + ucstring(": ") + finalMsg;
break; break;
default: default:
result = cat + CI18N::get("youSay") + ucstring(" : ") + finalMsg; result = cat + cur_time + csr + CI18N::get("youSay") + ucstring(": ") + finalMsg;
break; break;
} }
} }
else else
{ {
// special case where there is only a title, very rare case for some NPC // Special case where there is only a title, very rare case for some NPC
if (senderName.empty()) if (senderName.empty())
{ {
// we need the gender to display the correct title
CCharacterCL *entity = dynamic_cast<CCharacterCL*>(EntitiesMngr.getEntityByName(sender, true, true)); CCharacterCL *entity = dynamic_cast<CCharacterCL*>(EntitiesMngr.getEntityByName(sender, true, true));
// We need the gender to display the correct title
bool bWoman = entity && entity->getGender() == GSGENDER::female; bool bWoman = entity && entity->getGender() == GSGENDER::female;
senderName = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(CEntityCL::getTitleFromName(sender), bWoman); senderName = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(CEntityCL::getTitleFromName(sender), bWoman);
@ -1021,10 +1046,10 @@ void CClientChatManager::buildChatSentence(TDataSetIndex /* compressedSenderInde
switch(type) switch(type)
{ {
case CChatGroup::shout: case CChatGroup::shout:
result = cat + senderName + ucstring(" ") + CI18N::get("heShout") + ucstring(" : ") + finalMsg; result = cat + cur_time + csr + senderName + ucstring(" ") + CI18N::get("heShout") + ucstring(": ") + finalMsg;
break; break;
default: default:
result = cat + senderName + ucstring(" ") + CI18N::get("heSays") + ucstring(" : ") + finalMsg; result = cat + cur_time + csr + senderName + ucstring(" ") + CI18N::get("heSays") + ucstring(": ") + finalMsg;
break; break;
} }
} }
@ -1157,7 +1182,13 @@ class CHandlerTell : public IActionHandler
prop.readRGBA("UI:SAVE:CHAT:COLORS:SPEAKER"," "); prop.readRGBA("UI:SAVE:CHAT:COLORS:SPEAKER"," ");
ucstring finalMsg; ucstring finalMsg;
CChatWindow::encodeColorTag(prop.getRGBA(), finalMsg, false); CChatWindow::encodeColorTag(prop.getRGBA(), finalMsg, false);
finalMsg += CI18N::get("youTell") + ": "; ucstring cur_time;
if (CInterfaceManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_TIMES_IN_CHAT_CB", false)->getValueBool())
{
cur_time = CInterfaceManager::getTimestampHuman();
}
ucstring csr = CHARACTER_TITLE::isCsrTitle(UserEntity->getTitleRaw()) ? "(CSR) " : "";
finalMsg += cur_time + csr + CI18N::get("youTell") + ": ";
prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," "); prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," ");
CChatWindow::encodeColorTag(prop.getRGBA(), finalMsg, true); CChatWindow::encodeColorTag(prop.getRGBA(), finalMsg, true);
finalMsg += message; finalMsg += message;
@ -1238,6 +1269,14 @@ void CClientChatManager::updateChatModeAndButton(uint mode)
case CChatGroup::universe: pUserBut->setHardText("uiFilterUniverse"); break; case CChatGroup::universe: pUserBut->setHardText("uiFilterUniverse"); break;
case CChatGroup::team: if (teamActive) pUserBut->setHardText("uiFilterTeam"); break; case CChatGroup::team: if (teamActive) pUserBut->setHardText("uiFilterTeam"); break;
case CChatGroup::guild: if (guildActive) pUserBut->setHardText("uiFilterGuild"); break; case CChatGroup::guild: if (guildActive) pUserBut->setHardText("uiFilterGuild"); break;
case CChatGroup::dyn_chat:
uint32 index = PeopleInterraction.TheUserChat.Filter.getTargetDynamicChannelDbIndex();
uint32 textId = pIM->getDbProp("SERVER:DYN_CHAT:CHANNEL"+toString(index)+":NAME")->getValue32();
ucstring title;
STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId, title);
pUserBut->setHardText(title.toUtf8());
break;
// NB: user chat cannot have yubo_chat target
} }
pUserBut->setActive(true); pUserBut->setActive(true);
@ -1276,6 +1315,12 @@ class CHandlerTalk : public IActionHandler
text.fromUtf8 (getParam (sParams, "text")); text.fromUtf8 (getParam (sParams, "text"));
// text = getParam (sParams, "text"); // text = getParam (sParams, "text");
// Parse any tokens in the text
if ( ! CInterfaceManager::parseTokens(text))
{
return;
}
// Find the base group // Find the base group
if ((mode<CChatGroup::nbChatMode) && !text.empty()) if ((mode<CChatGroup::nbChatMode) && !text.empty())
{ {
@ -1292,7 +1337,7 @@ class CHandlerTalk : public IActionHandler
else else
{ {
CInterfaceManager *im = CInterfaceManager::getInstance(); CInterfaceManager *im = CInterfaceManager::getInstance();
im->displaySystemInfo (ucstring(cmd+" : ")+CI18N::get ("uiCommandNotExists")); im->displaySystemInfo (ucstring(cmd+": ")+CI18N::get ("uiCommandNotExists"));
} }
} }
else else

@ -125,7 +125,7 @@ extern CClientChatManager ChatMngr;
extern ULandscape *Landscape; extern ULandscape *Landscape;
extern UScene *Scene; extern UScene *Scene;
extern CLog g_log; extern CLog g_log;
extern CEntityManager EntitiesMngr;
/////////////// ///////////////
// Variables // // Variables //
@ -342,6 +342,317 @@ NLMISC_COMMAND(random, "Roll a dice and say the result around","[<min>] <max>")
return true; return true;
} }
//-----------------------------------------------
// 'dumpShapePos' : Dump Last Added Shape Pos
//-----------------------------------------------
NLMISC_COMMAND(dumpShapePos, "Dump Last Added Shape Pos.", "")
{
#if FINAL_VERSION
if (!hasPrivilegeDEV() &&
!hasPrivilegeSGM() &&
!hasPrivilegeGM() &&
!hasPrivilegeVG() &&
!hasPrivilegeSG() &&
!hasPrivilegeG() &&
!hasPrivilegeEM() &&
!hasPrivilegeEG())
return true;
#endif // FINAL_VERSION
if (ShapeAddedByCommand.empty())
{
nlwarning("No shape created yet");
return false;
}
CInterfaceManager *IM = CInterfaceManager::getInstance();
CVector pos = ShapeAddedByCommand.back().getPos();
IM->displaySystemInfo(ucstring(toString("Shape Pos = %f, %f, %f", pos.x, pos.y, pos.z)));
return true;
}
//-----------------------------------------------
// 'clearShape' : Remove all shapes added with the 'shape' command
//-----------------------------------------------
NLMISC_COMMAND(clearShape, "Remove all shapes added with the 'shape' command.", "")
{
#if FINAL_VERSION
if (!hasPrivilegeDEV() &&
!hasPrivilegeSGM() &&
!hasPrivilegeGM() &&
!hasPrivilegeVG() &&
!hasPrivilegeSG() &&
!hasPrivilegeG() &&
!hasPrivilegeEM() &&
!hasPrivilegeEG())
return true;
#endif // FINAL_VERSION
if (ShapeAddedByCommand.empty())
{
nlwarning("No shape created yet");
return false;
}
if (!Scene) return false;
for(uint k = 0; k < ShapeAddedByCommand.size(); ++k)
{
Scene->deleteInstance(ShapeAddedByCommand[k]);
}
ShapeAddedByCommand.clear();
return true;
}
//-----------------------------------------------------
// 'setShapeX' : Set X position for last created shape
//-----------------------------------------------------
NLMISC_COMMAND(setShapeX, "Set X position for last created shape.", "<x coordinate>")
{
#if FINAL_VERSION
if (!hasPrivilegeDEV() &&
!hasPrivilegeSGM() &&
!hasPrivilegeGM() &&
!hasPrivilegeVG() &&
!hasPrivilegeSG() &&
!hasPrivilegeG() &&
!hasPrivilegeEM() &&
!hasPrivilegeEG())
return true;
#endif // FINAL_VERSION
if (args.size() != 1) return false;
if (ShapeAddedByCommand.empty())
{
nlwarning("No shape created yet");
return false;
}
float coord;
bool valid_coord;
if (args[0][0] == '+')
valid_coord = fromString(args[0].substr(1), coord);
else
valid_coord = fromString(args[0], coord);
if (!valid_coord)
{
nlwarning("Can't get position");
return false;
}
CVector pos = ShapeAddedByCommand.back().getPos();
if (args[0][0] == '+')
pos.x += coord;
else
pos.x = coord;
ShapeAddedByCommand.back().setPos(pos);
return true;
}
//-----------------------------------------------------
// 'setShapeY' : Set Y position for last created shape
//-----------------------------------------------------
NLMISC_COMMAND(setShapeY, "Set Y position for last created shape.", "<y coordinate>")
{
#if FINAL_VERSION
if (!hasPrivilegeDEV() &&
!hasPrivilegeSGM() &&
!hasPrivilegeGM() &&
!hasPrivilegeVG() &&
!hasPrivilegeSG() &&
!hasPrivilegeG() &&
!hasPrivilegeEM() &&
!hasPrivilegeEG())
return true;
#endif // FINAL_VERSION
if (args.size() != 1) return false;
if (ShapeAddedByCommand.empty())
{
nlwarning("No shape created yet");
return false;
}
float coord;
bool valid_coord;
if (args[0][0] == '+')
valid_coord = fromString(args[0].substr(1), coord);
else
valid_coord = fromString(args[0], coord);
if (!valid_coord)
{
nlwarning("Can't get position");
return false;
}
CVector pos = ShapeAddedByCommand.back().getPos();
if (args[0][0] == '+')
pos.y += coord;
else
pos.y = coord;
ShapeAddedByCommand.back().setPos(pos);
return true;
}
//-----------------------------------------------------
// 'setShapeZ' : Set Z position for last created shape
//-----------------------------------------------------
NLMISC_COMMAND(setShapeZ, "Set Z position for last created shape.", "<z coordinate>")
{
#if FINAL_VERSION
if (!hasPrivilegeDEV() &&
!hasPrivilegeSGM() &&
!hasPrivilegeGM() &&
!hasPrivilegeVG() &&
!hasPrivilegeSG() &&
!hasPrivilegeG() &&
!hasPrivilegeEM() &&
!hasPrivilegeEG())
return true;
#endif // FINAL_VERSION
if (args.size() != 1) return false;
if (ShapeAddedByCommand.empty())
{
nlwarning("No shape created yet");
return false;
}
float coord;
bool valid_coord;
if (args[0][0] == '+')
valid_coord = fromString(args[0].substr(1), coord);
else
valid_coord = fromString(args[0], coord);
if (!valid_coord)
{
nlwarning("Can't get position");
return false;
}
CVector pos = ShapeAddedByCommand.back().getPos();
if (args[0][0] == '+')
pos.z += coord;
else
pos.z = coord;
ShapeAddedByCommand.back().setPos(pos);
return true;
}
//-----------------------------------------------------
// 'setShapeDir' : Set direction angle for last created shape
//-----------------------------------------------------
NLMISC_COMMAND(setShapeDir, "Set direction angle for last created shape.", "<angle>")
{
#if FINAL_VERSION
if (!hasPrivilegeDEV() &&
!hasPrivilegeSGM() &&
!hasPrivilegeGM() &&
!hasPrivilegeVG() &&
!hasPrivilegeSG() &&
!hasPrivilegeG() &&
!hasPrivilegeEM() &&
!hasPrivilegeEG())
return true;
#endif // FINAL_VERSION
if (args.size() != 1) return false;
if (ShapeAddedByCommand.empty())
{
nlwarning("No shape created yet");
return false;
}
float angle;
if (!fromString(args[0], angle))
{
nlwarning("Can't get angle");
return false;
}
CMatrix dir;
dir.identity();
CVector vangle = CVector(sin(angle), cos(angle), 0.f);
CVector vi = vangle^CVector(0.f, 0.f, 1.f);
CVector vk = vi^vangle;
dir.setRot(vi, vangle, vk, true);
// Set Orientation : User Direction should be normalized.
ShapeAddedByCommand.back().setRotQuat(dir.getRot());
return true;
}
//-----------------------------------------------
// 'shape' : Add a shape in the scene.
//-----------------------------------------------
NLMISC_COMMAND(shape, "Add a shape in the scene.", "<shape file>")
{
#if FINAL_VERSION
if (!hasPrivilegeDEV() &&
!hasPrivilegeSGM() &&
!hasPrivilegeGM() &&
!hasPrivilegeVG() &&
!hasPrivilegeSG() &&
!hasPrivilegeG() &&
!hasPrivilegeEM() &&
!hasPrivilegeEG())
return true;
#endif // FINAL_VERSION
if(args.size() < 1)
{
nlwarning("Command 'shape': need at least 1 parameter, try '/help shape' for more details.");
return false;
}
if (!Scene)
{
nlwarning("No scene available");
return false;
}
UInstance instance = Scene->createInstance(args[0]);
if(!instance.empty())
{
ShapeAddedByCommand.push_back(instance);
// Set the position
instance.setPos(UserEntity->pos());
instance.setClusterSystem(UserEntity->getClusterSystem()); // for simplicity, assume it is in the same
// cluster system than the user
// Compute the direction Matrix
CMatrix dir;
dir.identity();
CVector vi = UserEntity->dir()^CVector(0.f, 0.f, 1.f);
CVector vk = vi^UserEntity->dir();
dir.setRot(vi, UserEntity->dir(), vk, true);
// Set Orientation : User Direction should be normalized.
instance.setRotQuat(dir.getRot());
// if the shape is a particle system, additionnal parameters are user params
UParticleSystemInstance psi;
psi.cast (instance);
if (!psi.empty())
{
// set each user param that is present
for(uint k = 0; k < 4; ++k)
{
if (args.size() >= (k + 2))
{
float uparam;
if (fromString(args[k + 1], uparam))
{
psi.setUserParam(k, uparam);
}
else
{
nlwarning("Cant read param %d", k);
}
}
}
}
}
else
{
nlwarning("Command 'shape': cannot find the shape %s.", args[0].c_str());
}
// Command Well Done
return true;
}
NLMISC_COMMAND(bugReport, "Call the bug report tool with dump", "<AddScreenshot>") NLMISC_COMMAND(bugReport, "Call the bug report tool with dump", "<AddScreenshot>")
{ {
const char *brname[] = { "bug_report.exe", "bug_report_r.exe", "bug_report_rd.exe", "bug_report_df.exe", "bug_report_d.exe" }; const char *brname[] = { "bug_report.exe", "bug_report_r.exe", "bug_report_rd.exe", "bug_report_df.exe", "bug_report_d.exe" };
@ -908,6 +1219,10 @@ static bool talkInChan(uint32 nb,std::vector<std::string>args)
PeopleInterraction.talkInDynamicChannel(nb,ucstring(tmp)); PeopleInterraction.talkInDynamicChannel(nb,ucstring(tmp));
return true; return true;
} }
else
{
ChatMngr.updateChatModeAndButton(CChatGroup::dyn_chat);
}
return false; return false;
} }
@ -3467,156 +3782,6 @@ NLMISC_COMMAND(dist2side, "Change the distance to the side for a given sheet.",
//-----------------------------------------------
// 'clearShape' : Remove all shapes added with the 'shape' command
//-----------------------------------------------
NLMISC_COMMAND(clearShape, "Remove all shapes added with the 'shape' command.", "")
{
if (!Scene) return false;
for(uint k = 0; k < ShapeAddedByCommand.size(); ++k)
{
Scene->deleteInstance(ShapeAddedByCommand[k]);
}
ShapeAddedByCommand.clear();
return true;
}
//-----------------------------------------------------
// 'setShapeX' : Set X position for last created shape
//-----------------------------------------------------
NLMISC_COMMAND(setShapeX, "Set X position for last created shape.", "<x coordinate>")
{
if (args.size() != 1) return false;
if (ShapeAddedByCommand.empty())
{
nlwarning("No shape created yet");
return false;
}
float coord;
if (!fromString(args[0], coord))
{
nlwarning("Can't get position");
return false;
}
CVector pos = ShapeAddedByCommand.back().getPos();
pos.x = coord;
ShapeAddedByCommand.back().setPos(pos);
return true;
}
//-----------------------------------------------------
// 'setShapeY' : Set Y position for last created shape
//-----------------------------------------------------
NLMISC_COMMAND(setShapeY, "Set Y position for last created shape.", "<y coordinate>")
{
if (args.size() != 1) return false;
if (ShapeAddedByCommand.empty())
{
nlwarning("No shape created yet");
return false;
}
float coord;
if (!fromString(args[0], coord))
{
nlwarning("Can't get position");
return false;
}
CVector pos = ShapeAddedByCommand.back().getPos();
pos.y = coord;
ShapeAddedByCommand.back().setPos(pos);
return true;
}
//-----------------------------------------------------
// 'setShapeZ' : Set Z position for last created shape
//-----------------------------------------------------
NLMISC_COMMAND(setShapeZ, "Set Z position for last created shape.", "<z coordinate>")
{
if (args.size() != 1) return false;
if (ShapeAddedByCommand.empty())
{
nlwarning("No shape created yet");
return false;
}
float coord;
if (!fromString(args[0], coord))
{
nlwarning("Can't get position");
return false;
}
CVector pos = ShapeAddedByCommand.back().getPos();
pos.z = coord;
ShapeAddedByCommand.back().setPos(pos);
return true;
}
//-----------------------------------------------
// 'shape' : Add a shape in the scene.
//-----------------------------------------------
NLMISC_COMMAND(shape, "Add a shape in the scene.", "<shape file>")
{
if(args.size() < 1)
{
nlwarning("Command 'shape': need at least 1 parameter, try '/help shape' for more details.");
return false;
}
if (!Scene)
{
nlwarning("No scene available");
return false;
}
UInstance instance = Scene->createInstance(args[0]);
if(!instance.empty())
{
ShapeAddedByCommand.push_back(instance);
// Set the position
instance.setPos(UserEntity->pos());
instance.setClusterSystem(UserEntity->getClusterSystem()); // for simplicity, assume it is in the same
// cluster system than the user
// Compute the direction Matrix
CMatrix dir;
dir.identity();
CVector vi = UserEntity->dir()^CVector(0.f, 0.f, 1.f);
CVector vk = vi^UserEntity->dir();
dir.setRot(vi, UserEntity->dir(), vk, true);
// Set Orientation : User Direction should be normalized.
instance.setRotQuat(dir.getRot());
// if the shape is a particle system, additionnal parameters are user params
UParticleSystemInstance psi;
psi.cast (instance);
if (!psi.empty())
{
// set each user param that is present
for(uint k = 0; k < 4; ++k)
{
if (args.size() >= (k + 2))
{
float uparam;
if (fromString(args[k + 1], uparam))
{
psi.setUserParam(k, uparam);
}
else
{
nlwarning("Cant read param %d", k);
}
}
}
}
}
else
nlwarning("Command 'shape': cannot find the shape %s.", args[0].c_str());
// Command Well Done
return true;
}
// Change the parent of an entity. 'parent slot' not defined remove the current parent. // Change the parent of an entity. 'parent slot' not defined remove the current parent.
NLMISC_COMMAND(parent, "Change the parent of an entity.", "<slot> [<parent slot>]") NLMISC_COMMAND(parent, "Change the parent of an entity.", "<slot> [<parent slot>]")
{ {

@ -777,7 +777,7 @@ void contextExtractRM(bool rightClick, bool dblClick)
return; return;
if( ClientCfg.DblClickMode && !dblClick) if( ClientCfg.DblClickMode && !dblClick)
return; return;
UserEntity->moveToExtractionPhrase(SlotUnderCursor, MaxExtractionDistance, ~0, ~0, true ); UserEntity->moveToExtractionPhrase(SlotUnderCursor, MaxExtractionDistance, std::numeric_limits<uint>::max(), std::numeric_limits<uint>::max(), true );
} }
//----------------------------------------------- //-----------------------------------------------

@ -494,6 +494,90 @@ void CEntityManager::reinit()
initialize(_NbMaxEntity); initialize(_NbMaxEntity);
} }
CShapeInstanceReference CEntityManager::createInstance(const string& shape, const CVector &pos, const string& text, const string& url, bool bbox_active)
{
CShapeInstanceReference nullinstref(UInstance(), string(""), string(""));
if (!Scene) return nullinstref;
UInstance instance = Scene->createInstance(shape);
if (text.empty())
bbox_active = false;
CShapeInstanceReference instref = CShapeInstanceReference(instance, text, url, bbox_active);
if(!instance.empty())
{
_ShapeInstances.push_back(instref);
}
return instref;
}
bool CEntityManager::removeInstances()
{
if (!Scene) return false;
// Remove all instances.
for(uint i=0; i<_ShapeInstances.size(); ++i)
{
if (!_ShapeInstances[i].Instance.empty())
Scene->deleteInstance(_ShapeInstances[i].Instance);
}
_ShapeInstances.clear();
return true;
}
CShapeInstanceReference CEntityManager::getShapeInstanceUnderPos(float x, float y)
{
CShapeInstanceReference selectedInstance(UInstance(), string(""), string(""));
_LastInstanceUnderPos= NULL;
// If not initialised, return
if (_ShapeInstances.empty())
return selectedInstance;
// build the ray
CMatrix camMatrix = MainCam.getMatrix();
CFrustum camFrust = MainCam.getFrustum();
CViewport viewport = Driver->getViewport();
// Get the Ray made by the mouse.
CVector pos, dir;
viewport.getRayWithPoint(x, y, pos, dir, camMatrix, camFrust);
// Normalize the direction.
dir.normalize();
// **** Get instances with box intersecting the ray.
float bestDist = 255;
for(uint i=0; i<_ShapeInstances.size(); i++)
{
if (_ShapeInstances[i].BboxActive)
{
H_AUTO(RZ_Client_GEUP_box_intersect)
// if intersect the bbox
NLMISC::CAABBox bbox;
//= _ShapeInstances[i].SelectionBox;
_ShapeInstances[i].Instance.getShapeAABBox(bbox);
if (bbox.getCenter() == CVector::Null)
{
bbox.setMinMax(CVector(-0.3f, -0.3f, -0.3f)+_ShapeInstances[i].Instance.getPos(), CVector(0.3f, 0.3f, 0.3f)+_ShapeInstances[i].Instance.getPos());
}
else
{
bbox.setMinMax((bbox.getMin()*_ShapeInstances[i].Instance.getScale().x)+_ShapeInstances[i].Instance.getPos(), (bbox.getMax()*_ShapeInstances[i].Instance.getScale().x)+_ShapeInstances[i].Instance.getPos());
}
if(bbox.intersect(pos, pos+dir*15.0f))
{
float dist = (bbox.getCenter()-pos).norm();
if (dist < bestDist)
{
selectedInstance = _ShapeInstances[i];
bestDist = dist;
}
}
}
}
return selectedInstance;
}
//----------------------------------------------- //-----------------------------------------------
// Create an entity according to the slot and the form. // Create an entity according to the slot and the form.
// \param uint slot : slot for the entity. // \param uint slot : slot for the entity.

@ -85,8 +85,28 @@ public:
uint Slot; uint Slot;
}; };
/*
* Class to make cache shape instances
*/
class CShapeInstanceReference
{
public:
CShapeInstanceReference (NL3D::UInstance instance, const string &text, const string &url, bool bbox_active=true)
{
Instance = instance;
ContextText = text;
ContextURL = url;
BboxActive = bbox_active;
}
NL3D::UInstance Instance;
string ContextText;
string ContextURL;
bool BboxActive;
};
/** /**
* Class to manage entities. * Class to manage entities and shapes instances.
* \author Guillaume PUZIN * \author Guillaume PUZIN
* \author Nevrax France * \author Nevrax France
* \date 2001 * \date 2001
@ -106,6 +126,9 @@ private:
std::vector<CEntityReference> _ActiveEntities; std::vector<CEntityReference> _ActiveEntities;
std::vector<CEntityReference> _VisibleEntities; std::vector<CEntityReference> _VisibleEntities;
/// Shapes Instances caches
std::vector<CShapeInstanceReference> _ShapeInstances;
typedef struct typedef struct
{ {
NLMISC::TGameCycle GC; NLMISC::TGameCycle GC;
@ -123,6 +146,8 @@ private:
// For selection. NB: the pointer is just a cache. Must not be accessed // For selection. NB: the pointer is just a cache. Must not be accessed
CEntityCL *_LastEntityUnderPos; CEntityCL *_LastEntityUnderPos;
NL3D::UInstance _LastInstanceUnderPos;
////////////// //////////////
//// DEBUG /// //// DEBUG ///
uint _NbUser; uint _NbUser;
@ -174,6 +199,11 @@ public:
/// Release + initialize /// Release + initialize
void reinit(); void reinit();
CShapeInstanceReference createInstance(const string& shape, const CVector &pos, const string &text, const string &url, bool active=true);
bool removeInstances();
CShapeInstanceReference getShapeInstanceUnderPos(float x, float y);
/** /**
* Create an entity according to the slot and the form. * Create an entity according to the slot and the form.
* \param uint slot : slot for the entity. * \param uint slot : slot for the entity.

@ -2511,12 +2511,20 @@ NLMISC::CRGBA CEntityCL::getColor () const
{ {
if (isEnemy()) if (isEnemy())
{ {
return _PvpEnemyColor; if (getPvpMode()&PVP_MODE::PvpFactionFlagged || getPvpMode()&PVP_MODE::PvpChallenge)
return _PvpEnemyColor;
else
return CRGBA::CRGBA(min(255, _PvpEnemyColor.R+150), min(255, _PvpEnemyColor.G+150), min(255, _PvpEnemyColor.B+150),_PvpEnemyColor.A);
} }
} }
// neutral pvp // neutral pvp
if (isNeutralPVP()) if (isNeutralPVP())
{ {
if (isInTeam())
return _PvpAllyInTeamColor;
if (isInGuild())
return _PvpAllyInGuildColor;
return _PvpNeutralColor; return _PvpNeutralColor;
} }
// ally // ally
@ -2526,7 +2534,11 @@ NLMISC::CRGBA CEntityCL::getColor () const
return _PvpAllyInTeamColor; return _PvpAllyInTeamColor;
if(isInGuild()) if(isInGuild())
return _PvpAllyInGuildColor; return _PvpAllyInGuildColor;
return _PvpAllyColor;
if (getPvpMode()&PVP_MODE::PvpFactionFlagged)
return _PvpAllyColor;
else
return CRGBA::CRGBA(min(255, _PvpAllyColor.R+150), min(255, _PvpAllyColor.G+150), min(255, _PvpAllyColor.B+150),_PvpAllyColor.A);
} }
// neutral // neutral
if (isInTeam()) if (isInTeam())
@ -2795,9 +2807,11 @@ void CEntityCL::updateIsInTeam ()
presentProp && presentProp->getValueBool() ) presentProp && presentProp->getValueBool() )
{ {
_IsInTeam= true; _IsInTeam= true;
buildInSceneInterface();
return; return;
} }
} }
buildInSceneInterface();
} }
//----------------------------------------------- //-----------------------------------------------
@ -3051,13 +3065,15 @@ void CEntityCL::updateVisiblePostPos(const NLMISC::TTime &/* currentTimeInMs */,
position = pos().asVector(); position = pos().asVector();
position.z= _SelectBox.getMin().z; position.z= _SelectBox.getMin().z;
mat.setPos(position); mat.setPos(position);
mat.setRot(dirMatrix());
_StateFX.setTransformMode(NL3D::UTransformable::DirectMatrix); _StateFX.setTransformMode(NL3D::UTransformable::DirectMatrix);
_StateFX.setMatrix(mat); _StateFX.setMatrix(mat);
if (skeleton()) if (skeleton())
_StateFX.setClusterSystem(skeleton()->getClusterSystem()); _StateFX.setClusterSystem(skeleton()->getClusterSystem());
} }
else if (!_SelectionFX.empty() || !_MouseOverFX.empty())
if (!_SelectionFX.empty() || !_MouseOverFX.empty())
{ {
// Build a matrix for the fx // Build a matrix for the fx
NLMISC::CMatrix mat; NLMISC::CMatrix mat;

@ -686,7 +686,7 @@ public:
virtual bool isNeutralPVP() const { return false; } virtual bool isNeutralPVP() const { return false; }
/// Return true if this player has the viewing properties of a friend (inscene bars...) /// Return true if this player has the viewing properties of a friend (inscene bars...)
virtual bool isViewedAsFriend() const { return isNeutral() || isFriend(); } virtual bool isViewedAsFriend() const { return isNeutral() || isFriend() || isInTeam() || isInGuild(); }
/// Return the People for the entity (unknown by default) /// Return the People for the entity (unknown by default)
virtual EGSPD::CPeople::TPeople people() const; virtual EGSPD::CPeople::TPeople people() const;
@ -760,6 +760,12 @@ public:
return _Title; return _Title;
} }
/// Return the raw unparsed entity title
const ucstring getTitleRaw() const
{
return ucstring(_TitleRaw);
}
/// Return true if this entity has a reserved title /// Return true if this entity has a reserved title
bool hasReservedTitle() const { return _HasReservedTitle; } bool hasReservedTitle() const { return _HasReservedTitle; }

@ -1364,6 +1364,10 @@ void loadBackgroundBitmap (TBackground background)
string ext = CFile::getExtension (ClientCfg.Launch_BG); string ext = CFile::getExtension (ClientCfg.Launch_BG);
string filename; string filename;
if (frand(2.0) < 1)
filename = name+"_0."+ext;
else
filename = name+"_1."+ext;
switch (background) switch (background)
{ {
case ElevatorBackground: case ElevatorBackground:
@ -1397,13 +1401,6 @@ void loadBackgroundBitmap (TBackground background)
filename = ClientCfg.Loading_BG; filename = ClientCfg.Loading_BG;
break; break;
default: default:
/*
if (frand(2.0) < 1)
filename = name+"_0."+ext;
else
filename = name+"_1."+ext;
*/
filename = name+"."+ext;
break; break;
} }

@ -2440,6 +2440,174 @@ class CAHTarget : public IActionHandler
}; };
REGISTER_ACTION_HANDLER (CAHTarget, "target"); REGISTER_ACTION_HANDLER (CAHTarget, "target");
class CAHAddShape : public IActionHandler
{
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
{
string sShape = getParam(Params, "shape");
if(sShape.empty())
{
nlwarning("Command 'add_shape': need at least the parameter shape.");
return;
}
if (!Scene)
{
nlwarning("No scene available");
return;
}
double x = UserEntity->pos().x;
double y = UserEntity->pos().y;
double z = UserEntity->pos().z;
CVector userDir = UserEntity->dir();
float s = 1.0f;
string skeleton = getParam(Params, "skeleton");
string c = getParam(Params, "text");
string u = getParam(Params, "url");
string texture_name = getParam(Params, "texture");
string highlight = getParam(Params, "texture");
string transparency = getParam(Params, "transparency");
if (!getParam(Params, "x").empty())
fromString(getParam(Params, "x"), x);
if (!getParam(Params, "y").empty())
fromString(getParam(Params, "y"), y);
if (!getParam(Params, "z").empty())
fromString(getParam(Params, "z"), z);
if (!getParam(Params, "scale").empty())
fromString(getParam(Params, "scale"), s);
if (!getParam(Params, "angle").empty())
{
float a;
fromString(getParam(Params, "angle"), a);
userDir = CVector(sin(a), cos(a), 0.f);
}
bool have_shapes = true;
bool first_shape = true;
while(have_shapes)
{
string shape;
string::size_type index = sShape.find(string(" "));
// multiple shapes/fx
if (index != string::npos)
{
shape = sShape.substr(0, index);
sShape = sShape.substr(index+1);
} else {
shape = sShape;
have_shapes = false;
}
CShapeInstanceReference instref = EntitiesMngr.createInstance(shape, CVector((float)x, (float)y, (float)z), c, u, first_shape);
UInstance instance = instref.Instance;
if(!instance.empty())
{
for(uint j=0;j<instance.getNumMaterials();j++)
{
if (highlight.empty())
{
instance.getMaterial(j).setAmbient(CRGBA(0,0,0,255));
instance.getMaterial(j).setShininess( 10.0f );
instance.getMaterial(j).setEmissive(CRGBA(255,255,255,255));
}
else
{
instance.getMaterial(j).setAmbient(CRGBA(0,0,0,255));
instance.getMaterial(j).setEmissive(CRGBA(255,0,0,255));
instance.getMaterial(j).setShininess( 1000.0f );
}
if (!texture_name.empty() && first_shape)
{
sint numStages = instance.getMaterial(j).getLastTextureStage() + 1;
for(sint l = 0; l < numStages; l++)
{
if (instance.getMaterial(j).isTextureFile((uint) l))
{
instance.getMaterial(j).setTextureFileName(texture_name, (uint) l);
}
}
}
}
first_shape = false;
if (transparency.empty())
::makeInstanceTransparent(instance, 255, false);
else
::makeInstanceTransparent(instance, 100, true);
instance.setClusterSystem(UserEntity->getClusterSystem()); // for simplicity, assume it is in the same
// cluster system than the user
// Compute the direction Matrix
CMatrix dir;
dir.identity();
CVector vi = userDir^CVector(0.f, 0.f, 1.f);
CVector vk = vi^userDir;
dir.setRot(vi, userDir, vk, true);
// Set Orientation : User Direction should be normalized.
if (!skeleton.empty())
{
USkeleton skel = Scene->createSkeleton(skeleton);
if (!skel.empty())
{
skel.bindSkin(instance);
skel.setClusterSystem(UserEntity->getClusterSystem());
skel.setScale(skel.getScale()*s);
skel.setPos(CVector((float)x, (float)y, (float)z));
skel.setRotQuat(dir.getRot());
}
} else {
instance.setScale(instance.getScale()*s);
instance.setPos(CVector((float)x, (float)y, (float)z));
instance.setRotQuat(dir.getRot());
}
// if the shape is a particle system, additionnal parameters are user params
UParticleSystemInstance psi;
psi.cast (instance);
/*if (!psi.empty())
{
// set each user param that is present
for(uint k = 0; k < 4; ++k)
{
if (args.size() >= (k + 2))
{
float uparam;
if (fromString(args[k + 1], uparam))
{
psi.setUserParam(k, uparam);
}
else
{
nlwarning("Cant read param %d", k);
}
}
}
}*/
}
else
nlwarning("Command 'add_shape': cannot find the shape %s.", sShape.c_str());
}
return;
}
};
REGISTER_ACTION_HANDLER (CAHAddShape, "add_shape");
class CAHRemoveShapes : public IActionHandler
{
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
{
EntitiesMngr.removeInstances();
}
};
REGISTER_ACTION_HANDLER (CAHRemoveShapes, "remove_shapes");
// *************************************************************************** // ***************************************************************************
// See also CHandlerTeamTarget // See also CHandlerTeamTarget
class CAHTargetTeammateShortcut : public IActionHandler class CAHTargetTeammateShortcut : public IActionHandler

@ -104,7 +104,9 @@ static void setupMissionHelp(CSheetHelpSetup &setup);
#define INFO_LIST_BRICK_REQUIREMENT "list_brick_requirement" #define INFO_LIST_BRICK_REQUIREMENT "list_brick_requirement"
#define INFO_GROUP_MP_STAT "mp_stats" #define INFO_GROUP_MP_STAT "mp_stats"
#define INFO_GROUP_CHAR_3D "char3d" #define INFO_GROUP_CHAR_3D "char3d"
#define INFO_ITEM_PREVIEW "item_preview"
#define INFO_ITEM_PREVIEW_SCENE_3D "scene_item_preview"
#define ITEM_PREVIEW_WIDTH 200
// *************************************************************************** // ***************************************************************************
std::deque<uint> CInterfaceHelp::_ActiveWindows; std::deque<uint> CInterfaceHelp::_ActiveWindows;
@ -2178,6 +2180,14 @@ void resetSheetHelp(CSheetHelpSetup &setup)
{ {
listItem->setActive(false); listItem->setActive(false);
} }
// Hide the item preview by default
CInterfaceElement *elt= group->getElement(group->getId()+setup.PrefixForExtra+INFO_ITEM_PREVIEW);
if(elt)
{
elt->setActive(false);
}
// Hide the list of brick by default // Hide the list of brick by default
IListSheetBase *listBrick= dynamic_cast<IListSheetBase*>(group->getElement(group->getId()+setup.PrefixForExtra+INFO_LIST_BRICK)); IListSheetBase *listBrick= dynamic_cast<IListSheetBase*>(group->getElement(group->getId()+setup.PrefixForExtra+INFO_LIST_BRICK));
if(listBrick) if(listBrick)
@ -2268,6 +2278,151 @@ void setupCosmetic(CSheetHelpSetup &setup, CItemSheet *pIS)
} }
} }
// ***************************************************************************
void setupItemPreview(CSheetHelpSetup &setup, CItemSheet *pIS)
{
nlassert(pIS);
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CCDBNodeBranch *dbBranch = pIM->getDbBranch( setup.SrcSheet->getSheet() );
CInterfaceElement *elt = setup.HelpWindow->getElement(setup.HelpWindow->getId()+setup.PrefixForExtra+INFO_ITEM_PREVIEW);
if (elt == NULL)
return;
CInterfaceGroup *ig = dynamic_cast<CInterfaceGroup*>(elt);
if ( ! ig)
{
return;
}
static sint32 helpWidth = setup.HelpWindow->getW();
bool scene_inactive = ! pIM->getDbProp("UI:SAVE:SHOW_3D_ITEM_PREVIEW")->getValueBool();
if (scene_inactive ||
(pIS->Family != ITEMFAMILY::ARMOR &&
pIS->Family != ITEMFAMILY::MELEE_WEAPON &&
pIS->Family != ITEMFAMILY::RANGE_WEAPON &&
pIS->Family != ITEMFAMILY::SHIELD))
{
setup.HelpWindow->setW(helpWidth);
ig->setActive(false);
return;
}
else
{
setup.HelpWindow->setW(helpWidth + ITEM_PREVIEW_WIDTH);
ig->setActive(true);
}
CInterface3DScene *sceneI = dynamic_cast<CInterface3DScene *>(ig->getGroup("scene_item_preview"));
if (!sceneI)
{
nlwarning("Can't retrieve character 3d view, or bad type");
ig->setActive(false);
return;
}
CInterface3DCharacter *char3DI = NULL;
if (sceneI->getCharacter3DCount() != 0)
char3DI = sceneI->getCharacter3D(0);
if (char3DI == NULL)
{
nlwarning("Can't retrieve char 3D Interface");
ig->setActive(false);
return;
}
CInterface3DCamera *camera = sceneI->getCamera(0);
if (camera == NULL)
{
nlwarning("Can't retrieve camera");
ig->setActive(false);
return;
}
SCharacter3DSetup c3Ds;
CCharacterSummary cs;
SCharacter3DSetup::setupCharacterSummaryFromSERVERDB( cs );
float camHeight = -0.85f;
if (pIS->Family == ITEMFAMILY::ARMOR)
{
if (pIS->ItemType == ITEM_TYPE::LIGHT_BOOTS || pIS->ItemType == ITEM_TYPE::MEDIUM_BOOTS || pIS->ItemType == ITEM_TYPE::HEAVY_BOOTS)
{
CCDBNodeLeaf *color = dbBranch->getLeaf( setup.SrcSheet->getSheet()+":USER_COLOR", false );
cs.VisualPropB.PropertySubData.FeetModel = CVisualSlotManager::getInstance()->sheet2Index( CSheetId(setup.SrcSheet->getSheetId()), SLOTTYPE::FEET_SLOT );
cs.VisualPropB.PropertySubData.FeetColor = color->getValue32();
SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", cs);
camHeight = -1.15f;
}
else if (pIS->ItemType == ITEM_TYPE::LIGHT_GLOVES || pIS->ItemType == ITEM_TYPE::MEDIUM_GLOVES || pIS->ItemType == ITEM_TYPE::HEAVY_GLOVES)
{
CCDBNodeLeaf *color = dbBranch->getLeaf( setup.SrcSheet->getSheet()+":USER_COLOR", false );
cs.VisualPropB.PropertySubData.HandsModel = CVisualSlotManager::getInstance()->sheet2Index( CSheetId(setup.SrcSheet->getSheetId()), SLOTTYPE::HANDS_SLOT );
cs.VisualPropB.PropertySubData.HandsColor = color->getValue32();
SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", cs);
//cs.VisualPropB.PropertySubData.HandsColor = pIS->Color;
}
else if (pIS->ItemType == ITEM_TYPE::LIGHT_SLEEVES || pIS->ItemType == ITEM_TYPE::MEDIUM_SLEEVES || pIS->ItemType == ITEM_TYPE::HEAVY_SLEEVES)
{
CCDBNodeLeaf *color = dbBranch->getLeaf( setup.SrcSheet->getSheet()+":USER_COLOR", false );
cs.VisualPropA.PropertySubData.ArmModel = CVisualSlotManager::getInstance()->sheet2Index( CSheetId(setup.SrcSheet->getSheetId()), SLOTTYPE::ARMS_SLOT );
SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", cs);
SCharacter3DSetup::setDB("UI:TEMP:CHAR3D:VPA:ARMCOLOR", pIS->Color);
//cs.VisualPropA.PropertySubData.ArmColor = pIS->Color;
camHeight = -0.55f;
}
else if (pIS->ItemType == ITEM_TYPE::LIGHT_PANTS || pIS->ItemType == ITEM_TYPE::MEDIUM_PANTS || pIS->ItemType == ITEM_TYPE::HEAVY_PANTS)
{
CCDBNodeLeaf *color = dbBranch->getLeaf( setup.SrcSheet->getSheet()+":USER_COLOR", false );
cs.VisualPropA.PropertySubData.TrouserModel = CVisualSlotManager::getInstance()->sheet2Index( CSheetId(setup.SrcSheet->getSheetId()), SLOTTYPE::LEGS_SLOT );
cs.VisualPropA.PropertySubData.TrouserColor = color->getValue32();
SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", cs);
camHeight = -1.00f;
}
else if (pIS->ItemType == ITEM_TYPE::LIGHT_VEST || pIS->ItemType == ITEM_TYPE::MEDIUM_VEST || pIS->ItemType == ITEM_TYPE::HEAVY_VEST)
{
CCDBNodeLeaf *color = dbBranch->getLeaf( setup.SrcSheet->getSheet()+":USER_COLOR", false );
cs.VisualPropA.PropertySubData.JacketModel = CVisualSlotManager::getInstance()->sheet2Index( CSheetId(setup.SrcSheet->getSheetId()), SLOTTYPE::CHEST_SLOT );
cs.VisualPropA.PropertySubData.JacketColor = color->getValue32();
SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", cs);
camHeight = -0.55f;
}
else if (pIS->ItemType == ITEM_TYPE::HEAVY_HELMET)
{
CCDBNodeLeaf *color = dbBranch->getLeaf( setup.SrcSheet->getSheet()+":USER_COLOR", false );
cs.VisualPropA.PropertySubData.HatModel = CVisualSlotManager::getInstance()->sheet2Index( CSheetId(setup.SrcSheet->getSheetId()), SLOTTYPE::HEAD_SLOT );
cs.VisualPropA.PropertySubData.HatColor = color->getValue32();
SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", cs);
camHeight = -0.35f;
}
}
else if (pIS->Family == ITEMFAMILY::SHIELD)
{
cs.VisualPropA.PropertySubData.WeaponLeftHand = CVisualSlotManager::getInstance()->sheet2Index( CSheetId(setup.SrcSheet->getSheetId()), SLOTTYPE::LEFT_HAND_SLOT );
SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", cs);
}
else if (pIS->Family == ITEMFAMILY::MELEE_WEAPON || pIS->Family == ITEMFAMILY::RANGE_WEAPON)
{
cs.VisualPropA.PropertySubData.WeaponRightHand = CVisualSlotManager::getInstance()->sheet2Index( CSheetId(setup.SrcSheet->getSheetId()), SLOTTYPE::RIGHT_HAND_SLOT );
SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", cs);
}
else
nlwarning("<setupItemPreview> Invalid armour or weapon item type '%s'", ITEM_TYPE::toString( pIS->ItemType ).c_str() );
if (camera == NULL)
return;
camera->setTgtZ(camHeight);
char3DI->setAnim(CAnimationStateSheet::Idle);
}
// *************************************************************************** // ***************************************************************************
void refreshItemHelp(CSheetHelpSetup &setup) void refreshItemHelp(CSheetHelpSetup &setup)
{ {
@ -2291,6 +2446,9 @@ void refreshItemHelp(CSheetHelpSetup &setup)
// ---- Cosmetic only // ---- Cosmetic only
setupCosmetic (setup, pIS); setupCosmetic (setup, pIS);
// ---- item preview
setupItemPreview(setup, pIS);
} }
// if this is a R2 plot item, Add comment and description // if this is a R2 plot item, Add comment and description

@ -312,8 +312,7 @@ void CChatTargetFilter::msgEntered(const ucstring &msg, CChatWindow *chatWindow)
else if (!_TargetPlayer.empty()) else if (!_TargetPlayer.empty())
{ {
// the target must be a player, make a tell on him // the target must be a player, make a tell on him
// TODO: adapt this to unicode when this is OK on server side ChatMngr.tell(_TargetPlayer.toString(), msg);
ChatMngr.tell(_TargetPlayer.toString(), msg.toString());
// direct output in the chat // direct output in the chat
chatWindow->displayLocalPlayerTell(msg); chatWindow->displayLocalPlayerTell(msg);
} }

@ -472,7 +472,13 @@ void CChatWindow::displayLocalPlayerTell(const ucstring &msg, uint numBlinks /*=
CInterfaceProperty prop; CInterfaceProperty prop;
prop.readRGBA("UI:SAVE:CHAT:COLORS:SPEAKER"," "); prop.readRGBA("UI:SAVE:CHAT:COLORS:SPEAKER"," ");
encodeColorTag(prop.getRGBA(), finalMsg, false); encodeColorTag(prop.getRGBA(), finalMsg, false);
finalMsg += CI18N::get("youTell") + ": "; ucstring cur_time;
if (CInterfaceManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_TIMES_IN_CHAT_CB", false)->getValueBool())
{
cur_time = CInterfaceManager::getTimestampHuman();
}
ucstring csr = CHARACTER_TITLE::isCsrTitle(UserEntity->getTitleRaw()) ? "(CSR) " : "";
finalMsg += cur_time + csr + CI18N::get("youTell") + ": ";
prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," "); prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," ");
encodeColorTag(prop.getRGBA(), finalMsg, true); encodeColorTag(prop.getRGBA(), finalMsg, true);
finalMsg += msg; finalMsg += msg;
@ -1241,6 +1247,13 @@ public:
return; return;
} }
// Parse any tokens in the text
if ( ! CInterfaceManager::parseTokens(text))
{
pEB->setInputString (string(""));
return;
}
// if, it s a command, execute it and don't send the command to the server // if, it s a command, execute it and don't send the command to the server
if(text[0] == '/') if(text[0] == '/')
{ {
@ -1256,7 +1269,7 @@ public:
else else
{ {
CInterfaceManager *im = CInterfaceManager::getInstance(); CInterfaceManager *im = CInterfaceManager::getInstance();
im->displaySystemInfo (ucstring(cmd+" : ")+CI18N::get ("uiCommandNotExists")); im->displaySystemInfo (ucstring(cmd+": ")+CI18N::get ("uiCommandNotExists"));
} }
} }
else else

@ -45,6 +45,10 @@ extern "C"
#include "lua_ihm.h" #include "lua_ihm.h"
#include "../time_client.h" #include "../time_client.h"
#include "nel/misc/i18n.h"
#include "nel/misc/md5.h"
#include "nel/3d/texture_file.h"
#include "nel/misc/big_file.h"
using namespace std; using namespace std;
using namespace NLMISC; using namespace NLMISC;
@ -107,15 +111,106 @@ void CGroupHTML::addImageDownload(const string &url, CViewBase *img)
curl_easy_setopt(curl, CURLOPT_FILE, fp); curl_easy_setopt(curl, CURLOPT_FILE, fp);
curl_multi_add_handle(MultiCurl, curl); curl_multi_add_handle(MultiCurl, curl);
Curls.push_back(CImageDownload(curl, url, fp, img)); Curls.push_back(CDataDownload(curl, url, fp, ImgType, img));
#ifdef LOG_DL #ifdef LOG_DL
nlwarning("adding handle %x, %d curls", curl, Curls.size()); nlwarning("adding handle %x, %d curls", curl, Curls.size());
#endif #endif
RunningCurls++; RunningCurls++;
} }
// Call this evenly to check if an image in downloaded and then display it void CGroupHTML::initImageDownload()
void CGroupHTML::checkImageDownload() {
#ifdef LOG_DL
nlwarning("Init Image Download");
#endif
/*
// Get current flag
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
// Turn on leak-checking bit
tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF;
// Set flag to the new value
_CrtSetDbgFlag( tmpFlag );
*/
string pathName = "cache";
if ( ! CFile::isExists( pathName ) )
CFile::createDirectory( pathName );
}
// Get an url and return the local filename with the path where the bnp should be
string CGroupHTML::localBnpName(const string &url)
{
size_t lastIndex = url.find_last_of("/");
string dest = "user/"+url.substr(lastIndex+1);
return dest;
}
// Add a bnp download request in the multi_curl
void CGroupHTML::addBnpDownload(const string &url, const string &action)
{
// Search if we are not already downloading this url.
for(uint i = 0; i < Curls.size(); i++)
{
if(Curls[i].url == url)
{
#ifdef LOG_DL
nlwarning("already downloading '%s'", url.c_str());
#endif
return;
}
}
CURL *curl = curl_easy_init();
if (!MultiCurl || !curl)
return;
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, true);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
string dest = localBnpName(url);
#ifdef LOG_DL
nlwarning("add to download '%s' dest '%s'", url.c_str(), dest.c_str());
#endif
// create the local file
if (NLMISC::CFile::fileExists(dest))
{
if (action == "override" || action == "delete")
{
CFile::setRWAccess(dest);
NLMISC::CFile::deleteFile(dest.c_str());
}
}
if (action != "delete")
{
FILE *fp = fopen (dest.c_str(), "wb");
if (fp == NULL)
{
nlwarning("Can't open file '%s' for writing: code=%d '%s'", dest.c_str (), errno, strerror(errno));
return;
}
curl_easy_setopt(curl, CURLOPT_FILE, fp);
curl_multi_add_handle(MultiCurl, curl);
Curls.push_back(CDataDownload(curl, url, fp, BnpType, NULL));
#ifdef LOG_DL
nlwarning("adding handle %x, %d curls", curl, Curls.size());
#endif
RunningCurls++;
}
}
void CGroupHTML::initBnpDownload()
{
#ifdef LOG_DL
nlwarning("Init Bnp Download");
#endif
string pathName = "user";
if ( ! CFile::isExists( pathName ) )
CFile::createDirectory( pathName );
}
// Call this evenly to check if an element is downloaded and then manage it
void CGroupHTML::checkDownloads()
{ {
//nlassert(_CrtCheckMemory()); //nlassert(_CrtCheckMemory());
@ -142,7 +237,7 @@ void CGroupHTML::checkImageDownload()
{ {
if (msg->msg == CURLMSG_DONE) if (msg->msg == CURLMSG_DONE)
{ {
for (vector<CImageDownload>::iterator it=Curls.begin(); it<Curls.end(); it++) for (vector<CDataDownload>::iterator it=Curls.begin(); it<Curls.end(); it++)
{ {
if(msg->easy_handle == it->curl) if(msg->easy_handle == it->curl)
{ {
@ -156,58 +251,87 @@ void CGroupHTML::checkImageDownload()
#endif #endif
curl_easy_cleanup(it->curl); curl_easy_cleanup(it->curl);
string image = localImageName(it->url); string file;
if(CURLE_OK != res || r < 200 || r >= 300) if (it->type == ImgType)
file = localImageName(it->url)+".tmp";
else
file = localBnpName(it->url);
if(res != CURLE_OK || r < 200 || r >= 300)
{ {
NLMISC::CFile::deleteFile((image+".tmp").c_str()); NLMISC::CFile::deleteFile(file.c_str());
} }
else else
{ {
string finalUrl; string finalUrl;
CFile::moveFile(image.c_str(), (image+".tmp").c_str()); if (it->type == ImgType)
if (lookupLocalFile (finalUrl, image.c_str(), false))
{ {
for(uint i = 0; i < it->imgs.size(); i++) string image = localImageName(it->url);
CFile::moveFile(image.c_str(), (image+".tmp").c_str());
if (lookupLocalFile (finalUrl, image.c_str(), false))
{ {
// don't display image that are not power of 2 for(uint i = 0; i < it->imgs.size(); i++)
uint32 w, h;
CBitmap::loadSize (image, w, h);
if (w == 0 || h == 0 || ((!NLMISC::isPowerOf2(w) || !NLMISC::isPowerOf2(h)) && !NL3D::CTextureFile::supportNonPowerOfTwoTextures()))
image.clear();
CCtrlButton *btn = dynamic_cast<CCtrlButton*>(it->imgs[i]);
if(btn)
{ {
#ifdef LOG_DL // don't display image that are not power of 2
nlwarning("refresh new downloading image %d button %p", i, it->imgs[i]); uint32 w, h;
#endif CBitmap::loadSize (image, w, h);
btn->setTexture (image); if (w == 0 || h == 0 || ((!NLMISC::isPowerOf2(w) || !NLMISC::isPowerOf2(h)) && !NL3D::CTextureFile::supportNonPowerOfTwoTextures()))
btn->setTexturePushed(image); image.clear();
btn->invalidateCoords();
btn->invalidateContent(); CCtrlButton *btn = dynamic_cast<CCtrlButton*>(it->imgs[i]);
btn->resetInvalidCoords(); if(btn)
btn->updateCoords();
paragraphChange();
}
else
{
CViewBitmap *btm = dynamic_cast<CViewBitmap*>(it->imgs[i]);
if(btm)
{ {
#ifdef LOG_DL #ifdef LOG_DL
nlwarning("refresh new downloading image %d image %p", i, it->imgs[i]); nlwarning("refresh new downloading image %d button %p", i, it->imgs[i]);
#endif #endif
btm->setTexture (image); btn->setTexture (image);
btm->invalidateCoords(); btn->setTexturePushed(image);
btm->invalidateContent(); btn->invalidateCoords();
btm->resetInvalidCoords(); btn->invalidateContent();
btm->updateCoords(); btn->resetInvalidCoords();
btn->updateCoords();
paragraphChange(); paragraphChange();
} }
else
{
CViewBitmap *btm = dynamic_cast<CViewBitmap*>(it->imgs[i]);
if(btm)
{
#ifdef LOG_DL
nlwarning("refresh new downloading image %d image %p", i, it->imgs[i]);
#endif
btm->setTexture (image);
btm->invalidateCoords();
btm->invalidateContent();
btm->resetInvalidCoords();
btm->updateCoords();
paragraphChange();
}
}
} }
} }
} }
else
{
if (lookupLocalFile (finalUrl, file.c_str(), false))
{
nlinfo("BNPCHECK : downloaded");
bool memoryCompressed = CPath::isMemoryCompressed();
if (memoryCompressed)
{
CPath::memoryUncompress();
}
CPath::addSearchPath("user/", true, false, NULL);
if (memoryCompressed)
{
CPath::memoryCompress();
}
CInterfaceManager *pIM = CInterfaceManager::getInstance();
pIM->executeLuaScript("game:onBnpDownloadFinish()", true);
}
}
} }
Curls.erase(it); Curls.erase(it);
@ -220,32 +344,11 @@ void CGroupHTML::checkImageDownload()
RunningCurls = NewRunningCurls; RunningCurls = NewRunningCurls;
} }
void CGroupHTML::initImageDownload()
{
#ifdef LOG_DL
nlwarning("Init Image Download");
#endif
MultiCurl = curl_multi_init();
RunningCurls = 0;
/*
// Get current flag
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
// Turn on leak-checking bit
tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF;
// Set flag to the new value
_CrtSetDbgFlag( tmpFlag );
*/
string pathName = "cache"; void CGroupHTML::releaseDownloads()
if ( ! CFile::isExists( pathName ) )
CFile::createDirectory( pathName );
}
void CGroupHTML::releaseImageDownload()
{ {
#ifdef LOG_DL #ifdef LOG_DL
nlwarning("Release Image Download"); nlwarning("Release Downloads");
#endif #endif
if(MultiCurl) if(MultiCurl)
curl_multi_cleanup(MultiCurl); curl_multi_cleanup(MultiCurl);
@ -1251,6 +1354,21 @@ void CGroupHTML::beginElement (uint element_number, const BOOL *present, const c
endParagraph(); endParagraph();
_UL.push_back(true); _UL.push_back(true);
break; break;
case HTML_OBJECT:
_ObjectType = "";
_ObjectData = "";
_ObjectMD5Sum = "";
_ObjectAction = "";
if (present[HTML_OBJECT_TYPE] && value[HTML_OBJECT_TYPE])
_ObjectType = value[HTML_OBJECT_TYPE];
if (present[HTML_OBJECT_DATA] && value[HTML_OBJECT_DATA])
_ObjectData = value[HTML_OBJECT_DATA];
if (present[HTML_OBJECT_ID] && value[HTML_OBJECT_ID])
_ObjectMD5Sum = value[HTML_OBJECT_ID];
if (present[HTML_OBJECT_STANDBY] && value[HTML_OBJECT_STANDBY])
_ObjectAction = value[HTML_OBJECT_STANDBY];
break;
} }
} }
} }
@ -1371,6 +1489,14 @@ void CGroupHTML::endElement (uint element_number)
popIfNotEmpty (_UL); popIfNotEmpty (_UL);
} }
break; break;
case HTML_OBJECT:
if (_ObjectType=="application/ryzom-data")
{
if (!_ObjectData.empty())
{
addBnpDownload(_ObjectData, _ObjectAction);
}
}
} }
} }
} }
@ -1483,7 +1609,11 @@ CGroupHTML::CGroupHTML(const TCtorParam &param)
DefaultBackgroundBitmapView = "bg"; DefaultBackgroundBitmapView = "bg";
clearContext(); clearContext();
MultiCurl = curl_multi_init();
RunningCurls = 0;
initImageDownload(); initImageDownload();
initBnpDownload();
} }
// *************************************************************************** // ***************************************************************************
@ -2313,9 +2443,14 @@ CCtrlButton *CGroupHTML::addButton(CCtrlButton::EType type, const std::string &/
ctrlButton->setActionOnLeftClick (actionHandler); ctrlButton->setActionOnLeftClick (actionHandler);
ctrlButton->setParamsOnLeftClick (actionHandlerParams); ctrlButton->setParamsOnLeftClick (actionHandlerParams);
// Translate the tooltip // Translate the tooltip or display raw text (tooltip from webig)
if (tooltip) if (tooltip)
ctrlButton->setDefaultContextHelp (CI18N::get (tooltip)); {
if (CI18N::hasTranslation(tooltip))
ctrlButton->setDefaultContextHelp (CI18N::get(tooltip));
else
ctrlButton->setDefaultContextHelp (ucstring(tooltip));
}
getParagraph()->addChild (ctrlButton); getParagraph()->addChild (ctrlButton);
paragraphChange (); paragraphChange ();
@ -2913,7 +3048,7 @@ void CGroupHTML::handle ()
void CGroupHTML::draw () void CGroupHTML::draw ()
{ {
checkImageDownload(); checkDownloads();
CGroupScrollText::draw (); CGroupScrollText::draw ();
} }

@ -293,6 +293,8 @@ protected :
// the script to execute // the script to execute
std::string _LuaScript; std::string _LuaScript;
bool _ParsingBnpUrl;
std::string _BnpUrl;
// Someone is conecting. We got problem with libwww : 2 connection requests can deadlock the client. // Someone is conecting. We got problem with libwww : 2 connection requests can deadlock the client.
static CGroupHTML *_ConnectingLock; static CGroupHTML *_ConnectingLock;
@ -481,6 +483,12 @@ protected :
bool _SelectOption; bool _SelectOption;
ucstring _SelectOptionStr; ucstring _SelectOptionStr;
// Current node is a object
std::string _ObjectType;
std::string _ObjectData;
std::string _ObjectMD5Sum;
std::string _ObjectAction;
// Get last char // Get last char
ucchar getLastChar() const; ucchar getLastChar() const;
@ -527,25 +535,38 @@ private:
static ucstring decodeHTMLEntities(const ucstring &str); static ucstring decodeHTMLEntities(const ucstring &str);
// ImageDownload system // ImageDownload system
enum TDataType {ImgType= 0, BnpType};
struct CImageDownload struct CDataDownload
{ {
CImageDownload(CURL *c, const std::string &u, FILE *f, CViewBase *i) : curl(c), url(u), fp(f) { imgs.push_back(i); } CDataDownload(CURL *c, const std::string &u, FILE *f, TDataType t, CViewBase *i) : curl(c), url(u), fp(f), type(t) { imgs.push_back(i); }
CURL *curl; CURL *curl;
std::string url; std::string url;
TDataType type;
FILE *fp; FILE *fp;
std::vector<CViewBase *> imgs; std::vector<CViewBase *> imgs;
}; };
std::vector<CImageDownload> Curls; std::vector<CDataDownload> Curls;
CURLM *MultiCurl; CURLM *MultiCurl;
int RunningCurls; int RunningCurls;
void initImageDownload(); void initImageDownload();
void releaseImageDownload();
void checkImageDownload(); void checkImageDownload();
void addImageDownload(const std::string &url, CViewBase *img); void addImageDownload(const std::string &url, CViewBase *img);
std::string localImageName(const std::string &url); std::string localImageName(const std::string &url);
// BnpDownload system
void initBnpDownload();
void checkBnpDownload();
void addBnpDownload(const std::string &url, const std::string &action);
std::string localBnpName(const std::string &url);
void releaseDownloads();
void checkDownloads();
}; };
// adapter group that store y offset for inputs inside an html form // adapter group that store y offset for inputs inside an html form

@ -514,6 +514,13 @@ CGroupInSceneUserInfo *CGroupInSceneUserInfo::build (class CEntityCL *entity)
if (!isForageSource) if (!isForageSource)
{ {
CViewBase * invisibleLogo = info->getView("invisible_logo");
if (entity->isUser() && invisibleLogo)
{
bool invisible = pIM->getDbProp("SERVER:USER:IS_INVISIBLE")->getValueBool();
invisibleLogo->setActive(invisible);
}
// Get the target bitmap // Get the target bitmap
CViewBase *target = leftGroup->getView ("target"); CViewBase *target = leftGroup->getView ("target");
if (target) if (target)
@ -532,25 +539,91 @@ CGroupInSceneUserInfo *CGroupInSceneUserInfo::build (class CEntityCL *entity)
info->_MissionTarget = bitmap; info->_MissionTarget = bitmap;
} }
// set or inactive pvp logos CViewBase * pvpCivLogo = info->getView ("pvp_faction_civ_logo");
CViewBase * pvpCultLogo = info->getView ("pvp_faction_cult_logo");
CPlayerCL * pPlayer = dynamic_cast<CPlayerCL*>(entity); CPlayerCL * pPlayer = dynamic_cast<CPlayerCL*>(entity);
if (pPlayer != NULL && needPvPLogo) if (pPlayer == NULL)
needPvPLogo = false;
// set or inactive pvp logos
bool needCivPvpLogo = needPvPLogo;
bool needCultPvpLogo = needPvPLogo;
if (pPlayer != NULL && needPvPLogo && pvpCivLogo && pvpCultLogo)
{ {
CViewBase * pvpFactionLogo = info->getView ("pvp_faction_logo"); uint8 civToDisplay = (uint8)(pPlayer->getClanCivMaxFame() & 0xFF);
if (pvpFactionLogo) uint8 cultToDisplay = (uint8)(pPlayer->getClanCultMaxFame() & 0xFF);
if (!entity->isUser())
{ {
if( pPlayer->getPvpMode()&PVP_MODE::PvpFaction || pPlayer->getPvpMode()&PVP_MODE::PvpFactionFlagged) // Check if are Civ Allies
for (uint8 i = 0; i < 4; i++)
if ( (pPlayer->isPvpAlly(i) && UserEntity->isPvpAlly(i)) ||
(pPlayer->isPvpEnnemy(i) && UserEntity->isPvpEnnemy(i)) )
civToDisplay = i;
// Check if are Civ Ennemies
for (uint8 i = 0; i < 4; i++)
if ( (pPlayer->isPvpAlly(i) && UserEntity->isPvpEnnemy(i)) ||
(pPlayer->isPvpEnnemy(i) && UserEntity->isPvpAlly(i)) )
civToDisplay = i;
// Check if are Cult Allies
for (uint8 i = 4; i < 7; i++)
if ( (pPlayer->isPvpAlly(i) && UserEntity->isPvpAlly(i)) ||
(pPlayer->isPvpEnnemy(i) && UserEntity->isPvpEnnemy(i)) )
cultToDisplay = i;
// Check if are Cult Ennemies
for (uint8 i = 4; i < 7; i++)
if ( (pPlayer->isPvpAlly(i) && UserEntity->isPvpEnnemy(i)) ||
(pPlayer->isPvpEnnemy(i) && UserEntity->isPvpAlly(i)) )
cultToDisplay = i;
}
if ((pPlayer->getPvpMode() & PVP_MODE::PvpFaction) || (pPlayer->getPvpMode() & PVP_MODE::PvpFactionFlagged))
{
CViewBitmap * pvpCivLogoBmp = dynamic_cast<CViewBitmap *>(pvpCivLogo);
if( pvpCivLogoBmp )
{ {
CViewBitmap * pvpFactionLogoBmp = dynamic_cast<CViewBitmap *>(pvpFactionLogo); if (pPlayer->isPvpAlly(civToDisplay))
if( pvpFactionLogoBmp ) if (pPlayer->isPvpRanger())
pvpFactionLogoBmp->setTexture( pIM->getDefine(PVP_CLAN::toIconDefineString(pPlayer->getPvpClan())) ); pvpCivLogoBmp->setTexture("pvp_ally_ranger.tga");
else
pvpCivLogoBmp->setTexture("pvp_ally_"+toString(civToDisplay)+".tga");
else if (pPlayer->isPvpEnnemy(civToDisplay))
if (pPlayer->isPvpMarauder())
pvpCivLogoBmp->setTexture("pvp_enemy_marauder.tga");
else
pvpCivLogoBmp->setTexture("pvp_enemy_"+toString(civToDisplay)+".tga");
else
needCivPvpLogo = false;
} }
else
CViewBitmap * pvpCultLogoBmp = dynamic_cast<CViewBitmap *>(pvpCultLogo);
if( pvpCultLogoBmp )
{ {
pvpFactionLogo->setActive(false); if (pPlayer->isPvpAlly(cultToDisplay))
if (pPlayer->isPvpPrimas())
pvpCultLogoBmp->setTexture("pvp_ally_primas.tga");
else
pvpCultLogoBmp->setTexture("pvp_ally_"+toString(cultToDisplay)+".tga");
else if (pPlayer->isPvpEnnemy(cultToDisplay))
if (pPlayer->isPvpTrytonist())
pvpCultLogoBmp->setTexture("pvp_enemy_trytonist.tga");
else
pvpCultLogoBmp->setTexture("pvp_enemy_"+toString(cultToDisplay)+".tga");
else
needCultPvpLogo = false;
} }
} }
else
{
needCivPvpLogo = false;
needCultPvpLogo = false;
}
CViewBase * pvpOutpostLogo = info->getView ("pvp_outpost_logo"); CViewBase * pvpOutpostLogo = info->getView ("pvp_outpost_logo");
if (pvpOutpostLogo) if (pvpOutpostLogo)
{ {
@ -563,7 +636,7 @@ CGroupInSceneUserInfo *CGroupInSceneUserInfo::build (class CEntityCL *entity)
CViewBase * pvpDuelLogo = info->getView ("pvp_duel_logo"); CViewBase * pvpDuelLogo = info->getView ("pvp_duel_logo");
if (pvpDuelLogo) if (pvpDuelLogo)
{ {
if( !(pPlayer->getPvpMode()&PVP_MODE::PvpDuel) ) if( !(pPlayer->getPvpMode()&PVP_MODE::PvpDuel || pPlayer->getPvpMode()&PVP_MODE::PvpChallenge) )
{ {
pvpDuelLogo->setActive(false); pvpDuelLogo->setActive(false);
} }
@ -571,11 +644,6 @@ CGroupInSceneUserInfo *CGroupInSceneUserInfo::build (class CEntityCL *entity)
} }
else else
{ {
// unactive pvp logos
CViewBase * pvpFactionLogo = info->getView ("pvp_faction_logo");
if (pvpFactionLogo)
pvpFactionLogo->setActive(false);
CViewBase * pvpOutpostLogo = info->getView ("pvp_outpost_logo"); CViewBase * pvpOutpostLogo = info->getView ("pvp_outpost_logo");
if (pvpOutpostLogo) if (pvpOutpostLogo)
pvpOutpostLogo->setActive(false); pvpOutpostLogo->setActive(false);
@ -584,6 +652,13 @@ CGroupInSceneUserInfo *CGroupInSceneUserInfo::build (class CEntityCL *entity)
if (pvpDuelLogo) if (pvpDuelLogo)
pvpDuelLogo->setActive(false); pvpDuelLogo->setActive(false);
} }
if (pvpCivLogo)
pvpCivLogo->setActive(needCivPvpLogo);
if (pvpCultLogo)
pvpCultLogo->setActive(needCultPvpLogo);
} }
// No bar and no string ? // No bar and no string ?

@ -47,6 +47,7 @@
using namespace std; using namespace std;
using namespace NLMISC; using namespace NLMISC;
extern CPeopleInterraction PeopleInterraction;
NLMISC_REGISTER_OBJECT(CViewBase, CDBGroupListAscensor, std::string, "list_sheet_guild"); NLMISC_REGISTER_OBJECT(CViewBase, CDBGroupListAscensor, std::string, "list_sheet_guild");
@ -54,26 +55,27 @@ NLMISC_REGISTER_OBJECT(CViewBase, CDBGroupListAscensor, std::string, "list_sheet
// Interface part // Interface part
// *************************************************************************** // ***************************************************************************
#define WIN_GUILD "ui:interface:guild" #define WIN_GUILD "ui:interface:guild"
#define WIN_GUILD_CHAT "ui:interface:guild_chat" #define WIN_GUILD_CHAT "ui:interface:guild_chat"
#define WIN_GUILD_FORUM "ui:interface:guild_forum" #define WIN_GUILD_FORUM "ui:interface:guild_forum"
#define VIEW_TEXT_GUILD_QUIT "ui:interface:guild:content:tab_guild:quit_guild" #define VIEW_TEXT_GUILD_QUIT "ui:interface:guild:content:tab_guild:quit_guild"
#define CTRL_SHEET_GUILD_BLASON "ui:interface:guild:content:tab_guild:blason" #define CTRL_SHEET_GUILD_BLASON "ui:interface:guild:content:tab_guild:blason"
#define VIEW_TEXT_GUILD_MEMBER_COUNT "ui:interface:guild:content:tab_guild:member_count" #define VIEW_TEXT_GUILD_MEMBER_COUNT "ui:interface:guild:content:tab_guild:member_count"
#define LIST_GUILD_MEMBERS "ui:interface:guild:content:tab_guild:list_member:guild_members" #define LIST_GUILD_MEMBERS "ui:interface:guild:content:tab_guild:list_member:guild_members"
#define CTRL_QUIT_GUILD "ui:interface:guild:content:tab_guild:quit_guild" #define CTRL_QUIT_GUILD "ui:interface:guild:content:tab_guild:quit_guild"
#define TEMPLATE_GUILD_MEMBER "member_template" #define TEMPLATE_GUILD_MEMBER "member_template"
#define TEMPLATE_GUILD_MEMBER_NAME "name" #define TEMPLATE_GUILD_MEMBER_NAME "name"
#define TEMPLATE_GUILD_MEMBER_GRADE "grade" #define TEMPLATE_GUILD_MEMBER_GRADE "grade"
#define TEMPLATE_GUILD_MEMBER_SCORE "score" #define TEMPLATE_GUILD_MEMBER_SCORE "score"
#define MENU_GUILD_MEMBER "ui:interface:menu_member" #define TEMPLATE_GUILD_MEMBER_ENTER_DATE "enter_date"
#define MENU_GUILD_MEMBER "ui:interface:menu_member"
#define WIN_ASCENSOR "ui:interface:ascensor_teleport_list" #define WIN_ASCENSOR "ui:interface:ascensor_teleport_list"
#define WIN_JOIN_PROPOSAL "ui:interface:join_guild_proposal" #define WIN_JOIN_PROPOSAL "ui:interface:join_guild_proposal"
#define VIEW_JOIN_PROPOSAL_PHRASE "ui:interface:join_guild_proposal:content:inside:phrase" #define VIEW_JOIN_PROPOSAL_PHRASE "ui:interface:join_guild_proposal:content:inside:phrase"
CGuildManager* CGuildManager::_Instance = NULL; CGuildManager* CGuildManager::_Instance = NULL;
@ -109,16 +111,53 @@ static inline bool lt_member_grade(const SGuildMember &m1, const SGuildMember &m
return m1.Grade < m2.Grade; return m1.Grade < m2.Grade;
} }
static inline bool lt_member_online(const SGuildMember &m1, const SGuildMember &m2)
{
if (m1.Online == m2.Online)
{
return lt_member_grade(m1, m2);
}
// Compare online status
switch (m1.Online)
{
case ccs_online:
// m1 is < if m1 is online
return true;
break;
case ccs_online_abroad:
// m1 is < if m2 is offline
return (m2.Online == ccs_offline);
break;
case ccs_offline:
default:
// m2 is always < if m1 is offline
return false;
break;
}
}
// *************************************************************************** // ***************************************************************************
void CGuildManager::sortGuildMembers() void CGuildManager::sortGuildMembers(TSortOrder order)
{ {
if (_GuildMembers.size() < 2) return; if (_GuildMembers.size() < 2) return;
// First sort by name switch (order)
sort(_GuildMembers.begin(), _GuildMembers.end(), lt_member_name); {
default:
// Second sort by grade case sort_grade:
stable_sort(_GuildMembers.begin(), _GuildMembers.end(), lt_member_grade); sort(_GuildMembers.begin(), _GuildMembers.end(), lt_member_name);
stable_sort(_GuildMembers.begin(), _GuildMembers.end(), lt_member_grade);
break;
case sort_name:
sort(_GuildMembers.begin(), _GuildMembers.end(), lt_member_name);
break;
case sort_online:
sort(_GuildMembers.begin(), _GuildMembers.end(), lt_member_name);
stable_sort(_GuildMembers.begin(), _GuildMembers.end(), lt_member_online);
break;
}
} }
bool CGuildManager::isProxy() bool CGuildManager::isProxy()
@ -715,8 +754,9 @@ class CAHGuildSheetOpen : public IActionHandler
// *** Update Members, if necessary // *** Update Members, if necessary
if(updateMembers) if(updateMembers)
{ {
CGuildManager::TSortOrder order = (CGuildManager::TSortOrder)(pIM->getDbProp("UI:SAVE:GUILD_LIST:SORT_ORDER")->getValue32());
// Sort the members in Guild Manager // Sort the members in Guild Manager
pGM->sortGuildMembers(); pGM->sortGuildMembers(order);
// update member count view // update member count view
const vector<SGuildMember> &rGuildMembers = pGM->getGuildMembers(); const vector<SGuildMember> &rGuildMembers = pGM->getGuildMembers();
@ -784,6 +824,21 @@ class CAHGuildSheetOpen : public IActionHandler
} }
} }
// Enter Date
CViewText *pViewEnterDate = dynamic_cast<CViewText*>(pLine->getView(TEMPLATE_GUILD_MEMBER_ENTER_DATE));
if (pViewEnterDate != NULL)
{
CRyzomTime rt;
rt.updateRyzomClock(rGuildMembers[i].EnterDate);
ucstring str = toString("%04d", rt.getRyzomYear()) + " ";
str += CI18N::get("uiJenaYear") + " : ";
str += CI18N::get("uiAtysianCycle") + " ";
str += toString("%01d", rt.getRyzomCycle()+1) +", ";
str += CI18N::get("ui"+MONTH::toString( (MONTH::EMonth)rt.getRyzomMonthInCurrentCycle() )) + ", ";
str += toString("%02d", rt.getRyzomDayOfMonth()+1);
pViewEnterDate->setText(str);
}
// Add to the list // Add to the list
pLine->setParent (pParent); pLine->setParent (pParent);
pParent->addChild (pLine); pParent->addChild (pLine);
@ -852,15 +907,7 @@ class CAHGuildSheetMenuOpen : public IActionHandler
return; return;
} }
// *** Check with the grade of the local player wich types of actions we can do on the player selected // *** Check with the grade of the local player wich types of actions we can do on the player selected
// Grade less or equal cant do anything
if (pGM->getGrade() >= rGuildMembers[nLineNb].Grade)
{
// Close
pIM->disableModalWindow();
return;
}
// enable or disable menu entries // enable or disable menu entries
if (pGM->isProxy()) if (pGM->isProxy())
@ -871,7 +918,11 @@ class CAHGuildSheetMenuOpen : public IActionHandler
else else
{ {
// Depending on the grade we can do things or other // Depending on the grade we can do things or other
if (pGM->getGrade() == EGSPD::CGuildGrade::Leader)
// Grade less or equal can't do anything
if (pGM->getGrade() >= rGuildMembers[nLineNb].Grade)
setRights(false, false, false, false, false, false, false);
else if (pGM->getGrade() == EGSPD::CGuildGrade::Leader)
setRights(true, true, true, true, true, true, true); setRights(true, true, true, true, true, true, true);
else if (pGM->getGrade() == EGSPD::CGuildGrade::HighOfficer) else if (pGM->getGrade() == EGSPD::CGuildGrade::HighOfficer)
setRights(false, false, true, true, true, true, true); setRights(false, false, true, true, true, true, true);
@ -928,6 +979,70 @@ static void sendMsgSetGrade(EGSPD::CGuildGrade::TGuildGrade Grade)
} }
} }
// ***************************************************************************
// Sort the guild member list
class CAHGuildSheetSortGuildList : public IActionHandler
{
public:
void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */)
{
CInterfaceManager* pIM= CInterfaceManager::getInstance();
CGuildManager::TSortOrder order = (CGuildManager::TSortOrder)(pIM->getDbProp("UI:SAVE:GUILD_LIST:SORT_ORDER")->getValue32());
order = (CGuildManager::TSortOrder)(order + 1);
if (order == CGuildManager::END_SORT_ORDER)
{
order = CGuildManager::START_SORT_ORDER;
}
pIM->getDbProp("UI:SAVE:GUILD_LIST:SORT_ORDER")->setValue32((sint32)order);
pIM->runActionHandler("guild_sheet_open", NULL, toString("update_members=1"));
}
};
REGISTER_ACTION_HANDLER(CAHGuildSheetSortGuildList, "sort_guild_list");
// ***************************************************************************
// Invoke the 'tell' command on a contact from its menu
// The tell command is displayed in the 'around me' window
class CAHGuildSheetTellMember : public IActionHandler
{
public:
void execute (CCtrlBase * pCaller, const std::string &/* sParams */)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CGuildManager *pGM = CGuildManager::getInstance();
const vector<SGuildMember> &rGuildMembers = pGM->getGuildMembers();
// *** Check and retrieve the current member index (index in the member list)
CCtrlBase *ctrlLaunchingModal= pIM->getCtrlLaunchingModal();
if (pCaller == NULL)
{
// Error -> Close
return;
}
string sId = pCaller->getId();
sId = sId.substr(sId.rfind('m')+1,sId.size());
sint32 nLineNb;
fromString(sId, nLineNb);
if ((nLineNb < 0) || (nLineNb >= (sint32)rGuildMembers.size()))
{
// Error -> Close
return;
}
MemberIndexSelected= nLineNb;
MemberNameSelected = rGuildMembers[nLineNb].Name;
CPeopleInterraction::displayTellInMainChat(MemberNameSelected);
}
// Current selection
static sint32 MemberIndexSelected; // Index of the member selected when left clicked
static ucstring MemberNameSelected; // Name of the member selected when lef clicked
};
REGISTER_ACTION_HANDLER(CAHGuildSheetTellMember, "guild_tell_member");
sint32 CAHGuildSheetTellMember::MemberIndexSelected= -1;
ucstring CAHGuildSheetTellMember::MemberNameSelected;
// *************************************************************************** // ***************************************************************************
class CAHGuildSheetSetLeader : public IActionHandler class CAHGuildSheetSetLeader : public IActionHandler
{ {

@ -98,7 +98,16 @@ public:
const SGuild &getGuild() { return _Guild; } const SGuild &getGuild() { return _Guild; }
const std::vector<SGuildMember> &getGuildMembers() { return _GuildMembers; } const std::vector<SGuildMember> &getGuildMembers() { return _GuildMembers; }
void sortGuildMembers(); enum TSortOrder
{
sort_grade,
START_SORT_ORDER = sort_grade,
sort_name,
sort_online,
END_SORT_ORDER
};
void sortGuildMembers(TSortOrder order = sort_grade);
/// Check if the guild is a proxified guild (not managed on the actual shard) /// Check if the guild is a proxified guild (not managed on the actual shard)
bool isProxy(); bool isProxy();

@ -506,7 +506,10 @@ void CInterface3DScene::draw ()
for (i = 0; i < _Characters.size(); ++i) for (i = 0; i < _Characters.size(); ++i)
_Characters[i]->setClusterSystem ((UInstanceGroup*)-1); _Characters[i]->setClusterSystem ((UInstanceGroup*)-1);
for (i = 0; i < _Shapes.size(); ++i) for (i = 0; i < _Shapes.size(); ++i)
_Shapes[i]->getShape().setClusterSystem ((UInstanceGroup*)-1); {
if (!_Shapes[i]->getShape().empty())
_Shapes[i]->getShape().setClusterSystem ((UInstanceGroup*)-1);
}
for (i = 0; i < _FXs.size(); ++i) for (i = 0; i < _FXs.size(); ++i)
if (!_FXs[i]->getPS().empty()) if (!_FXs[i]->getPS().empty())
_FXs[i]->getPS().setClusterSystem ((UInstanceGroup*)-1); _FXs[i]->getPS().setClusterSystem ((UInstanceGroup*)-1);
@ -1344,7 +1347,20 @@ std::string CInterface3DShape::getName() const
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void CInterface3DShape::setName (const std::string &ht) void CInterface3DShape::setName (const std::string &ht)
{ {
string lwrname = strlwr(ht); if (ht.empty())
{
CInterface3DScene *pI3DS = dynamic_cast<CInterface3DScene*>(_Parent);
nlassert(pI3DS != NULL);
if (!_Instance.empty())
{
pI3DS->getScene()->deleteInstance(_Instance);
}
return;
_Name.clear();
}
string lwrname = toLower(ht);
if (lwrname != _Name) if (lwrname != _Name)
{ {
CInterface3DScene *pI3DS = dynamic_cast<CInterface3DScene*>(_Parent); CInterface3DScene *pI3DS = dynamic_cast<CInterface3DScene*>(_Parent);

@ -101,6 +101,7 @@
#include "../entity_animation_manager.h" // for emotes #include "../entity_animation_manager.h" // for emotes
#include "../net_manager.h" // for emotes #include "../net_manager.h" // for emotes
#include "../client_chat_manager.h" // for emotes #include "../client_chat_manager.h" // for emotes
#include "../entities.h"
#include "chat_text_manager.h" #include "chat_text_manager.h"
#include "../npc_icon.h" #include "../npc_icon.h"
@ -1288,6 +1289,18 @@ void CInterfaceManager::updateFrameEvents()
pVT = dynamic_cast<CViewText*>(getElementFromId("ui:interface:map:content:map_content:time")); pVT = dynamic_cast<CViewText*>(getElementFromId("ui:interface:map:content:map_content:time"));
if (pVT != NULL) if (pVT != NULL)
pVT->setText(str); pVT->setText(str);
str.clear();
// Update the clock in the compass if enabled.
pVT = dynamic_cast<CViewText*>(getElementFromId("ui:interface:compass:clock:time"));
if (pVT != NULL)
{
if (pVT->getActive())
{
str = getTimestampHuman("%H:%M");
pVT->setText(str);
}
}
} }
} }
@ -6274,3 +6287,300 @@ void CInterfaceManager::CServerToLocalAutoCopy::onLocalChange(ICDBNode *localNod
} }
} }
// ------------------------------------------------------------------------------------------------
char* CInterfaceManager::getTimestampHuman(const char* format /* "[%H:%M:%S] " */)
{
static char cstime[25];
time_t date;
time (&date);
struct tm *tms = localtime(&date);
if (tms)
{
strftime(cstime, 25, format, tms);
}
else
{
strcpy(cstime, "");
}
return cstime;
}
/*
* Parse tokens in a chatmessage or emote
*
* Valid subjects:
* $me$
* $t$
* $tt$
* $tm1$..$tm8$
*
* Valid parameters:
* $<subject>.name$
* $<subject>.title$
* $<subject>.race$
* $<subject>.guild$
* $<subject>.gs(m/f/n)$
*
* Default parameter if parameter result is empty:
* $<subject>.<parameter>/<default>$
*
* All \d's in default parameter remove a following character.
*/
bool CInterfaceManager::parseTokens(ucstring& ucstr)
{
ucstring str = ucstr;
ucstring start_token = "$";
ucstring end_token = "$";
size_t start_pos = 0;
size_t end_pos = 1;
sint endless_loop_protector = 0;
while ((start_pos < str.length() - 1) &&
((start_pos = str.find(start_token, start_pos)) != string::npos))
{
endless_loop_protector++;
if (endless_loop_protector > 100)
{
break;
}
// Get the whole token substring first
end_pos = str.find(end_token, start_pos + 1);
if ((start_pos == string::npos) ||
(end_pos == string::npos) ||
(end_pos <= start_pos + 1))
{
// Wrong formatting; give up on this one.
start_pos = max(start_pos, end_pos);
continue;
}
// Get everything between the two "$"
size_t token_start_pos = start_pos + start_token.length();
size_t token_end_pos = end_pos - end_token.length();
if ((token_start_pos - token_end_pos) < 0)
{
// Wrong formatting; give up on this one.
start_pos = end_pos;
continue;
}
ucstring token_whole = str.luabind_substr(start_pos, end_pos - start_pos + 1);
ucstring token_string = token_whole.luabind_substr(1, token_whole.length() - 2);
ucstring token_replacement = token_whole;
ucstring token_default = token_whole;
ucstring token_subject;
ucstring token_param;
// Does the token have a parameter?
// If not it is 'name' by default
vector<ucstring> token_vector;
vector<ucstring> param_vector;
splitUCString(token_string, ucstring("."), token_vector);
token_subject = token_vector[0];
if (token_vector.size() == 1)
{
splitUCString(token_subject, ucstring("/"), param_vector);
token_subject = param_vector[0];
token_param = ucstring("name");
}
else
{
token_param = token_vector[1];
if (token_param.luabind_substr(0, 3) != ucstring("gs("))
{
splitUCString(token_vector[1], ucstring("/"), param_vector);
token_param = param_vector[0];
}
}
// Get any default value, if not gs
sint extra_replacement = 0;
if (token_param.luabind_substr(0, 3) != ucstring("gs("))
{
if (param_vector.size() == 2)
{
// Set default value
token_replacement = param_vector[1];
// Delete following chars for every '\d' in default
string::size_type token_replacement_pos;
while ((token_replacement_pos = token_replacement.find(ucstring("\\d"))) != string::npos)
{
token_replacement.replace(token_replacement_pos, 2, ucstring(""));
extra_replacement++;
}
token_default = token_replacement;
}
}
CEntityCL *pTokenSubjectEntity = NULL;
if (token_subject == ucstring("me"))
{
pTokenSubjectEntity = static_cast<CEntityCL*>(UserEntity);
}
else if (token_subject == ucstring("t"))
{
// Target
uint targetSlot = UserEntity->targetSlot();
pTokenSubjectEntity = EntitiesMngr.entity(targetSlot);
}
else if (token_subject == ucstring("tt"))
{
// Target's target
uint targetSlot = UserEntity->targetSlot();
CEntityCL *target = EntitiesMngr.entity(targetSlot);
if (target)
{
// Check the new slot.
CLFECOMMON::TCLEntityId newSlot = target->targetSlot();
CEntityCL* pE = EntitiesMngr.entity(newSlot);
if (pE)
{
pTokenSubjectEntity = pE;
}
}
}
else if ((token_subject.length() == 3) &&
(token_subject.luabind_substr(0, 2) == ucstring("tm")))
{
// Teammate
uint indexInTeam = 0;
fromString(token_subject.luabind_substr(2, 1).toString(), indexInTeam);
// Make 0-based
--indexInTeam;
if (indexInTeam < PeopleInterraction.TeamList.getNumPeople() )
{
// Index is the database index (serverIndex() not used for team list)
CCDBNodeLeaf *pNL = CInterfaceManager::getInstance()->getDbProp( NLMISC::toString(TEAM_DB_PATH ":%hu:NAME", indexInTeam ), false);
if (pNL && pNL->getValueBool() )
{
// There is a character corresponding to this index
pNL = CInterfaceManager::getInstance()->getDbProp( NLMISC::toString( TEAM_DB_PATH ":%hu:UID", indexInTeam ), false );
if (pNL)
{
CLFECOMMON::TClientDataSetIndex compressedIndex = pNL->getValue32();
// Search entity in vision
CEntityCL *entity = EntitiesMngr.getEntityByCompressedIndex( compressedIndex );
if (entity)
{
pTokenSubjectEntity = entity;
}
}
}
}
}
else
{
// Unknown token subject, skip it
start_pos = end_pos;
continue;
}
if (pTokenSubjectEntity != NULL)
{
// Parse the parameter
if (token_param == ucstring("name"))
{
ucstring name = pTokenSubjectEntity->getDisplayName();
// special case where there is only a title, very rare case for some NPC
if (name.empty())
{
name = pTokenSubjectEntity->getTitle();
}
token_replacement = name.empty() ? token_replacement : name;
}
else if (token_param == ucstring("title"))
{
ucstring title = pTokenSubjectEntity->getTitle();
token_replacement = title.empty() ? token_replacement : title;
}
else if (token_param == ucstring("race"))
{
CCharacterCL *pC = (CCharacterCL*)(pTokenSubjectEntity);
if (pC)
{
EGSPD::CPeople::TPeople race = pC->people();
if (race >= EGSPD::CPeople::Playable && race <= EGSPD::CPeople::EndPlayable)
{
ucstring srace = NLMISC::CI18N::get("io" + EGSPD::CPeople::toString(race));
token_replacement = srace.empty() ? token_replacement : srace;
}
}
}
else if (token_param == ucstring("guild"))
{
STRING_MANAGER::CStringManagerClient *pSMC = STRING_MANAGER::CStringManagerClient::instance();
ucstring ucGuildName;
if (pSMC->getString(pTokenSubjectEntity->getGuildNameID(), ucGuildName))
{
token_replacement = ucGuildName.empty() ? token_replacement : ucGuildName;
}
}
else if (token_param.luabind_substr(0, 3) == ucstring("gs(") &&
token_param.luabind_substr(token_param.length() - 1 , 1) == ucstring(")"))
{
// Gender string
vector<ucstring> strList;
ucstring gender_string = token_param.luabind_substr(3, token_param.length() - 4);
splitUCString(gender_string, ucstring("/"), strList);
if (strList.size() <= 1)
{
start_pos = end_pos;
continue;
}
// Only care about gender if it's a humanoid.
GSGENDER::EGender gender = GSGENDER::neutral;
if (pTokenSubjectEntity->isUser() || pTokenSubjectEntity->isPlayer() || pTokenSubjectEntity->isNPC())
{
CCharacterCL *pC = (CCharacterCL*)(pTokenSubjectEntity);
if (pC)
{
gender = pC->getGender();
}
}
// Neuter part is optional.
// Fallback to male if something is wrong.
GSGENDER::EGender g = ((uint)gender >= strList.size()) ? GSGENDER::male : gender;
token_replacement = strList[g];
}
}
if (token_whole == token_replacement)
{
// Nothing to replace; show message and exit
CInterfaceManager *im = CInterfaceManager::getInstance();
ucstring message = ucstring(CI18N::get("uiUntranslatedToken"));
message.replace(message.find(ucstring("%s")), 2, token_whole);
im->displaySystemInfo(message);
return false;
}
// Replace all occurances of token with the replacement
size_t token_whole_pos = str.find(token_whole);
start_pos = 0;
// Only do extra replacement if using default
extra_replacement = (token_replacement == token_default) ? extra_replacement : 0;
while (str.find(token_whole, start_pos) != string::npos)
{
str = str.replace(token_whole_pos, token_whole.length() + extra_replacement, token_replacement);
start_pos = token_whole_pos + token_replacement.length();
token_whole_pos = str.find(token_whole, start_pos);
}
}
ucstr = str;
return true;;
}

@ -712,6 +712,14 @@ public:
void updateTooltipCoords(); void updateTooltipCoords();
/** Returns a human readable timestamp with the given format.
*/
static char* getTimestampHuman(const char* format = "[%H:%M:%S] ");
/** Parses any tokens in the ucstring like $t$ or $g()$
*/
static bool parseTokens(ucstring& ucstr);
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
private: private:

@ -25,6 +25,7 @@
#include "nel/misc/algo.h" #include "nel/misc/algo.h"
#include "nel/misc/mem_stream.h" #include "nel/misc/mem_stream.h"
#include "nel/misc/factory.h" #include "nel/misc/factory.h"
#include "nel/misc/big_file.h"
#include "game_share/xml_auto_ptr.h" #include "game_share/xml_auto_ptr.h"
@ -106,6 +107,7 @@
#include "../commands.h" #include "../commands.h"
#include "lua_helper.h" #include "lua_helper.h"
#include "lua_ihm.h" #include "lua_ihm.h"
#include "../r2/editor.h"
#ifdef LUA_NEVRAX_VERSION #ifdef LUA_NEVRAX_VERSION
#include "lua_ide_dll_nevrax/include/lua_ide_dll/ide_interface.h" // external debugger #include "lua_ide_dll_nevrax/include/lua_ide_dll/ide_interface.h" // external debugger
@ -114,6 +116,23 @@ const uint32 UI_CACHE_SERIAL_CHECK = (uint32) 'IUG_';
using namespace NLMISC; using namespace NLMISC;
void badLuaParseMessageBox()
{
NL3D::UDriver::TMessageBoxId ret = Driver->systemMessageBox( "LUA files reading failed!\n"
"Some LUA files are corrupted, moved or may have been removed.\n"
"Ryzom may need to be restarted to run properly.\n"
"Would you like to quit now?",
"LUA reading failed!",
NL3D::UDriver::yesNoType,
NL3D::UDriver::exclamationIcon);
if (ret == NL3D::UDriver::yesId)
{
extern void quitCrashReport ();
quitCrashReport ();
exit (EXIT_FAILURE);
}
}
void saveXMLTree(COFile &f, xmlNodePtr node) void saveXMLTree(COFile &f, xmlNodePtr node)
{ {
// save node name // save node name
@ -494,10 +513,16 @@ static void interfaceScriptAsMemStream(const std::string &script, CMemStream &de
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool CInterfaceParser::parseInterface (const std::vector<std::string> & strings, bool reload, bool isFilename) bool CInterfaceParser::parseInterface (const std::vector<std::string> & strings, bool reload, bool isFilename, bool checkInData)
{ {
bool ok; bool ok;
bool needCheck = checkInData;
#if !FINAL_VERSION
needCheck = false;
#endif
// TestYoyo. UnHide For Parsing Profile // TestYoyo. UnHide For Parsing Profile
/* /*
NLMISC::CHTimer::startBench(); NLMISC::CHTimer::startBench();
@ -524,7 +549,19 @@ bool CInterfaceParser::parseInterface (const std::vector<std::string> & strings,
{ {
//get the first file document pointer //get the first file document pointer
firstFileName = *it; firstFileName = *it;
if (!file.open (CPath::lookup(firstFileName))) string filename = CPath::lookup(firstFileName);
bool isInData = false;
if (filename.find ("@") != string::npos)
{
vector<string> bigFilePaths;
CBigFile::getInstance().getBigFilePaths(bigFilePaths);
if (CBigFile::getInstance().getBigFileName(filename.substr(0, filename.find ("@"))) != "data/"+filename.substr(0, filename.find ("@")))
isInData = false;
else
isInData = true;
}
if ((needCheck && !isInData) || !file.open (CPath::lookup(firstFileName)))
{ {
// todo hulud interface syntax error // todo hulud interface syntax error
nlwarning ("could not open file %s, skipping xml parsing",firstFileName.c_str()); nlwarning ("could not open file %s, skipping xml parsing",firstFileName.c_str());
@ -929,7 +966,10 @@ bool CInterfaceParser::parseXMLDocument(xmlNodePtr root, bool reload)
else if ( !strcmp((char*)root->name,"lua") ) else if ( !strcmp((char*)root->name,"lua") )
{ {
if(!parseLUAScript(root)) if(!parseLUAScript(root))
{
badLuaParseMessageBox();
nlwarning ("could not parse 'lua'"); nlwarning ("could not parse 'lua'");
}
} }
root = root->next; root = root->next;
@ -4648,6 +4688,13 @@ void CInterfaceParser::uninitLUA()
bool CInterfaceParser::loadLUA(const std::string &fileName, std::string &error) bool CInterfaceParser::loadLUA(const std::string &fileName, std::string &error)
{ {
// get file // get file
bool needCheck = true;
#if !FINAL_VERSION
needCheck = false;
#endif
string pathName= CPath::lookup(fileName, false); string pathName= CPath::lookup(fileName, false);
if(pathName.empty()) if(pathName.empty())
{ {
@ -4655,6 +4702,20 @@ bool CInterfaceParser::loadLUA(const std::string &fileName, std::string &error)
return false; return false;
} }
bool isInData = false;
if (pathName.find ("@") != string::npos)
{
if (CBigFile::getInstance().getBigFileName(pathName.substr(0, pathName.find ("@"))) != "data/"+pathName.substr(0, pathName.find ("@")))
isInData = false;
else
isInData = true;
}
if (needCheck && !isInData)
{
return false;
}
// Parse script // Parse script
nlassert(_LuaState); nlassert(_LuaState);
try try

@ -103,7 +103,7 @@ public:
* \param isFilename true if xmlFileNames array contains the names of the xml file, false, if each * \param isFilename true if xmlFileNames array contains the names of the xml file, false, if each
* array is a script itself * array is a script itself
*/ */
bool parseInterface (const std::vector<std::string> &xmlFileNames, bool reload, bool isFilename = true); bool parseInterface (const std::vector<std::string> &xmlFileNames, bool reload, bool isFilename = true, bool checkInData = false);
bool parseXMLDocument (xmlNodePtr root, bool reload); bool parseXMLDocument (xmlNodePtr root, bool reload);

@ -4287,7 +4287,14 @@ void CLuaIHM::tell(const ucstring &player, const ucstring &msg)
{ {
if (!msg.empty()) if (!msg.empty())
{ {
ChatMngr.tell(player.toUtf8(), msg); // Parse any tokens in the message.
ucstring msg_modified = msg;
// Parse any tokens in the text
if ( ! CInterfaceManager::parseTokens(msg_modified))
{
return;
}
ChatMngr.tell(player.toUtf8(), msg_modified);
} }
else else
{ {

@ -18,6 +18,7 @@
#include "stdpch.h" #include "stdpch.h"
// client // client
#include "../string_manager_client.h"
#include "people_interraction.h" #include "people_interraction.h"
#include "interface_expr.h" #include "interface_expr.h"
#include "interface_manager.h" #include "interface_manager.h"
@ -756,6 +757,7 @@ void CPeopleInterraction::createGuildChat()
chatDesc.Title = "uiGuildChat"; chatDesc.Title = "uiGuildChat";
chatDesc.Listener = &GuildChatEntryHandler; chatDesc.Listener = &GuildChatEntryHandler;
chatDesc.Localize = true; chatDesc.Localize = true;
chatDesc.Savable = true;
chatDesc.Id = "guild_chat"; chatDesc.Id = "guild_chat";
chatDesc.AHOnCloseButton = "proc"; chatDesc.AHOnCloseButton = "proc";
chatDesc.AHOnCloseButtonParams = "guild_chat_proc_close"; chatDesc.AHOnCloseButtonParams = "guild_chat_proc_close";
@ -774,6 +776,7 @@ void CPeopleInterraction::createYuboChat()
chatDesc.Title = "uiYuboChat"; chatDesc.Title = "uiYuboChat";
chatDesc.Listener = &YuboChatEntryHandler; chatDesc.Listener = &YuboChatEntryHandler;
chatDesc.Localize = true; chatDesc.Localize = true;
chatDesc.Savable = true;
chatDesc.Id = "yubo_chat"; chatDesc.Id = "yubo_chat";
chatDesc.AHOnCloseButton = "proc"; chatDesc.AHOnCloseButton = "proc";
chatDesc.AHOnCloseButtonParams = "yubo_chat_proc_close"; chatDesc.AHOnCloseButtonParams = "yubo_chat_proc_close";
@ -781,6 +784,7 @@ void CPeopleInterraction::createYuboChat()
YuboChat = getChatWndMgr().createChatWindow(chatDesc); YuboChat = getChatWndMgr().createChatWindow(chatDesc);
if (!YuboChat) return; if (!YuboChat) return;
YuboChat->setMenu(STD_CHAT_SOURCE_MENU);
} }
@ -795,6 +799,7 @@ void CPeopleInterraction::createDynamicChats()
DynamicChatEntryHandler[i].DbIndex= i; DynamicChatEntryHandler[i].DbIndex= i;
chatDesc.Listener = &DynamicChatEntryHandler[i]; chatDesc.Listener = &DynamicChatEntryHandler[i];
chatDesc.Localize = false; chatDesc.Localize = false;
chatDesc.Savable = true;
chatDesc.ChatTemplate ="dynamic_chat_id"; chatDesc.ChatTemplate ="dynamic_chat_id";
chatDesc.ChatTemplateParams.push_back(make_pair(string("dyn_chat_nb"),toString(i))); chatDesc.ChatTemplateParams.push_back(make_pair(string("dyn_chat_nb"),toString(i)));
chatDesc.Id = string("dynamic_chat") + toString(i); chatDesc.Id = string("dynamic_chat") + toString(i);
@ -804,6 +809,8 @@ void CPeopleInterraction::createDynamicChats()
chatDesc.HeaderColor = "UI:SAVE:WIN:COLORS:MEM"; chatDesc.HeaderColor = "UI:SAVE:WIN:COLORS:MEM";
DynamicChat[i] = getChatWndMgr().createChatWindow(chatDesc); DynamicChat[i] = getChatWndMgr().createChatWindow(chatDesc);
if (!DynamicChat[i]) continue;
DynamicChat[i]->setMenu(STD_CHAT_SOURCE_MENU);
} }
} }
@ -956,7 +963,23 @@ class CHandlerChatGroupFilter : public IActionHandler
case CChatGroup::team: pUserBut->setHardText("uiFilterTeam"); break; case CChatGroup::team: pUserBut->setHardText("uiFilterTeam"); break;
case CChatGroup::guild: pUserBut->setHardText("uiFilterGuild"); break; case CChatGroup::guild: pUserBut->setHardText("uiFilterGuild"); break;
case CChatGroup::universe: pUserBut->setHardText("uiFilterUniverse"); break; case CChatGroup::universe: pUserBut->setHardText("uiFilterUniverse"); break;
// NB: user chat cannot have yubo_chat or dyn_chat target case CChatGroup::dyn_chat:
uint32 index = PeopleInterraction.TheUserChat.Filter.getTargetDynamicChannelDbIndex();
uint32 textId = pIM->getDbProp("SERVER:DYN_CHAT:CHANNEL"+toString(index)+":NAME")->getValue32();
ucstring title;
STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId, title);
if (title.empty())
{
// Dyn channel not available yet, so set to around
PeopleInterraction.TheUserChat.Filter.setTargetGroup(CChatGroup::arround);
pUserBut->setHardText("uiFilterAround");
}
else
{
pUserBut->setHardText(title.toUtf8());
}
break;
// NB: user chat cannot have yubo_chat target
} }
pUserBut->setActive(true); pUserBut->setActive(true);
@ -1276,6 +1299,10 @@ void CPeopleInterraction::initContactLists( const std::vector<uint32> &vFriendLi
for (uint i = 0; i < vIgnoreListName.size(); ++i) for (uint i = 0; i < vIgnoreListName.size(); ++i)
addContactInList(contactIdPool++, vIgnoreListName[i], ccs_offline, 1); addContactInList(contactIdPool++, vIgnoreListName[i], ccs_offline, 1);
updateAllFreeTellerHeaders(); updateAllFreeTellerHeaders();
CInterfaceManager* pIM= CInterfaceManager::getInstance();
CPeopleList::TSortOrder order = (CPeopleList::TSortOrder)(pIM->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32());
FriendList.sortEx(order);
} }
//================================================================================================================= //=================================================================================================================
@ -1758,6 +1785,20 @@ void CPeopleInterraction::talkInDynamicChannel(uint32 channelNb,ucstring sentenc
} }
} }
//=================================================================================================================
void CPeopleInterraction::displayTellInMainChat(const ucstring &playerName)
{
//CChatWindow *chat = PeopleInterraction.MainChat.Window;
CChatWindow *chat = PeopleInterraction.ChatGroup.Window;
if (!chat) return;
chat->getContainer()->setActive (true);
// make the container blink
chat->getContainer()->enableBlink(2);
// TODO : center the view on the newly created container ?
// display a new command '/name' in the chat. The player must enter a new unique name for the party chat.
chat->setCommand("tell " + playerName + " ", false);
chat->setKeyboardFocus();
}
///////////////////////////////////// /////////////////////////////////////
// ACTION HANDLERS FOR PEOPLE LIST // // ACTION HANDLERS FOR PEOPLE LIST //
@ -1945,22 +1986,6 @@ public:
}; };
REGISTER_ACTION_HANDLER( CHandlerRemoveContact, "remove_contact"); REGISTER_ACTION_HANDLER( CHandlerRemoveContact, "remove_contact");
//=================================================================================================================
static void displayTellInMainChat(const ucstring &playerName)
{
//CChatWindow *chat = PeopleInterraction.MainChat.Window;
CChatWindow *chat = PeopleInterraction.ChatGroup.Window;
if (!chat) return;
chat->getContainer()->setActive (true);
// make the container blink
chat->getContainer()->enableBlink(2);
// TODO : center the view on the newly created container ?
// display a new command '/name' in the chat. The player must enter a new unique name for the party chat.
chat->setCommand("tell " + playerName + " ", false);
chat->setKeyboardFocus();
}
//================================================================================================================= //=================================================================================================================
// Invoke the 'tell' command on a contact from its menu // Invoke the 'tell' command on a contact from its menu
// The tell command is displayed in the 'around me' window // The tell command is displayed in the 'around me' window
@ -1974,7 +1999,7 @@ public:
uint peopleIndex; uint peopleIndex;
if (PeopleInterraction.getPeopleFromCurrentMenu(list, peopleIndex)) if (PeopleInterraction.getPeopleFromCurrentMenu(list, peopleIndex))
{ {
displayTellInMainChat(list->getName(peopleIndex)); CPeopleInterraction::displayTellInMainChat(list->getName(peopleIndex));
} }
} }
}; };
@ -1996,7 +2021,7 @@ class CHandlerTellContact : public IActionHandler
uint peopleIndex; uint peopleIndex;
if (PeopleInterraction.getPeopleFromContainerID(gc->getId(), list, peopleIndex)) if (PeopleInterraction.getPeopleFromContainerID(gc->getId(), list, peopleIndex))
{ {
displayTellInMainChat(list->getName(peopleIndex)); CPeopleInterraction::displayTellInMainChat(list->getName(peopleIndex));
} }
} }
@ -2150,9 +2175,20 @@ class CHandlerSortContacts : public IActionHandler
public: public:
void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */)
{ {
CInterfaceManager* pIM= CInterfaceManager::getInstance();
nlinfo("Load Order : %d", pIM->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32());
CPeopleList::TSortOrder order = (CPeopleList::TSortOrder)(pIM->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32());
order = (CPeopleList::TSortOrder)(order + 1);
if (order == CPeopleList::END_SORT_ORDER) {
order = CPeopleList::START_SORT_ORDER;
}
nlinfo("Save Order : %d", order);
pIM->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->setValue32((sint32)order);
CPeopleList *pl = PeopleInterraction.getPeopleListFromCurrentMenu(); CPeopleList *pl = PeopleInterraction.getPeopleListFromCurrentMenu();
if (pl) if (pl)
pl->sort(); pl->sortEx(order);
} }
}; };
REGISTER_ACTION_HANDLER( CHandlerSortContacts, "sort_contacts"); REGISTER_ACTION_HANDLER( CHandlerSortContacts, "sort_contacts");
@ -2441,6 +2477,30 @@ public:
if (pMenuUniverse) pMenuUniverse->setGrayed (false); if (pMenuUniverse) pMenuUniverse->setGrayed (false);
if (pMenuTeam) pMenuTeam->setGrayed (!teamActive); if (pMenuTeam) pMenuTeam->setGrayed (!teamActive);
if (pMenuGuild) pMenuGuild->setGrayed (!guildActive); if (pMenuGuild) pMenuGuild->setGrayed (!guildActive);
// Remove existing dynamic chats
while (pMenu->getNumLine() > 5)
pMenu->deleteLine(pMenu->getNumLine()-1);
// Add dynamic chats
uint insertion_index = 0;
for (uint i = 0; i < CChatGroup::MaxDynChanPerPlayer; i++)
{
string s = toString(i);
uint32 textId = im->getDbProp("SERVER:DYN_CHAT:CHANNEL"+s+":NAME")->getValue32();
bool active = (textId != 0);
if (active)
{
uint32 canWrite = im->getDbProp("SERVER:DYN_CHAT:CHANNEL"+s+":WRITE_RIGHT")->getValue32();
if (canWrite != 0)
{
ucstring title;
STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId, title);
pMenu->addLineAtIndex(5 + insertion_index, title+" @{T8}/"+s, "chat_target_selected", "dyn"+s, "dyn"+s);
insertion_index++;
}
}
}
} }
// activate the menu // activate the menu
@ -2465,28 +2525,42 @@ class CHandlerChatTargetSelected : public IActionHandler
CChatTargetFilter &cf = fc->Filter; CChatTargetFilter &cf = fc->Filter;
// Team // Team
if (nlstricmp(sParams, "team") == 0) if (nlstricmp(sParams, "team") == 0)
{
cf.setTargetGroup(CChatGroup::team); cf.setTargetGroup(CChatGroup::team);
}
// Guild // Guild
if (nlstricmp(sParams, "guild") == 0) else if (nlstricmp(sParams, "guild") == 0)
{
cf.setTargetGroup(CChatGroup::guild); cf.setTargetGroup(CChatGroup::guild);
}
// Say // Say
if (nlstricmp(sParams, "say") == 0) else if (nlstricmp(sParams, "say") == 0)
{
cf.setTargetGroup(CChatGroup::say); cf.setTargetGroup(CChatGroup::say);
}
// Shout // Shout
if (nlstricmp(sParams, "shout") == 0) else if (nlstricmp(sParams, "shout") == 0)
{
cf.setTargetGroup(CChatGroup::shout); cf.setTargetGroup(CChatGroup::shout);
}
// Region // Region
if (nlstricmp(sParams, "region") == 0) else if (nlstricmp(sParams, "region") == 0)
{
cf.setTargetGroup(CChatGroup::region); cf.setTargetGroup(CChatGroup::region);
}
// Universe // Universe
if (nlstricmp(sParams, "universe") == 0) else if (nlstricmp(sParams, "universe") == 0)
{
cf.setTargetGroup(CChatGroup::universe); cf.setTargetGroup(CChatGroup::universe);
}
else
{
for (uint i = 0; i < CChatGroup::MaxDynChanPerPlayer; i++) {
if (nlstricmp(sParams, "dyn"+toString("%d", i)) == 0) {
cf.setTargetGroup(CChatGroup::dyn_chat, i);
}
}
}
// Case of user chat in grouped chat window // Case of user chat in grouped chat window
if (cw == PeopleInterraction.ChatGroup.Window) if (cw == PeopleInterraction.ChatGroup.Window)
@ -2593,6 +2667,25 @@ class CHandlerSelectChatSource : public IActionHandler
// select main chat menu // select main chat menu
menu = dynamic_cast<CGroupMenu *>(im->getElementFromId(MAIN_CHAT_SOURCE_MENU)); menu = dynamic_cast<CGroupMenu *>(im->getElementFromId(MAIN_CHAT_SOURCE_MENU));
// Remove all unused dynamic channels and set the names
for (uint i = 0; i < CChatGroup::MaxDynChanPerPlayer; i++)
{
string s = toString(i);
CViewTextMenu *pVTM = dynamic_cast<CViewTextMenu *>(im->getElementFromId(MAIN_CHAT_SOURCE_MENU+":tab:dyn"+s));
if (pVTM)
{
uint32 textId = im->getDbProp("SERVER:DYN_CHAT:CHANNEL"+s+":NAME")->getValue32();
bool active = (textId != 0);
pVTM->setActive(active);
if (active)
{
ucstring title;
STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId, title);
pVTM->setText("["+s+"] " + title);
}
}
}
// Menu with Filters // Menu with Filters
CChatGroupWindow *pWin = pi.getChatGroupWindow(); CChatGroupWindow *pWin = pi.getChatGroupWindow();
if (pWin->getTabIndex() == 5) // (5 == user) -> complete menu if (pWin->getTabIndex() == 5) // (5 == user) -> complete menu

@ -256,6 +256,8 @@ public:
void updateAllFreeTellerHeaders(); void updateAllFreeTellerHeaders();
void removeAllFreeTellers(); void removeAllFreeTellers();
static void displayTellInMainChat(const ucstring &playerName);
private: private:
// create various chat & people lists // create various chat & people lists
void createTeamChat(); void createTeamChat();

@ -185,6 +185,85 @@ sint CPeopleList::getIndexFromContainerID(const std::string &id) const
return -1; return -1;
} }
//==================================================================
bool CPeopleList::sortExByContactId(const CPeople& a, const CPeople& b)
{
return (a.ContactId < b.ContactId);
}
//==================================================================
bool CPeopleList::sortExByName(const CPeople& a, const CPeople& b)
{
ucstring name_a = toUpper(a.getName());
ucstring name_b = toUpper(b.getName());
return (name_a < name_b);
}
//==================================================================
bool CPeopleList::sortExByOnline(const CPeople& a, const CPeople& b)
{
ucstring name_a = toUpper(a.getName());
ucstring name_b = toUpper(b.getName());
// We want order: online/alpha, offworld/alpha, offline/alpha
if (a.Online == b.Online) {
return (name_a < name_b);
}
else {
// Compare online status
switch (a.Online) {
case ccs_online:
// a is > if a is online
return true;
break;
case ccs_online_abroad:
// a is > if b is offline
return (b.Online == ccs_offline);
break;
case ccs_offline:
default:
// b is always > if a is offline
return false;
break;
}
}
// Should not get here so just return something
return true;
}
//==================================================================
void CPeopleList::sortEx(TSortOrder order)
{
// remove all people from the father container
if (!_BaseContainer) return;
uint k;
for(k = 0; k < _Peoples.size(); ++k)
{
_BaseContainer->detachContainer(_Peoples[k].Container);
}
switch (order) {
default:
case sort_index:
std::sort(_Peoples.begin(), _Peoples.end(), CPeopleList::sortExByContactId);
break;
case sort_name:
std::sort(_Peoples.begin(), _Peoples.end(), CPeopleList::sortExByName);
break;
case sort_online:
std::sort(_Peoples.begin(), _Peoples.end(), CPeopleList::sortExByOnline);
break;
}
for(k = 0; k < _Peoples.size(); ++k)
{
_BaseContainer->attachContainer(_Peoples[k].Container);
}
}
//================================================================== //==================================================================
void CPeopleList::sort() void CPeopleList::sort()
{ {
@ -384,7 +463,14 @@ void CPeopleList::displayLocalPlayerTell(uint index,const ucstring &msg,uint num
nlwarning("<CPeopleList::displayLocalPlayerTell> can't get group list."); nlwarning("<CPeopleList::displayLocalPlayerTell> can't get group list.");
return; return;
} }
ucstring finalMsg = /*UserEntity->getName() + " " +*/ CI18N::get("youTell") + ": " + msg;
ucstring cur_time;
if (CInterfaceManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_TIMES_IN_CHAT_CB", false)->getValueBool())
{
cur_time = CInterfaceManager::getTimestampHuman();
}
ucstring csr = CHARACTER_TITLE::isCsrTitle(UserEntity->getTitleRaw()) ? "(CSR) " : "";
ucstring finalMsg = cur_time + csr + CI18N::get("youTell") + ": " + msg;
// display msg with good color // display msg with good color
CInterfaceProperty prop; CInterfaceProperty prop;
prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," "); prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," ");
@ -788,12 +874,19 @@ class CHandlerContactEntry : public IActionHandler
if(text.size() == 0) if(text.size() == 0)
return; return;
// Parse any tokens in the text
if ( ! CInterfaceManager::parseTokens(text))
{
pEB->setInputString (string(""));
return;
}
// is it a command ? // is it a command ?
if(text[0] == '/') if(text[0] == '/')
{ {
CChatWindow::_ChatWindowLaunchingCommand = NULL; // no CChatWindow instance there .. CChatWindow::_ChatWindowLaunchingCommand = NULL; // no CChatWindow instance there ..
// TODO : have NLMISC::ICommand accept unicode strings // TODO : have NLMISC::ICommand accept unicode strings
std::string str = text.toString().substr(1); std::string str = text.toUtf8().substr(1);
NLMISC::ICommand::execute( str, g_log ); NLMISC::ICommand::execute( str, g_log );
pEB->setInputString (string("")); pEB->setInputString (string(""));
return; return;
@ -804,6 +897,7 @@ class CHandlerContactEntry : public IActionHandler
CGroupContainer *gc = pCaller->getParent()->getEnclosingContainer(); CGroupContainer *gc = pCaller->getParent()->getEnclosingContainer();
// title gives the name of the player // title gives the name of the player
ucstring playerName = gc->getUCTitle(); ucstring playerName = gc->getUCTitle();
// Simply do a tell on the player // Simply do a tell on the player
ChatMngr.tell(playerName.toString(), text); ChatMngr.tell(playerName.toString(), text);
pEB->setInputString (string("")); pEB->setInputString (string(""));
@ -816,8 +910,9 @@ class CHandlerContactEntry : public IActionHandler
} }
// Retrieve name of the container in the list // Retrieve name of the container in the list
string str = gc->getId().substr(0,gc->getId().rfind('_')); string ui_interface_free_chat = "ui:interface:free_chat";
if (str != "ui:interface:free_chat") string str = gc->getId().substr(0, ui_interface_free_chat.length());
if (str != ui_interface_free_chat)
{ {
string str2 = gc->getId().substr(gc->getId().rfind('_')+1,gc->getId().size()); string str2 = gc->getId().substr(gc->getId().rfind('_')+1,gc->getId().size());
str = str.substr(0,str.rfind('_')); str = str.substr(0,str.rfind('_'));
@ -839,7 +934,13 @@ class CHandlerContactEntry : public IActionHandler
prop.readRGBA("UI:SAVE:CHAT:COLORS:SPEAKER"," "); prop.readRGBA("UI:SAVE:CHAT:COLORS:SPEAKER"," ");
ucstring final; ucstring final;
CChatWindow::encodeColorTag(prop.getRGBA(), final, false); CChatWindow::encodeColorTag(prop.getRGBA(), final, false);
final += CI18N::get("youTell")+": "; ucstring cur_time;
if (CInterfaceManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_TIMES_IN_CHAT_CB", false)->getValueBool())
{
cur_time = CInterfaceManager::getTimestampHuman();
}
ucstring csr = CHARACTER_TITLE::isCsrTitle(UserEntity->getTitleRaw()) ? "(CSR) " : "";
final += cur_time + csr + CI18N::get("youTell")+": ";
prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," "); prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," ");
CChatWindow::encodeColorTag(prop.getRGBA(), final, true); CChatWindow::encodeColorTag(prop.getRGBA(), final, true);
final += text; final += text;

@ -81,6 +81,18 @@ public:
ucstring getName(uint index) const; ucstring getName(uint index) const;
// Sort people alphabetically // Sort people alphabetically
void sort(); void sort();
enum TSortOrder
{
sort_index = 0,
START_SORT_ORDER = sort_index,
sort_name,
sort_online,
END_SORT_ORDER
};
void sortEx(TSortOrder order);
/** Add a people to the list, and returns its index or -1 if the creation failed /** Add a people to the list, and returns its index or -1 if the creation failed
* If this is a team mate, tells its index so that ic can be bound to the database in the right location * If this is a team mate, tells its index so that ic can be bound to the database in the right location
*/ */
@ -165,6 +177,10 @@ private:
void updatePeopleMenu(uint index); void updatePeopleMenu(uint index);
// from CGroupContainer::IChildrenObs // from CGroupContainer::IChildrenObs
virtual void childrenMoved(uint srcIndex, uint destIndex, CGroupContainer *children); virtual void childrenMoved(uint srcIndex, uint destIndex, CGroupContainer *children);
static bool sortExByContactId(const CPeople& a, const CPeople& b);
static bool sortExByName(const CPeople& a, const CPeople& b);
static bool sortExByOnline(const CPeople& a, const CPeople& b);
}; };
#endif #endif

@ -224,7 +224,7 @@ void CViewBitmap::setTexture(const std::string & TxName)
// CInterfaceManager *pIM = CInterfaceManager::getInstance(); // CInterfaceManager *pIM = CInterfaceManager::getInstance();
// CViewRenderer &rVR = pIM->getViewRenderer(); // CViewRenderer &rVR = pIM->getViewRenderer();
_TextureId.setTexture (TxName.c_str (), _TxtOffsetX, _TxtOffsetY, _TxtWidth, _TxtHeight); _TextureId.setTexture (TxName.c_str (), _TxtOffsetX, _TxtOffsetY, _TxtWidth, _TxtHeight, false);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

@ -344,16 +344,22 @@ void CLightCycleManager::setHour(float hour, const CWeatherManagerClient &wm, NL
} }
_Touched = false; _Touched = false;
// Set the Sun color
CRGBA color; // Set the Sun color only if not indoor
color.add(_LastDiffuse, lightningColor); if (ContinentMngr.cur()->Indoor)
Scene->setLightGroupColor (LightGroupDay, color); {
Scene->setSunAmbient(CRGBA(150, 150, 150, 255));
// Set the Night color }
float nightLevel = _LightLevel*255.f; else
clamp (nightLevel, 0, 255); {
color.set ((uint8)nightLevel, (uint8)nightLevel, (uint8)nightLevel); CRGBA color;
Scene->setLightGroupColor (LightGroupNight, color); color.add(_LastDiffuse, lightningColor);
Scene->setLightGroupColor (LightGroupDay, color);
float nightLevel = _LightLevel*255.f;
clamp (nightLevel, 0, 255);
color.set ((uint8)nightLevel, (uint8)nightLevel, (uint8)nightLevel);
Scene->setLightGroupColor (LightGroupNight, color);
}
if (Landscape) if (Landscape)
{ {

@ -606,7 +606,7 @@ static CInterfaceChatDisplayer InterfaceChatDisplayer;
void CInterfaceChatDisplayer::colorizeSender(ucstring &text, const ucstring &senderName, CRGBA baseColor) void CInterfaceChatDisplayer::colorizeSender(ucstring &text, const ucstring &senderName, CRGBA baseColor)
{ {
// find the sender/text separator to put color tags // find the sender/text separator to put color tags
ucstring::size_type pos = text.find(ucchar(':')); ucstring::size_type pos = senderName.length() - 1;
if (pos != ucstring::npos) if (pos != ucstring::npos)
{ {
ucstring str; ucstring str;
@ -635,14 +635,17 @@ void CInterfaceChatDisplayer::displayChat(TDataSetIndex compressedSenderIndex, c
bool bubbleWanted = true; bool bubbleWanted = true;
// Subtract rawMessage from ucstr so that the 'sender' part remains.
ucstring senderPart = ucstr.luabind_substr(0, ucstr.length() - rawMessage.length());
// search a "{no_bubble}" tag // search a "{no_bubble}" tag
{ {
ucstring::size_type index = finalString.find (ucstring("{no_bubble}")); ucstring::size_type index = finalString.find(ucstring("{no_bubble}"));
const size_t tokenSize= 11; // strlen de "{no_bubble}" const size_t tokenSize= 11; // length of "{no_bubble}"
if (index != ucstring::npos) if (index != ucstring::npos)
{ {
bubbleWanted = false; bubbleWanted = false;
finalString = finalString.substr (0, index) + finalString.substr(index+tokenSize,finalString.size()); finalString = finalString.luabind_substr(0, index) + finalString.substr(index+tokenSize,finalString.size());
} }
} }
@ -654,9 +657,9 @@ void CInterfaceChatDisplayer::displayChat(TDataSetIndex compressedSenderIndex, c
// Remove all {break} // Remove all {break}
for(;;) for(;;)
{ {
ucstring::size_type index = finalString.find (ucstring("{break}")); ucstring::size_type index = finalString.find(ucstring("{break}"));
if (index == ucstring::npos) break; if (index == ucstring::npos) break;
finalString = finalString.substr (0, index) + finalString.substr(index+7,finalString.size()); finalString = finalString.luabind_substr(0, index) + finalString.luabind_substr(index+7,finalString.size());
} }
// select DB // select DB
@ -696,7 +699,15 @@ void CInterfaceChatDisplayer::displayChat(TDataSetIndex compressedSenderIndex, c
if (mode != CChatGroup::system) if (mode != CChatGroup::system)
{ {
// find the sender/text separator to put color tags // find the sender/text separator to put color tags
colorizeSender(finalString, senderName, col); if (senderPart.empty() && stringCategory == "emt")
{
size_t pos = finalString.find(ucstring(": "), 0);
if (pos != ucstring::npos)
{
senderPart = finalString.luabind_substr(0, pos + 2);
}
}
colorizeSender(finalString, senderPart, col);
} }
// play associated fx if any // play associated fx if any
@ -839,10 +850,15 @@ void CInterfaceChatDisplayer::displayTell(/*TDataSetIndex senderIndex, */const u
prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," "); prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," ");
bool windowVisible; bool windowVisible;
colorizeSender(finalString, senderName, prop.getRGBA());
ucstring goodSenderName = CEntityCL::removeTitleAndShardFromName(senderName); ucstring goodSenderName = CEntityCL::removeTitleAndShardFromName(senderName);
// The sender part is up to and including the first ":" after the goodSenderName
ucstring::size_type pos = finalString.find(goodSenderName);
pos = finalString.find(':', pos);
pos = finalString.find(' ', pos);
ucstring senderPart = finalString.substr(0, pos+1);
colorizeSender(finalString, senderPart, prop.getRGBA());
PeopleInterraction.ChatInput.Tell.displayTellMessage(/*senderIndex, */finalString, goodSenderName, prop.getRGBA(), 2, &windowVisible); PeopleInterraction.ChatInput.Tell.displayTellMessage(/*senderIndex, */finalString, goodSenderName, prop.getRGBA(), 2, &windowVisible);
// Open the free teller window // Open the free teller window
@ -1764,6 +1780,14 @@ void impulseTeamContactStatus(NLMISC::CBitMemStream &impulse)
// 0<=FriendList (actually ignore list does not show online state) // 0<=FriendList (actually ignore list does not show online state)
PeopleInterraction.updateContactInList(contactId, online, 0); PeopleInterraction.updateContactInList(contactId, online, 0);
// Resort the contact list if needed
CInterfaceManager* pIM= CInterfaceManager::getInstance();
CPeopleList::TSortOrder order = (CPeopleList::TSortOrder)(pIM->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32());
if (order == CPeopleList::sort_online)
{
PeopleInterraction.FriendList.sortEx(order);
}
}// impulseTeamContactStatus // }// impulseTeamContactStatus //
@ -3069,7 +3093,7 @@ void impulseItemCloseRoomInventory(NLMISC::CBitMemStream &impulse)
void impulseUserBars(NLMISC::CBitMemStream &impulse) void impulseUserBars(NLMISC::CBitMemStream &impulse)
{ {
uint8 msgNumber; uint8 msgNumber;
sint16 hp, sap, sta, focus; sint32 hp, sap, sta, focus;
impulse.serial(msgNumber); impulse.serial(msgNumber);
impulse.serial(hp); impulse.serial(hp);
impulse.serial(sap); impulse.serial(sap);
@ -3164,7 +3188,6 @@ private:
if(contentStr.size()>=6 && contentStr[0]=='W' && contentStr[1]=='E' && contentStr[2]=='B' if(contentStr.size()>=6 && contentStr[0]=='W' && contentStr[1]=='E' && contentStr[2]=='B'
&& contentStr[3]==' ' && contentStr[4]==':' && contentStr[5]==' ' ) && contentStr[3]==' ' && contentStr[4]==':' && contentStr[5]==' ' )
{ {
ucstring web_app;
uint i; uint i;
const uint digitStart= 6; const uint digitStart= 6;
const uint digitMaxEnd= (uint)contentStr.size(); const uint digitMaxEnd= (uint)contentStr.size();
@ -3176,18 +3199,17 @@ private:
if(contentStr[i] == ' ') if(contentStr[i] == ' ')
break; break;
} }
nlinfo("%d", i);
if(i != digitMaxEnd) if(i != digitMaxEnd)
web_app = contentStr.substr(digitStart, i-digitStart); {
ucstring web_app = contentStr.substr(digitStart, i-digitStart);
contentStr = ucstring("http://atys.ryzom.com/start/")+web_app+ucstring(".php?")+contentStr.substr(i+1);
}
else else
{ {
web_app = ucstring("index"); contentStr = "";
i = digitStart; i = digitStart;
nlinfo("no app");
} }
contentStr = ucstring("http://atys.ryzom.com/start/")+web_app+ucstring(".php?")+contentStr.substr(i+1); }
nlinfo("contentStr = %s", contentStr.toString().c_str());
}
else if(contentStr.size()>=5 && contentStr[0]=='@' && contentStr[1]=='{' && contentStr[2]=='W') else if(contentStr.size()>=5 && contentStr[0]=='@' && contentStr[1]=='{' && contentStr[2]=='W')
{ {
uint i; uint i;
@ -3218,12 +3240,19 @@ private:
{ {
CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(pIM->getElementFromId("ui:interface:webig")); CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(pIM->getElementFromId("ui:interface:webig"));
pGC->setActive(true);
string url = contentStr.toString(); if (contentStr.empty())
addWebIGParams(url); {
groupHtml->browse(url.c_str()); pGC->setActive(false);
pIM->setTopWindow(pGC); }
else
{
pGC->setActive(true);
string url = contentStr.toString();
addWebIGParams(url);
groupHtml->browse(url.c_str());
pIM->setTopWindow(pGC);
}
} }
} }
else else

@ -227,15 +227,21 @@ bool CPlayerCL::isEnemy () const
} }
// Faction // Faction
if( getPvpMode()&PVP_MODE::PvpFactionFlagged && if ((getPvpMode()&PVP_MODE::PvpFaction || getPvpMode()&PVP_MODE::PvpFactionFlagged) &&
(UserEntity->getPvpMode()&PVP_MODE::PvpFaction || UserEntity->getPvpMode()&PVP_MODE::PvpFactionFlagged) ) (UserEntity->getPvpMode()&PVP_MODE::PvpFaction || UserEntity->getPvpMode()&PVP_MODE::PvpFactionFlagged))
{ {
if( CFactionWarManager::getInstance()->areFactionsInWar(getPvpClan(),UserEntity->getPvpClan()) ) // Check if is not ally
if (!isInTeam() && !isInGuild())
{ {
return true; // Check for each Clan if is in opposition
for (uint8 i = 0; i < PVP_CLAN::NbClans; i++)
{
if ((isPvpEnnemy(i) && UserEntity->isPvpAlly(i)) || (isPvpAlly(i) && UserEntity->isPvpEnnemy(i)))
return true;
}
} }
} }
return false; return false;
} // isEnemy // } // isEnemy //
@ -293,15 +299,24 @@ bool CPlayerCL::isAlly() const
} }
// Faction // Faction
if( getPvpMode()&PVP_MODE::PvpFactionFlagged && if ((getPvpMode()&PVP_MODE::PvpFaction || getPvpMode()&PVP_MODE::PvpFactionFlagged) &&
(UserEntity->getPvpMode()&PVP_MODE::PvpFaction || UserEntity->getPvpMode()&PVP_MODE::PvpFactionFlagged)) (UserEntity->getPvpMode()&PVP_MODE::PvpFaction || UserEntity->getPvpMode()&PVP_MODE::PvpFactionFlagged))
{ {
if( getPvpClan()!=PVP_CLAN::Neutral && UserEntity->getPvpClan()!=PVP_CLAN::Neutral ) if (isInTeam() && isInGuild())
return true;
// Check for each Clan if is in opposition
for (uint8 i = 0; i < PVP_CLAN::NbClans; i++)
{ {
if( getPvpClan()==UserEntity->getPvpClan() ) if ((isPvpEnnemy(i) && UserEntity->isPvpAlly(i)) || (isPvpAlly(i) && UserEntity->isPvpEnnemy(i)))
{ return false;
}
// Check for each Clan if is in same clan
for (uint8 i = 0; i < PVP_CLAN::NbClans; i++)
{
if ((isPvpEnnemy(i) && UserEntity->isPvpEnnemy(i)) || (isPvpAlly(i) && UserEntity->isPvpAlly(i)))
return true; return true;
}
} }
} }
@ -365,19 +380,19 @@ bool CPlayerCL::isNeutralPVP() const
return true; return true;
} }
// Faction if ((getPvpMode()&PVP_MODE::PvpFaction || getPvpMode()&PVP_MODE::PvpFactionFlagged) &&
if( getPvpMode()&PVP_MODE::PvpFactionFlagged ) (UserEntity->getPvpMode()&PVP_MODE::PvpFaction || UserEntity->getPvpMode()&PVP_MODE::PvpFactionFlagged))
{ {
// if only target is in faction pvp // Check for each Clan if is in opposition or same
if( !(UserEntity->getPvpMode()&PVP_MODE::PvpFaction || UserEntity->getPvpMode()&PVP_MODE::PvpFactionFlagged) ) for (uint8 i = 0; i < PVP_CLAN::NbClans; i++)
{ {
return true; if ((isPvpEnnemy(i) && UserEntity->isPvpAlly(i)) ||
} (isPvpAlly(i) && UserEntity->isPvpEnnemy(i)) ||
// else if factions not in war (isPvpEnnemy(i) && UserEntity->isPvpEnnemy(i)) ||
if( CFactionWarManager::getInstance()->areFactionsInWar(getPvpClan(),UserEntity->getPvpClan())==false ) (isPvpAlly(i) && UserEntity->isPvpAlly(i)))
{ return false;
return true;
} }
return true;
} }
return false; return false;

@ -198,6 +198,16 @@ CUserEntity::~CUserEntity()
_MountSpeeds.release(); _MountSpeeds.release();
CInterfaceManager *pIM = CInterfaceManager::getInstance(); CInterfaceManager *pIM = CInterfaceManager::getInstance();
{
CCDBNodeLeaf *node = pIM->getDbProp("SERVER:USER:IS_INVISIBLE", false);
if (node)
{
ICDBNode::CTextId textId;
node->removeObserver(&_InvisibleObs, textId);
}
}
for(uint i=0;i<EGSPD::CSPType::EndSPType;i++) for(uint i=0;i<EGSPD::CSPType::EndSPType;i++)
{ {
CCDBNodeLeaf *node= pIM->getDbProp(toString("SERVER:USER:SKILL_POINTS_%d:VALUE", i), false); CCDBNodeLeaf *node= pIM->getDbProp(toString("SERVER:USER:SKILL_POINTS_%d:VALUE", i), false);
@ -347,8 +357,17 @@ bool CUserEntity::build(const CEntitySheet *sheet) // virtual
// Rebuild interface // Rebuild interface
buildInSceneInterface (); buildInSceneInterface ();
// Add an observer on skill points // Add observer on invisible property
CInterfaceManager *pIM = CInterfaceManager::getInstance(); CInterfaceManager *pIM = CInterfaceManager::getInstance();
{
CCDBNodeLeaf *node = pIM->getDbProp("SERVER:USER:IS_INVISIBLE", false);
if (node) {
ICDBNode::CTextId textId;
node->addObserver(&_InvisibleObs, textId);
}
}
// Add an observer on skill points
for(uint i=0;i<EGSPD::CSPType::EndSPType;i++) for(uint i=0;i<EGSPD::CSPType::EndSPType;i++)
{ {
_SkillPointObs[i].SpType= i; _SkillPointObs[i].SpType= i;
@ -3664,6 +3683,11 @@ void CUserEntity::load() // virtual
//--------------------------------------------------- //---------------------------------------------------
void CUserEntity::CInvisibleObserver::update(ICDBNode* node)
{
UserEntity->buildInSceneInterface();
}
//--------------------------------------------------- //---------------------------------------------------
void CUserEntity::CSkillPointsObserver::update(ICDBNode* node ) void CUserEntity::CSkillPointsObserver::update(ICDBNode* node )
{ {

@ -589,7 +589,12 @@ protected:
}; };
CSkillPointsObserver _SkillPointObs[EGSPD::CSPType::EndSPType]; CSkillPointsObserver _SkillPointObs[EGSPD::CSPType::EndSPType];
class CInvisibleObserver : public ICDBNode::IPropertyObserver
{
public :
virtual void update(ICDBNode* node);
};
CInvisibleObserver _InvisibleObs;
/// Fame observer /// Fame observer
class CFameObserver : public ICDBNode::IPropertyObserver class CFameObserver : public ICDBNode::IPropertyObserver

Loading…
Cancel
Save