Merge branch 'atys' into ryzom/ark/features

ryzom/ark/features
Nuno 4 years ago
commit 7964a42927

@ -27,6 +27,7 @@
#include "nel/gui/ctrl_button.h"
#include "nel/gui/group_table.h"
#include "nel/gui/html_element.h"
#include "nel/gui/html_parser.h"
#include "nel/gui/css_style.h"
// forward declaration
@ -115,6 +116,9 @@ namespace NLGUI
// Browse error
void browseError (const char *msg);
// Error message with html content
void browseErrorHtml(const std::string &html);
bool isBrowsing();
// Update coords
@ -375,7 +379,9 @@ namespace NLGUI
// true if renderer is waiting for css files to finish downloading (link rel=stylesheet)
bool _WaitingForStylesheet;
// list of css file urls that are queued up for download
std::vector<std::string> _StylesheetQueue;
std::vector<CHtmlParser::StyleLink> _StylesheetQueue;
// <style> and downloaded <link rel=stylesheet> elements
std::vector<std::string> _HtmlStyles;
// Valid base href was found
bool _IgnoreBaseUrlTag;
@ -854,6 +860,7 @@ namespace NLGUI
CCurlWWWData *data;
std::string url;
std::string dest;
std::string tmpdest;
std::string luaScript;
std::string md5sum;
TDataType type;
@ -889,7 +896,7 @@ namespace NLGUI
std::string localBnpName(const std::string &url);
// add css file from <link href=".." rel="stylesheet"> to download queue
void addStylesheetDownload(std::vector<std::string> links);
void addStylesheetDownload(std::vector<CHtmlParser::StyleLink> links);
// stop all curl downalods (html and data)
void releaseDownloads();

@ -54,6 +54,8 @@ namespace NLGUI
Right
};
enum TTextAlign { AlignLeft = 0, AlignCenter, AlignRight, AlignJustify };
///constructor
CGroupParagraph(const TCtorParam &param);
@ -97,6 +99,8 @@ namespace NLGUI
// the same, but with id taken from the database
void addTextChildID (const std::string &dbPath, bool multiLine = true);
void setTextAlign(const TTextAlign align) { _TextAlign = align; }
protected:
void delChild (CViewBase* child);
@ -270,6 +274,9 @@ namespace NLGUI
// (the element drawn are stored in _views, _contrlos or _childrengroups of cinterfacegroup
std::vector<CElementInfo> _Elements;
// Horizontal align for elements
TTextAlign _TextAlign;
// Last parent width
sint32 _LastW;

@ -31,14 +31,23 @@ namespace NLGUI
class CHtmlParser
{
public:
// <link rel=stylesheet>
struct StyleLink
{
uint Index;
std::string Url;
StyleLink(uint i, const std::string &url) : Index(i), Url(url)
{ }
};
bool parseHtml(std::string htmlString) const;
// parse html string into DOM, extract <style> tags into styleString, <link stylesheet> urls into links
void getDOM(std::string htmlString, CHtmlElement &parent, std::string &styleString, std::vector<std::string> &links) const;
// parse html string into DOM, extract <style> and <link stylesheet> urls
void getDOM(std::string htmlString, CHtmlElement &parent, std::vector<std::string> &styles, std::vector<StyleLink> &links) const;
private:
// iterate over libxml html tree, build DOM, and join all <style> tags together
void parseNode(xmlNode *a_node, CHtmlElement &parent, std::string &styleString, std::vector<std::string> &links) const;
// iterate over libxml html tree, build DOM
void parseNode(xmlNode *a_node, CHtmlElement &parent, std::vector<std::string> &styles, std::vector<StyleLink> &links) const;
// read <style> tag and add its content to styleString
void parseStyle(xmlNode *a_node, std::string &styleString) const;

@ -246,9 +246,10 @@ inline bool fromString(const std::string &str, sint64 &val) { bool ret = sscanf(
inline bool fromString(const std::string &str, float &val) { bool ret = sscanf(str.c_str(), "%f", &val) == 1; if (!ret) val = 0.0f; return ret; }
inline bool fromString(const std::string &str, double &val) { bool ret = sscanf(str.c_str(), "%lf", &val) == 1; if (!ret) val = 0.0; return ret; }
// Fast string to bool, reliably defined for strings starting with 0, 1, t, T, f, F, y, Y, n, N, anything else is undefined.
// (str[0] == '1' || (str[0] & 0xD2) == 0x50)
// - Kaetemi
/// Fast string to bool, reliably defined for strings starting with 0, 1, t, T, f, F, y, Y, n, N, and empty strings, anything else is undefined.
/// - Kaetemi
inline bool toBool(const char *str) { return str[0] == '1' || (str[0] & 0xD2) == 0x50; }
inline bool toBool(const std::string &str) { return toBool(str.c_str()); } // Safe because first byte may be null
bool fromString(const std::string &str, bool &val);

@ -0,0 +1,74 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef XML_MACROS_H
#define XML_MACROS_H
//
// xmlNodePtr cur;
// CXMLAutoPtr prop;
//
// sint i;
// XML_READ_SINT(cur, "prop_name", i, -1);
//
#define XML_READ_UINT(node, name, var, def) { \
uint tmp; \
prop = (char *) xmlGetProp(node, (xmlChar*)name); \
if (prop && fromString((const char*)prop, tmp)) \
var = tmp; \
else \
var = def; \
}
#define XML_READ_SINT(node, name, var, def) { \
sint tmp; \
prop = (char *) xmlGetProp(node, (xmlChar*)name); \
if (prop && fromString((const char*)prop, tmp)) \
var = tmp; \
else \
var = def; \
}
#define XML_READ_BOOL(node, name, var, def) { \
prop = (char *) xmlGetProp(node, (xmlChar*)name); \
if (prop) \
var = NLMISC::toBool((const char*)prop); \
else \
var = def; \
}
#define XML_READ_COLOR(node, name, var, def) { \
NLMISC::CRGBA tmp; \
prop = (char *) xmlGetProp(node, (xmlChar*)name); \
if (prop && fromString((const char*)prop, tmp)) \
var = tmp; \
else \
var = def; \
}
#define XML_READ_STRING(node, name, var, def) { \
prop = (char *) xmlGetProp(node, (xmlChar*)name); \
if (prop) \
var = (const char*)prop; \
else \
var = def; \
}
#endif // XML_MACROS_H

@ -524,18 +524,19 @@ namespace NLGUI
return false;
}
string tmpdest = download.dest + ".tmp";
// use browser Id so that two browsers would not use same temp file
download.tmpdest = localImageName(_Id + download.dest) + ".tmp";
// erase the tmp file if exists
if (CFile::fileExists(tmpdest))
if (CFile::fileExists(download.tmpdest))
{
CFile::deleteFile(tmpdest);
CFile::deleteFile(download.tmpdest);
}
FILE *fp = nlfopen (tmpdest, "wb");
FILE *fp = nlfopen (download.tmpdest, "wb");
if (fp == NULL)
{
nlwarning("Can't open file '%s' for writing: code=%d '%s'", tmpdest.c_str (), errno, strerror(errno));
nlwarning("Can't open file '%s' for writing: code=%d '%s'", download.tmpdest.c_str (), errno, strerror(errno));
return false;
}
@ -543,7 +544,7 @@ namespace NLGUI
if (!curl)
{
fclose(fp);
CFile::deleteFile(tmpdest);
CFile::deleteFile(download.tmpdest);
nlwarning("Creating cURL handle failed, unable to download '%s'", download.url.c_str());
return false;
@ -607,54 +608,57 @@ namespace NLGUI
void CGroupHTML::finishCurlDownload(const CDataDownload &download)
{
std::string tmpfile = download.dest + ".tmp";
if (download.type == ImgType)
{
// there is race condition if two browser instances are downloading same file
// second instance deletes first tmpfile and creates new file for itself.
if (CFile::getFileSize(tmpfile) > 0)
if (CFile::fileExists(download.tmpdest) && CFile::getFileSize(download.tmpdest) > 0)
{
try
{
// verify that image is not corrupted
uint32 w, h;
CBitmap::loadSize(tmpfile, w, h);
CBitmap::loadSize(download.tmpdest, w, h);
if (w != 0 && h != 0)
{
// if not tmpfile, then img is already in cache
if (CFile::fileExists(tmpfile))
{
if (CFile::fileExists(download.dest))
{
CFile::deleteFile(download.dest);
}
// to reload image on page, the easiest seems to be changing texture
// to temp file temporarily. that forces driver to reload texture from disk
// ITexture::touch() seem not to do this.
// cache was updated, first set texture as temp file
for(uint i = 0; i < download.imgs.size(); i++)
{
setImage(download.imgs[i].Image, tmpfile, download.imgs[i].Type);
setImageSize(download.imgs[i].Image, download.imgs[i].Style);
}
CFile::moveFile(download.dest, tmpfile);
}
if (CFile::fileExists(download.dest))
CFile::deleteFile(download.dest);
// to reload image on page, the easiest seems to be changing texture
// to temp file temporarily. that forces driver to reload texture from disk
// ITexture::touch() seem not to do this.
// cache was updated, first set texture as temp file
for(uint i = 0; i < download.imgs.size(); i++)
{
setImage(download.imgs[i].Image, download.dest, download.imgs[i].Type);
setImage(download.imgs[i].Image, download.tmpdest, download.imgs[i].Type);
setImageSize(download.imgs[i].Image, download.imgs[i].Style);
}
CFile::moveFile(download.dest, download.tmpdest);
}
}
catch(const NLMISC::Exception &e)
{
// exception message has .tmp file name, so keep it for further analysis
nlwarning("Invalid image (%s): %s", download.url.c_str(), e.what());
nlwarning("Invalid image (%s) from url (%s): %s", download.tmpdest.c_str(), download.url.c_str(), e.what());
}
}
if (CFile::fileExists(download.dest) && CFile::getFileSize(download.dest) > 0)
{
try
{
// verify that image is not corrupted
uint32 w, h;
CBitmap::loadSize(download.dest, w, h);
if (w != 0 && h != 0)
for(uint i = 0; i < download.imgs.size(); i++)
{
setImage(download.imgs[i].Image, download.dest, download.imgs[i].Type);
setImageSize(download.imgs[i].Image, download.imgs[i].Style);
}
}
catch(const NLMISC::Exception &e)
{
nlwarning("Invalid image (%s) from url (%s): %s", download.dest.c_str(), download.url.c_str(), e.what());
}
}
@ -663,13 +667,13 @@ namespace NLGUI
if (download.type == StylesheetType)
{
if (CFile::fileExists(tmpfile))
if (CFile::fileExists(download.tmpdest))
{
if (CFile::fileExists(download.dest))
{
CFile::deleteFile(download.dest);
}
CFile::moveFile(download.dest, tmpfile);
CFile::moveFile(download.dest, download.tmpdest);
}
cssDownloadFinished(download.url, download.dest);
@ -680,20 +684,20 @@ namespace NLGUI
{
bool verified = false;
// no tmpfile if file was already in cache
if (CFile::fileExists(tmpfile))
if (CFile::fileExists(download.tmpdest))
{
verified = download.md5sum.empty() || (download.md5sum != getMD5(tmpfile).toString());
verified = download.md5sum.empty() || (download.md5sum != getMD5(download.tmpdest).toString());
if (verified)
{
if (CFile::fileExists(download.dest))
{
CFile::deleteFile(download.dest);
}
CFile::moveFile(download.dest, tmpfile);
CFile::moveFile(download.dest, download.tmpdest);
}
else
{
CFile::deleteFile(tmpfile);
CFile::deleteFile(download.tmpdest);
}
}
else if (CFile::fileExists(download.dest))
@ -745,7 +749,7 @@ namespace NLGUI
if (type != OverImage)
{
std::string temp = dest;
if (!CFile::fileExists(temp))
if (!CFile::fileExists(temp) || CFile::getFileSize(temp) == 0)
{
temp = placeholder;
}
@ -857,21 +861,16 @@ namespace NLGUI
CFile::createDirectory( pathName );
}
void CGroupHTML::addStylesheetDownload(std::vector<std::string> links)
void CGroupHTML::addStylesheetDownload(const std::vector<CHtmlParser::StyleLink> links)
{
for(uint i = 0; i < links.size(); ++i)
{
std::string url = getAbsoluteUrl(links[i]);
std::string local = localImageName(url);
_StylesheetQueue.push_back(links[i]);
std::string url = getAbsoluteUrl(links[i].Url);
_StylesheetQueue.back().Url = url;
// insert only if url not already downloading
std::vector<std::string>::const_iterator it = std::find(_StylesheetQueue.begin(), _StylesheetQueue.end(), url);
if (it == _StylesheetQueue.end())
{
_StylesheetQueue.push_back(url);
// push to the front of the queue
Curls.push_front(CDataDownload(url, local, StylesheetType, NULL, "", ""));
}
// push to the front of the queue
Curls.push_front(CDataDownload(url, localImageName(url), StylesheetType, NULL, "", ""));
}
pumpCurlQueue();
}
@ -971,9 +970,9 @@ namespace NLGUI
{
fclose(it->fp);
if (CFile::fileExists(it->dest + ".tmp"))
if (CFile::fileExists(it->tmpdest))
{
CFile::deleteFile(it->dest + ".tmp");
CFile::deleteFile(it->tmpdest);
}
}
}
@ -2549,6 +2548,17 @@ namespace NLGUI
newParagraph->setResizeFromChildH(true);
newParagraph->setMarginLeft(getIndent());
if (!_Style.Current.TextAlign.empty())
{
if (_Style.Current.TextAlign == "left")
newParagraph->setTextAlign(CGroupParagraph::AlignLeft);
else if (_Style.Current.TextAlign == "center")
newParagraph->setTextAlign(CGroupParagraph::AlignCenter);
else if (_Style.Current.TextAlign == "right")
newParagraph->setTextAlign(CGroupParagraph::AlignRight);
else if (_Style.Current.TextAlign == "justify")
newParagraph->setTextAlign(CGroupParagraph::AlignJustify);
}
// Add to the group
addHtmlGroup (newParagraph, beginSpace);
@ -2642,6 +2652,17 @@ namespace NLGUI
invalidateCoords();
}
void CGroupHTML::browseErrorHtml(const std::string &html)
{
releaseDownloads();
removeContent();
renderHtmlString(html);
updateRefreshButton();
invalidateCoords();
}
// ***************************************************************************
bool CGroupHTML::isBrowsing()
@ -3964,11 +3985,22 @@ namespace NLGUI
{
if (!success)
{
CUrlParser uri(_CurlWWW->Url);
// potentially unwanted chars
std::string url = _CurlWWW->Url;
url = strFindReplaceAll(url, string("<"), string("%3C"));
url = strFindReplaceAll(url, string(">"), string("%3E"));
url = strFindReplaceAll(url, string("\""), string("%22"));
url = strFindReplaceAll(url, string("'"), string("%27"));
std::string err;
err = "Connection failed with cURL error: ";
err = "<html><head><title>cURL error</title></head><body>";
err += "<h1>Connection failed with cURL error</h1>";
err += error;
err += "\nURL '" + _CurlWWW->Url + "'";
browseError(err.c_str());
err += "<hr>(" + uri.scheme + "://" + uri.host + ") <a href=\"" + url + "\">reload</a>";
err += "</body></html>";
browseErrorHtml(err);
return;
}
@ -4080,10 +4112,9 @@ namespace NLGUI
obj.LastModified = data.data->getLastModified();
CHttpCache::getInstance()->store(data.dest, obj);
std::string tmpfile = data.dest + ".tmp";
if (code == 304 && CFile::fileExists(tmpfile))
if (code == 304 && CFile::fileExists(data.tmpdest))
{
CFile::deleteFile(tmpfile);
CFile::deleteFile(data.tmpdest);
}
}
else if ((code >= 301 && code <= 303) || code == 307 || code == 308)
@ -4111,10 +4142,9 @@ namespace NLGUI
LOG_DL("Redirect '%s'", location.c_str());
// no finished callback called, so cleanup old temp
std::string tmpfile = data.dest + ".tmp";
if (CFile::fileExists(tmpfile))
if (CFile::fileExists(data.tmpdest))
{
CFile::deleteFile(tmpfile);
CFile::deleteFile(data.tmpdest);
}
return;
}
@ -4187,19 +4217,28 @@ namespace NLGUI
// ***************************************************************************
void CGroupHTML::cssDownloadFinished(const std::string &url, const std::string &local)
{
// remove file from download queue
std::vector<std::string>::iterator it = std::find(_StylesheetQueue.begin(), _StylesheetQueue.end(), url);
if (it != _StylesheetQueue.end())
for(std::vector<CHtmlParser::StyleLink>::iterator it = _StylesheetQueue.begin();
it != _StylesheetQueue.end(); ++it)
{
_StylesheetQueue.erase(it);
}
if (it->Url == url)
{
// read downloaded file into HtmlStyles
if (CFile::fileExists(local) && it->Index < _HtmlStyles.size())
{
CIFile in;
if (in.open(local))
{
if (!in.readAll(_HtmlStyles[it->Index]))
{
nlwarning("Failed to read downloaded css file(%s), url(%s)", local.c_str(), url.c_str());
}
}
}
if (!CFile::fileExists(local))
{
return;
_StylesheetQueue.erase(it);
break;
}
}
parseStylesheetFile(local);
}
void CGroupHTML::renderDocument()
@ -4217,6 +4256,16 @@ namespace NLGUI
beginBuild();
removeContent();
// process all <style> and <link rel=stylesheet> elements
for(uint i = 0; i < _HtmlStyles.size(); ++i)
{
if (!_HtmlStyles[i].empty())
{
_Style.parseStylesheet(_HtmlStyles[i]);
}
}
_HtmlStyles.clear();
std::list<CHtmlElement>::iterator it = _HtmlDOM.Children.begin();
while(it != _HtmlDOM.Children.end())
{
@ -4826,9 +4875,6 @@ namespace NLGUI
// ***************************************************************************
bool CGroupHTML::parseHtml(const std::string &htmlString)
{
std::vector<std::string> links;
std::string styleString;
CHtmlElement *parsedDOM;
if (_CurrentHTMLElement == NULL)
{
@ -4841,16 +4887,28 @@ namespace NLGUI
parsedDOM = _CurrentHTMLElement;
}
std::vector<CHtmlParser::StyleLink> links;
CHtmlParser parser;
parser.getDOM(htmlString, *parsedDOM, styleString, links);
parser.getDOM(htmlString, *parsedDOM, _HtmlStyles, links);
if (!styleString.empty())
// <link> elements inserted from lua::parseHtml are ignored
if (_CurrentHTMLElement == NULL && !links.empty())
{
_Style.parseStylesheet(styleString);
addStylesheetDownload(links);
}
if (!links.empty())
else if (_CurrentHTMLElement != NULL)
{
addStylesheetDownload(links);
// Called from active element (lua)
// <style> order is not preserved as document is already being rendered
for(uint i = 0; i < _HtmlStyles.size(); ++i)
{
if (!_HtmlStyles[i].empty())
{
_Style.parseStylesheet(_HtmlStyles[i]);
}
}
_HtmlStyles.clear();
}
// this should rarely fail as first element should be <html>
@ -4861,7 +4919,7 @@ namespace NLGUI
{
if (it->Type == CHtmlElement::ELEMENT_NODE && it->Value == "html")
{
// more newly parsed childs from <body> into siblings
// move newly parsed childs from <body> into siblings
if (_CurrentHTMLElement) {
std::list<CHtmlElement>::iterator it2 = it->Children.begin();
while(it2 != it->Children.end())
@ -5358,6 +5416,11 @@ namespace NLGUI
cellParams.Align = CGroupCell::Center;
else if (align == "right")
cellParams.Align = CGroupCell::Right;
else if (align != "justify")
align.clear();
// copy td align (can be empty) attribute back into css
_Style.Current.TextAlign = align;
}
{
@ -5503,7 +5566,7 @@ namespace NLGUI
string suri = elm.getAttribute("href");
if(suri.find("ah:") == 0)
{
if (_TrustedDomain)
if (_TrustedDomain || suri.find("ah:script:") == 0)
_Link.back() = suri;
}
else
@ -6360,11 +6423,13 @@ namespace NLGUI
void CGroupHTML::htmlOBJECTend(const CHtmlElement &elm)
{
if (!_TrustedDomain)
return;
if (_ObjectType=="application/ryzom-data")
{
if (!_TrustedDomain)
return;
if (!_ObjectData.empty())
{
if (addBnpDownload(_ObjectData, _ObjectAction, _ObjectScript, _ObjectMD5Sum))
@ -6374,6 +6439,20 @@ namespace NLGUI
_ObjectScript.clear();
}
}
else if (_ObjectType=="application/ryzom-tutorial")
{
while(strFindReplace(_ObjectScript, "[", ""));
while(strFindReplace(_ObjectScript, "]", ""));
CLuaManager::getInstance().executeLuaScript("\ngame:executeTutorial([["+_ObjectScript+"]])\n", true);
_ObjectScript.clear();
}
else if (_ObjectType=="application/ryzom-script")
{
while(strFindReplace(_ObjectScript, "[", ""));
while(strFindReplace(_ObjectScript, "]", ""));
CLuaManager::getInstance().executeLuaScript("\ngame:executeRyzomScript([["+_ObjectScript+"]])\n", true);
_ObjectScript.clear();
}
_Object = false;
}
@ -6767,6 +6846,9 @@ namespace NLGUI
// setting ModulateGlobalColor must be after addImageDownload
if (_Style.checkStyle("-ryzom-modulate-bgcolor", "true"))
table->setModulateGlobalColor(true);
else if (_Style.checkStyle("-ryzom-modulate-bgcolor", "false"))
table->setModulateGlobalColor(false);
table->setMarginLeft(getIndent());
addHtmlGroup (table, 0);

@ -64,6 +64,7 @@ namespace NLGUI
_Indent = 0;
_FirstViewIndentView = false;
_TextId = 0;
_TextAlign = AlignLeft;
}
// ----------------------------------------------------------------------------
@ -713,6 +714,10 @@ namespace NLGUI
CViewText *viewText = dynamic_cast<CViewText*>(_Elements[i].Element);
if (viewText)
{
// FIXME: this does not work with multiple view text on same line
if (_TextAlign == AlignCenter && elmCount == 1)
viewText->setTextMode(CViewText::Centered);
viewText->setFirstLineX(x + ((i==0)?_FirstViewIndentView:0));
viewText->setX(0);
viewText->updateTextContext();
@ -730,6 +735,12 @@ namespace NLGUI
// Does we balance the last line height ?
if (viewText)
{
if (_TextAlign == AlignCenter && elmCount == 1)
{
sint pad = width - viewText->getWReal();
viewText->setX(pad/2);
}
changeLine = viewText->getNumLine() > 1;
if (!viewText->getText().empty() && *(viewText->getText().rbegin()) == (ucchar) '\n')
{

@ -57,7 +57,7 @@ namespace NLGUI
// ***************************************************************************
// recursive function to walk html document
void CHtmlParser::parseNode(xmlNode *a_node, CHtmlElement &parent, std::string &styleString, std::vector<std::string> &links) const
void CHtmlParser::parseNode(xmlNode *a_node, CHtmlElement &parent, std::vector<std::string> &styles, std::vector<StyleLink> &links) const
{
uint childIndex = 0;
uint element_number;
@ -66,7 +66,15 @@ namespace NLGUI
{
if (node->type == XML_TEXT_NODE)
{
parent.Children.push_back(CHtmlElement(CHtmlElement::TEXT_NODE, (const char*)(node->content)));
// linebreak right after pre,textare open tag should be removed
if (parent.Children.empty() && (*node->content == '\n') && (parent.ID == HTML_PRE || parent.ID == HTML_TEXTAREA))
{
parent.Children.push_back(CHtmlElement(CHtmlElement::TEXT_NODE, (const char*)(node->content) + 1));
}
else
{
parent.Children.push_back(CHtmlElement(CHtmlElement::TEXT_NODE, (const char*)(node->content)));
}
}
else
if (node->type == XML_ELEMENT_NODE)
@ -145,7 +153,9 @@ namespace NLGUI
if (useStyle)
{
parseStyle(node->children, styleString);
std::string style;
parseStyle(node->children, style);
styles.push_back(style);
}
// style tag is kept in dom
}
@ -163,13 +173,24 @@ namespace NLGUI
if (useStyle)
{
links.push_back(elm.getAttribute("href"));
styles.push_back("");
links.push_back(StyleLink(styles.size()-1, elm.getAttribute("href")));
}
// link tag is kept in dom
}
else if (node->children)
{
parseNode(node->children, elm, styleString, links);
parseNode(node->children, elm, styles, links);
if (!elm.Children.empty() && elm.ID == HTML_PRE && elm.Children.back().Type == CHtmlElement::TEXT_NODE)
{
std::string::size_type size = elm.Children.back().Value.size();
// strip last '\n' from non-empty line
if (size > 1 && elm.Children.back().Value[size-1] == '\n')
{
elm.Children.back().Value = elm.Children.back().Value.substr(0, size - 1);
}
}
// must cleanup nested tags that libxml2 does not fix
// dt without end tag: <dl><dt><dt></dl>
@ -406,7 +427,7 @@ namespace NLGUI
}
// ***************************************************************************
void CHtmlParser::getDOM(std::string htmlString, CHtmlElement &dom, std::string &styleString, std::vector<std::string> &links) const
void CHtmlParser::getDOM(std::string htmlString, CHtmlElement &dom, std::vector<std::string> &styles, std::vector<StyleLink> &links) const
{
htmlParserCtxtPtr parser = htmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL, XML_CHAR_ENCODING_UTF8);
if (!parser)
@ -428,8 +449,7 @@ namespace NLGUI
xmlNode *root = xmlDocGetRootElement(parser->myDoc);
if (root)
{
styleString.clear();
parseNode(root, dom, styleString, links);
parseNode(root, dom, styles, links);
}
else
{

@ -1028,21 +1028,16 @@ namespace NLGUI
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceElement::convertBool (const char *ptr)
bool CInterfaceElement::convertBool (const char *ptr)
{
std::string str = toLower(ptr);
bool b = false;
fromString( str, b );
return b;
return NLMISC::toBool(ptr);
}
// ------------------------------------------------------------------------------------------------
NLMISC::CVector CInterfaceElement::convertVector (const char *ptr)
{
float x = 0.0f, y = 0.0f, z = 0.0f;
sscanf (ptr, "%f %f %f", &x, &y, &z);
return CVector(x,y,z);
}

@ -3570,7 +3570,7 @@ void CBitmap::loadSize(NLMISC::IStream &f, uint32 &retWidth, uint32 &retHeight)
}
while(!eof);
}
else if(fileType == JPG_HEADER)
else if(memcmp(&fileType, &JPG_HEADER, 2) == 0)
{
uint8 blockMarker1 = 0;
uint8 blockMarker2 = 0;

@ -179,7 +179,6 @@
#else
# include <sys/types.h>
# include <sys/stat.h>
# include <sys/sysctl.h>
# include <fcntl.h>
# include <unistd.h>
# include <cerrno>

@ -180,6 +180,7 @@ int main(int argc, char **argv)
Args.setVersion(getDisplayVersion());
Args.setDescription("Ryzom client");
Args.addArg("n", "nopatch", "value", "Use this to not use patch system");
Args.addArg("p", "profile", "id", "Use this profile to determine what directory to use by default");
Args.addAdditionalArg("login", "Login to use", true, false);
Args.addAdditionalArg("password", "Password to use", true, false);

@ -326,8 +326,8 @@ CClientConfig::CClientConfig()
Local = false; // Default is Net Mode.
FSHost = ""; // Default Host.
TexturesInterface.push_back("texture_interfaces_v3");
TexturesInterfaceDXTC.push_back("texture_interfaces_dxtc");
TexturesInterface.push_back("texture_interfaces_v3_2x");
TexturesInterfaceDXTC.push_back("texture_interfaces_dxtc_2x");
TexturesOutGameInterface.push_back("texture_interfaces_v3_outgame_ui");
@ -782,8 +782,8 @@ void CClientConfig::setValues()
READ_STRINGVECTOR_FV(TexturesOutGameInterfaceDXTC);
// interface textures ingame and r2
READ_STRINGVECTOR_FV(TexturesInterface);
READ_STRINGVECTOR_FV(TexturesInterfaceDXTC);
//READ_STRINGVECTOR_FV(TexturesInterface);
//READ_STRINGVECTOR_FV(TexturesInterfaceDXTC);
// interface files login menus
READ_STRINGVECTOR_FV(XMLLoginInterfaceFiles);

@ -549,6 +549,6 @@ bool CSBrickSheet::mustDisplayLevel() const
// NB: Yoyo Hack. special interface with indexInFamily==63 means "want to display the level"
return !( isMandatory() ||
isRoot() ||
(BrickFamily>= BRICK_FAMILIES::BeginInterface && BrickFamily<= BRICK_FAMILIES::EndInterface && IndexInFamily!=63) ||
//(BrickFamily>= BRICK_FAMILIES::BeginInterface && BrickFamily<= BRICK_FAMILIES::EndInterface && IndexInFamily!=63) ||
Level==0 );
}

@ -193,6 +193,7 @@ bool hasPrivilegeG() { return (UserPrivileges.find(":G:") != std::string::npos);
bool hasPrivilegeEM() { return (UserPrivileges.find(":EM:") != std::string::npos); }
bool hasPrivilegeEG() { return (UserPrivileges.find(":EG:") != std::string::npos); }
bool hasPrivilegeOBSERVER() { return (UserPrivileges.find(":OBSERVER:") != std::string::npos); }
bool hasPrivilegeTESTER() { return (UserPrivileges.find(":TESTER:") != std::string::npos); }
// Restore the video mode (fullscreen for example) after the connection (done in a window)

@ -52,6 +52,7 @@ bool hasPrivilegeEM();
bool hasPrivilegeEG();
bool hasPrivilegeVG();
bool hasPrivilegeOBSERVER();
bool hasPrivilegeTESTER();
// connection with the server. (login, shard list, etc.).

@ -49,12 +49,12 @@
#include "login_progress_post_thread.h"
#include "interface_v3/action_handler_base.h"
#include "item_group_manager.h"
#include "nel/misc/cmd_args.h"
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
using namespace NLMISC;
using namespace NLNET;
using namespace NL3D;
@ -210,6 +210,7 @@ extern bool IsInRingSession;
extern void selectTipsOfTheDay (uint tips);
#define BAR_STEP_TP 2
extern NLMISC::CCmdArgs Args;
CLoginStateMachine::TEvent CLoginStateMachine::waitEvent()
{
@ -462,12 +463,14 @@ void CLoginStateMachine::run()
case st_check_patch:
/// check the data to check if patch needed
CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_PostLogin, "login_step_post_login"));
if (!ClientCfg.PatchWanted)
if (!ClientCfg.PatchWanted || (Args.haveArg("n") && Args.getLongArg("nopatch").front() == "1"))
{
// client don't want to be patched !
_CurrentState = st_display_eula;
break;
}
initPatchCheck();
SM_BEGIN_EVENT_TABLE
if (isBGDownloadEnabled())
@ -1517,4 +1520,3 @@ void CFarTP::farTPmainLoop()
if(welcomeWindow)
initWelcomeWindow();
}

@ -267,7 +267,7 @@ void CGameContextMenu::update()
setupContextMenuCantTalk(); // can't talk by default
bool showGMOptions = (hasPrivilegeDEV() || hasPrivilegeSGM() || hasPrivilegeGM() || hasPrivilegeVG() || hasPrivilegeSG() || hasPrivilegeEM() || hasPrivilegeEG() || hasPrivilegeOBSERVER());
bool showGMOptions = (hasPrivilegeDEV() || hasPrivilegeSGM() || hasPrivilegeGM() || hasPrivilegeVG() || hasPrivilegeSG() || hasPrivilegeEM() || hasPrivilegeEG() || hasPrivilegeOBSERVER() || hasPrivilegeTESTER());
if (_TextInvisible)
_TextInvisible->setActive(showGMOptions);

@ -4686,7 +4686,7 @@ class CHandlerOutgameNaviGetKeys : public IActionHandler
id = "sel";
if (event != -1)
- CLuaManager::getInstance().executeLuaScript(toString("outgame:eventChar%sKeyGet(%i)", id.c_str(), event));
CLuaManager::getInstance().executeLuaScript(toString("outgame:eventChar%sKeyGet(%i)", id.c_str(), event));
}
// reset previous input
Driver->AsyncListener.reset();

@ -86,6 +86,12 @@ void CBotChatManager::setCurrPage(CBotChatPage *page)
UserEntity->trader(CLFECOMMON::INVALID_SLOT);
}
_CurrPage = page;
if (page == NULL && !_AHAfterEnd.empty())
{
CAHManager::getInstance()->runActionHandler(_AHAfterEnd, NULL, "");
_AHAfterEnd = "";
}
}
// ********************************************************************************************

@ -93,12 +93,15 @@ public:
// Called for local client debugging
void debugLocalReceiveMissionInfo();
void setAHAfterEnd(const std::string &ah) { _AHAfterEnd = ah ;}
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
private:
CBotChatPage *_CurrPage;
uint16 _SessionID;
std::string _AHAfterEnd;
static CBotChatManager *_Instance;
//uint _ChosenMissionFlags;

@ -161,6 +161,7 @@ void CBotChatPageMission::acceptMission()
/// close the botchat
//CBotChatManager::getInstance()->setCurrPage(NULL);
_CurrSel = NULL;
CBotChatManager::getInstance()->setAHAfterEnd("context_choose_mission");
}

@ -51,6 +51,7 @@ private:
// an observer to update big mission list from littles pages in server database
CHugeListObs _MissionPagesObs;
CDBCtrlSheet *_CurrSel;
bool _HaveAcceptedMission;
MISSION_DESC::TClientMissionType _MType;
};

@ -424,30 +424,37 @@ CViewBase *CChatTextManager::createMsgTextComplex(const ucstring &msg, NLMISC::C
ucstring::size_type pos = 0;
// Manage Translations
CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_TRANSLATION_ONLY_AS_TOOLTIP_CB", false);
bool originalFirst = node->getValueBool();
string::size_type startTr = msg.find(ucstring("{:"));
string::size_type endOfOriginal = msg.find(ucstring("}@{"));
// Original/Translated case, example: {:enHello the world!}@{ Bonjour le monde !
if (startTr != string::npos && endOfOriginal != string::npos)
{
string lang = toUpper(msg.substr(startTr+2, 2)).toString();
bool inverse = false;
bool hideFlag = false;
CCDBNodeLeaf *nodeInverse = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:TRANSLATION:" + lang + ":INVERSE_DISPLAY", false);
if (nodeInverse)
inverse = nodeInverse->getValueBool();
CCDBNodeLeaf *nodeHideFlag = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:TRANSLATION:" + lang + ":HIDE_FLAG", false);
if (nodeHideFlag)
hideFlag = nodeHideFlag->getValueBool();
CViewBase *vt = createMsgTextSimple(msg.substr(0, startTr), col, justified, NULL);
para->addChild(vt);
string texture = "flag-"+toLower(msg.substr(startTr+2, 2)).toString()+".tga";
ucstring original = msg.substr(startTr+5, endOfOriginal-startTr-5);
ucstring translation = msg.substr(endOfOriginal+3);
ucstring translation = msg.substr(endOfOriginal+4);
CCtrlButton *ctrlButton = new CCtrlButton(CViewBase::TCtorParam());
ctrlButton->setTexture(texture);
ctrlButton->setTextureOver(texture);
ctrlButton->setTexturePushed(texture);
if (!originalFirst)
if (!inverse)
{
ctrlButton->setDefaultContextHelp(original);
pos = endOfOriginal+3;
pos = endOfOriginal+4;
}
else
{
@ -456,7 +463,11 @@ CViewBase *CChatTextManager::createMsgTextComplex(const ucstring &msg, NLMISC::C
textSize = endOfOriginal;
}
ctrlButton->setId("tr");
para->addChild(ctrlButton);
if (hideFlag) {
delete ctrlButton;
} else {
para->addChild(ctrlButton);
}
}
// quickly check if text has links or not

@ -216,7 +216,25 @@ void CChatWindow::displayMessage(const ucstring &msg, NLMISC::CRGBA col, CChatGr
gl = dynamic_cast<CGroupList *>(_Chat->getGroup("cb:text_list"));
CViewBase *child = ctm.createMsgText(msg, col);
bool noTranslation = false;
CCDBNodeLeaf *nodeNoTranslation = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:TRANSLATION:" + toUpper(CChatGroup::groupTypeToString(gt)) + ":DISABLE", false);
if (nodeNoTranslation)
noTranslation = nodeNoTranslation->getValueBool();
ucstring msgNoTranslate = msg;
if (noTranslation) {
string::size_type startTr = msg.find(ucstring("{:"));
string::size_type endOfOriginal = msg.find(ucstring("}@{"));
if (startTr != string::npos && endOfOriginal != string::npos) {
msgNoTranslate = msg.substr(0, startTr) + msg.substr(startTr+5, endOfOriginal-startTr-5);
}
}
CViewBase *child = ctm.createMsgText(msgNoTranslate, col);
if (child)
{
if (gl) gl->addChild(child);
@ -568,6 +586,18 @@ void CChatGroupWindow::displayMessage(const ucstring &msg, NLMISC::CRGBA col, CC
ucstring newmsg = msg;
ucstring prefix;
CCDBNodeLeaf *nodeNoTranslation = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:TRANSLATION:" + toUpper(CChatGroup::groupTypeToString(gt)) + ":DISABLE", false);
bool noTranslation = nodeNoTranslation->getValueBool();
if (noTranslation) {
string::size_type startTr = msg.find(ucstring("{:"));
string::size_type endOfOriginal = msg.find(ucstring("}@{"));
if (startTr != string::npos && endOfOriginal != string::npos) {
newmsg = newmsg.substr(0, startTr) + newmsg.substr(startTr+5, endOfOriginal-startTr-5);
}
}
CViewBase *child = NULL;
if (gl != NULL)
{

@ -56,6 +56,7 @@
#include "../r2/editor.h"
#include "nel/gui/lua_manager.h"
#include "nel/misc/xml_macros.h"
extern CSheetManager SheetMngr;
@ -543,6 +544,15 @@ CCtrlDraggable(param)
_RegenText = NULL;
_RegenTextValue = 0;
_RegenTextEnabled = true;
_RegenTextShadow = true;
_RegenTextOutline = false;
_RegenTextFctLua = false;
_RegenTextY = 2;
_RegenTextFontSize = 8;
_RegenTextColor = NLMISC::CRGBA::White;
_RegenTextShadowColor = NLMISC::CRGBA::Black;
_RegenTextOutlineColor = NLMISC::CRGBA::Black;
}
// ----------------------------------------------------------------------------
@ -655,6 +665,17 @@ bool CDBCtrlSheet::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup)
prop = (char*) xmlGetProp( cur, (xmlChar*)"focus_buff_icon" );
if (prop) _FocusBuffIcon = string((const char *)prop);
XML_READ_BOOL(cur, "regen_text", _RegenTextEnabled, true);
XML_READ_BOOL(cur, "regen_text_shadow", _RegenTextShadow, true);
XML_READ_BOOL(cur, "regen_text_outline", _RegenTextOutline, false);
XML_READ_SINT(cur, "regen_text_y", _RegenTextY, 2);
XML_READ_UINT(cur, "regen_text_fontsize", _RegenTextFontSize, 8);
XML_READ_COLOR(cur, "regen_text_color", _RegenTextColor, NLMISC::CRGBA::White);
XML_READ_COLOR(cur, "regen_text_shadow_color", _RegenTextShadowColor, NLMISC::CRGBA::Black);
XML_READ_COLOR(cur, "regen_text_outline_color", _RegenTextOutlineColor, NLMISC::CRGBA::Black);
XML_READ_STRING(cur, "regen_text_fct", _RegenTextFct, "");
_RegenTextFctLua = startsWith(_RegenTextFct, "lua:");
updateActualType();
// Init size for Type
initSheetSize();
@ -1086,6 +1107,7 @@ void CDBCtrlSheet::clearIconBuffs()
{
_EnchantIcons.clear();
_BuffIcons.clear();
_BoostIcons.clear();
}
// ***************************************************************************
@ -1118,8 +1140,15 @@ void CDBCtrlSheet::infoReceived()
if (brick)
{
if (!brick->isRoot() && !brick->isCredit() && !brick->isParameter())
if (brick->BrickFamily == BRICK_FAMILIES::BSGMCB) // Boost of Allegories, use it as boost icon
{
if (!haveRoot)
_BoostIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(brick->getIcon()), brick->IconColor));
rVR.getTextureSizeFromId(_BoostIcons.back().TextureId, _BoostIcons.back().IconW, _BoostIcons.back().IconH);
}
else if (!brick->isRoot() && !brick->isCredit() && !brick->isParameter())
{
if (!haveRoot && !brick->getIconBack().empty())
{
_EnchantIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(brick->getIconBack()), brick->IconBackColor));
rVR.getTextureSizeFromId(_EnchantIcons.back().TextureId, _EnchantIcons.back().IconW, _EnchantIcons.back().IconH);
@ -2097,35 +2126,8 @@ void CDBCtrlSheet::draw()
rVR.drawQuad(_RenderLayer + 1, regenTris[tri], backTex, CRGBA::White, false);
}
if (!_RegenText) {
_RegenText = new CViewText(CViewBase::TCtorParam());
_RegenText->setId(getId() + ":regen");
_RegenText->setParent(_Parent);
_RegenText->setOverflowText(ucstring(""));
_RegenText->setModulateGlobalColor(false);
_RegenText->setMultiLine(false);
_RegenText->setTextMode(CViewText::ClipWord);
_RegenText->setFontSizing("0", "0");
// TODO: font size / color hardcoded.
_RegenText->setFontSize(8);
_RegenText->setColor(CRGBA::White);
_RegenText->setShadow(true);
_RegenText->setActive(true);
_RegenText->updateTextContext();
}
// TODO: ticks in second hardcoded
uint32 nextValue = _RegenTickRange.EndTick > LastGameCycle ? (_RegenTickRange.EndTick - LastGameCycle) / 10 : 0;
if (_RegenTextValue != nextValue)
{
_RegenTextValue = nextValue;
_RegenText->setText(toString("%d", _RegenTextValue));
_RegenText->updateTextContext();
}
_RegenText->setXReal(_XReal+1);
_RegenText->setYReal(_YReal+2);
_RegenText->setRenderLayer(_RenderLayer+2);
_RegenText->draw();
if (_RegenTextEnabled)
drawRegenText();
}
}
@ -2155,6 +2157,118 @@ void CDBCtrlSheet::draw()
}
}
// ----------------------------------------------------------------------------
void CDBCtrlSheet::drawRegenText()
{
if (!_RegenText) {
_RegenText = new CViewText(CViewBase::TCtorParam());
_RegenText->setId(getId() + ":regen");
_RegenText->setParent(_Parent);
_RegenText->setOverflowText(std::string());
_RegenText->setModulateGlobalColor(false);
_RegenText->setMultiLine(true);
_RegenText->setTextMode(CViewText::ClipWord);
_RegenText->setFontSize(_RegenTextFontSize);
_RegenText->setColor(_RegenTextColor);
// do not set shadow if outline is set to avoid clearing it on draw (would call invalidate)
_RegenText->setShadow(_RegenTextShadow && !_RegenTextOutline);
_RegenText->setShadowOutline(false);
_RegenText->setShadowColor(_RegenTextShadowColor);
_RegenText->setActive(true);
_RegenText->updateTextContext();
}
// TODO: 10 hardcoded (ticks in second)
sint32 nextValue;
if (_RegenTickRange.EndTick > LastGameCycle)
nextValue = (_RegenTickRange.EndTick - LastGameCycle) / 10;
else if (_RegenTextFctLua)
nextValue = ((sint64)_RegenTickRange.EndTick - (sint64)LastGameCycle) / 10;
else
nextValue = 0;
if (_RegenTextValue != nextValue)
{
_RegenTextValue = nextValue;
if (_RegenTextFct.empty())
{
// format as "10m", "9'59", "59"
if (_RegenTextValue > 600)
{
_RegenText->setText(toString("%dm", _RegenTextValue / 60));
}
else if (_RegenTextValue > 0)
{
if (_RegenTextValue < 60)
_RegenText->setText(toString("%d", _RegenTextValue));
else
_RegenText->setText(toString("%d'%02d", _RegenTextValue / 60, _RegenTextValue % 60));
}
else
{
_RegenText->setText(ucstring());
}
}
else
{
std::string fct;
if (_RegenTextFctLua)
{
CCDBNodeBranch *root = getRootBranch();
if (root)
fct = toString("%s(%d, '%s')", _RegenTextFct.c_str(), _RegenTextValue, root->getFullName().c_str());
else
fct = toString("%s(%d, nil)", _RegenTextFct.c_str(), _RegenTextValue);
}
else
{
fct = toString("%s(%d)", _RegenTextFct.c_str(), _RegenTextValue);
}
// if using color tags in format, then RegenText color should be set to CRGBA::White
// as tag color is modulated with main color
std::string result;
if (CInterfaceExpr::evalAsString(fct, result))
_RegenText->setTextFormatTaged(result);
}
_RegenText->updateTextContext();
// todo: posref
// note: if x,y is moved outside icon area it might get cliped and not be visible (wreal/hreal == 0)
_RegenText->setX(_WReal / 2 -_RegenText->getMaxUsedW() / 2);
// move RegenTextY=0 to baseline
_RegenText->setY(_RegenTextY - _RegenText->getFontLegHeight());
}
_RegenText->setXReal(_XReal + _RegenText->getX());
_RegenText->setYReal(_YReal + _RegenText->getY());
_RegenText->setRenderLayer(_RenderLayer+2);
// TODO: create shader for this
if (_RegenTextOutline)
{
// player.xml t_bonus_text template way of drawing
sint x = _RegenText->getXReal();
sint y = _RegenText->getYReal();
_RegenText->setColor(_RegenTextShadowColor);
_RegenText->setXReal(x-1); _RegenText->setYReal(y+0); _RegenText->draw();
_RegenText->setXReal(x+1); _RegenText->setYReal(y+0); _RegenText->draw();
_RegenText->setXReal(x+0); _RegenText->setYReal(y-1); _RegenText->draw();
_RegenText->setXReal(x+0); _RegenText->setYReal(y+1); _RegenText->draw();
_RegenText->setColor(_RegenTextColor);
_RegenText->setXReal(x); _RegenText->setYReal(y);
_RegenText->draw();
_RegenText->draw();
}
else
{
_RegenText->draw();
_RegenText->draw();
}
}
// ----------------------------------------------------------------------------
void CDBCtrlSheet::drawRotatedQuad(CViewRenderer &vr, float angle, float scale, uint renderLayer, uint32 texId, sint32 texWidth, sint32 texHeight)
@ -2444,10 +2558,17 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti
}
yIcon -= hIcon;
rVR.drawRotFlipBitmap(_RenderLayer + 1, xIcon, yIcon, wIcon, hIcon, 0, false, _EnchantIcons[0].TextureId, fastMulRGB(curSheetColor, _EnchantIcons[0].Color));
rVR.drawRotFlipBitmap(_RenderLayer+1, xIcon, yIcon, wIcon, hIcon, 0, false, _EnchantIcons[i].TextureId, fastMulRGB(curSheetColor, _EnchantIcons[i].Color));
rVR.drawRotFlipBitmap(_RenderLayer + 1, xIcon, yIcon, wIcon, hIcon, 0, false, _EnchantIcons[i].TextureId, fastMulRGB(curSheetColor, _EnchantIcons[i].Color));
if ((i - 1) < _BoostIcons.size()) {
rVR.drawRotFlipBitmap(_RenderLayer + 2, xIcon+wIcon-_BoostIcons[i-1].IconW, yIcon, _BoostIcons[i-1].IconW, _BoostIcons[i-1].IconH, 0, false, _BoostIcons[i-1].TextureId, fastMulRGB(curSheetColor, _BoostIcons[i-1].Color));
}
}
}
// Draw Quality. -1 for lookandfeel. Draw it with global color
if (_DispQuality != -1)
{
@ -3804,6 +3925,7 @@ void CDBCtrlSheet::resetAllTexIDs()
_ItemInfoChanged = true;
_EnchantIcons.clear();
_BuffIcons.clear();
_BoostIcons.clear();
}
@ -4743,6 +4865,12 @@ std::string CDBCtrlSheet::getContextHelpWindowName() const
return CCtrlBase::getContextHelpWindowName();
}
// ***************************************************************************
void CDBCtrlSheet::setRegenTextFct(const std::string &s)
{
_RegenTextFct = s;
_RegenTextFctLua = startsWith(s, "lua:");
}
// ***************************************************************************
void CDBCtrlSheet::setRegenTickRange(const CTickRange &tickRange)

@ -602,6 +602,25 @@ public:
void setRegenTickRange(const CTickRange &tickRange);
const CTickRange &getRegenTickRange() const { return _RegenTickRange; }
// Default regen text is displayed on bottom of icon.
void setRegenText(bool b) { _RegenTextEnabled = b; }
// Allow to override default formatter.
// First parameter will be replaced with current timer value (always >= 0)
// If its a lua function, then parameters are
// 1: current timer value; can be negative
// 2: DB path for ctrl root (ie UI:VARIABLES:BONUSES:0), or nil
//
// ie: "secondsToTimeStringShort" -> CInterfaceExpr::evalAsString("secondsToTimeStringShort(123)", ret)
// ie: "lua:secondsToTimeStringShort" -> CInterfaceExpr::evalAsString("lua:secondsToTimeStringShort(123, 'UI:VARIABLES:BONUSES:0')", ret)
void setRegenTextFct(const std::string &s);
void setRegenTextY(sint32 y) { _RegenTextY = y; }
void setRegenTextShadow(bool b) { _RegenTextShadow = b; }
void setRegenTextShadowColor(NLMISC::CRGBA c) { _RegenTextShadowColor = c; }
void setRegenTextOutline(bool b) { _RegenTextOutline = b; }
void setRegenTextOutlineColor(NLMISC::CRGBA c) { _RegenTextOutlineColor = c; }
void setRegenTextFontSize(uint32 s) { _RegenTextFontSize = s; }
void setRegenTextColor(NLMISC::CRGBA c) { _RegenTextColor = c; }
// start notify anim (at the end of regen usually)
void startNotifyAnim();
@ -682,6 +701,7 @@ protected:
};
std::vector<SBuffIcon> _BuffIcons;
std::vector<SBuffIcon> _EnchantIcons;
std::vector<SBuffIcon> _BoostIcons;
// Level Brick or Quality
union
@ -738,7 +758,19 @@ protected:
CTickRange _RegenTickRange;
NLGUI::CViewText *_RegenText;
uint32 _RegenTextValue;
sint32 _RegenTextValue;
//
std::string _RegenTextFct;
bool _RegenTextFctLua;
bool _RegenTextEnabled;
bool _RegenTextShadow;
bool _RegenTextOutline;
sint32 _RegenTextY;
uint32 _RegenTextFontSize;
NLMISC::CRGBA _RegenTextShadowColor;
NLMISC::CRGBA _RegenTextOutlineColor;
NLMISC::CRGBA _RegenTextColor;
/// D'n'd
sint32 _DragX, _DragY;
@ -852,6 +884,9 @@ private:
// gelper to draw the notify animation
void drawRotatedQuad(CViewRenderer &vr, float angle, float scale, uint renderLayer, uint32 textureId, sint32 texWidth, sint32 texHeight);
// create and draw regen text over icon
void drawRegenText();
};
/** User type (used with expression system of the interface, see interface_expr.h, that contains a pointer to a CDBCtrlSheet

@ -23,7 +23,7 @@
#include "stdpch.h"
#include "dbgroup_list_sheet_bonus_malus.h"
#include "interface_manager.h"
#include "nel/misc/xml_macros.h"
using namespace std;
using namespace NLMISC;
@ -35,87 +35,106 @@ NLMISC_REGISTER_OBJECT(CViewBase, CDBGroupListSheetBonusMalus, std::string, "lis
// ***************************************************************************
CDBGroupListSheetBonusMalus::CDBGroupListSheetBonusMalus(const TCtorParam &param)
: CDBGroupListSheet(param)
: CDBGroupListSheet(param),
_RegenTextEnabled(true),
_RegenTextY(-14), _RegenTextFontSize(8),
_RegenTextColor(NLMISC::CRGBA::White),
_RegenTextDisabledColor(NLMISC::CRGBA(127,127,127))
{
_TextId= -1;
// want leave space between controls in the list
// Yoyo: I think it's better like this, + this is important for space consideration and because of XPCat/PVPOutpost
//_ListLeaveSpace= false;
}
// ***************************************************************************
bool CDBGroupListSheetBonusMalus::parse (xmlNodePtr cur, CInterfaceGroup *parentGroup)
CDBGroupListSheetBonusMalus::CSheetChildTimer::CSheetChildTimer()
: TimerDB(NULL), DisabledDB(NULL), TimerCache(0),
_RegenTextColor(NLMISC::CRGBA::White),
_RegenTextDisabledColor(NLMISC::CRGBA(127,127,127))
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
}
if(!CDBGroupListSheet::parse(cur, parentGroup))
return false;
// ***************************************************************************
void CDBGroupListSheetBonusMalus::CSheetChildTimer::init(CDBGroupListSheet *pFather, uint index)
{
// init my parent
CSheetChild::init(pFather, index);
// read the texture
CXMLAutoPtr prop;
prop = (char*) xmlGetProp( cur, (xmlChar*)"disable_texture" );
if (prop)
CCDBNodeBranch *root = Ctrl->getRootBranch();
if (root)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CViewRenderer &rVR = *CViewRenderer::getInstance();
_TextId= rVR.getTextureIdFromName ((const char *)prop);
TimerDB = dynamic_cast<CCDBNodeLeaf *>(root->getNode(ICDBNode::CTextId("DISABLED_TIME"), false));
DisabledDB = dynamic_cast<CCDBNodeLeaf *>(root->getNode(ICDBNode::CTextId("DISABLED"), false));
}
// get the Node leaves to be tested each frame
uint i= 0;
for(;;)
if (Ctrl)
{
string db= toString("%s:%d:" DISABLE_LEAF, _DbBranchName.c_str(), i);
CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp(db, false);
if(!node)
CDBGroupListSheetBonusMalus *owner = dynamic_cast<CDBGroupListSheetBonusMalus *>(pFather);
if (owner)
{
break;
_RegenTextColor = owner->_RegenTextColor;
_RegenTextDisabledColor = owner->_RegenTextDisabledColor;
Ctrl->setRegenText(owner->_RegenTextEnabled);
Ctrl->setRegenTextY(owner->_RegenTextY);
Ctrl->setRegenTextColor(owner->_RegenTextColor);
Ctrl->setRegenTextFontSize(owner->_RegenTextFontSize);
if (!owner->_RegenTextFct.empty())
Ctrl->setRegenTextFct(owner->_RegenTextFct);
}
else
{
_DisableStates.push_back(node);
i++;
}
}
return true;
Ctrl->setRegenTextOutline(true);
}
}
// ***************************************************************************
void CDBGroupListSheetBonusMalus::draw ()
void CDBGroupListSheetBonusMalus::CSheetChildTimer::update(CDBGroupListSheet * /* pFather */)
{
CDBGroupListSheet::draw();
// CInterfaceManager *pIM= CInterfaceManager::getInstance();
// CViewRenderer &rVR= *CViewRenderer::getInstance();
// sint32 drl= getRenderLayer()+1;
if(!TimerDB)
return;
// May draw disable bitmaps on the ctrl sheets if disabled.
uint numCtrls= (uint)min(_SheetChildren.size(), _DisableStates.size());
for(uint i=0;i<numCtrls;i++)
NLMISC::TGameCycle tick = TimerDB->getValue32();
if (TimerCache != tick)
{
CDBCtrlSheet *ctrl= _SheetChildren[i]->Ctrl;
// if the ctrl is displayed, and if the state is disabled
if(ctrl->getActive())
TimerCache = TimerDB->getValue32();
Ctrl->setRegenTickRange(CTickRange(LastGameCycle, TimerCache));
if (DisabledDB)
{
if(_DisableStates[i]->getValue32()!=0)
if (DisabledDB->getValue32() == 0)
{
ctrl->setGrayed(true);
/*
// YOYO: for now, don't display the gray bitmap. cross not cool.
CRGBA crossColor= ctrl->getSheetColor();
crossColor.A>>= 2;
// Draw the disable bitmap on this control. +1 for the slot (ugly)
rVR.drawRotFlipBitmap(drl, ctrl->getXReal()+1, ctrl->getYReal()+1,
CCtrlSheetInfo::BrickSheetWidth, CCtrlSheetInfo::BrickSheetHeight, 0, 0, _TextId, crossColor);
*/
// active timer
Ctrl->setGrayed(false);
Ctrl->setRegenTextColor(_RegenTextColor);
}
else
ctrl->setGrayed(false);
{
// skill disabled timer
Ctrl->setGrayed(true);
Ctrl->setRegenTextColor(_RegenTextDisabledColor);
}
}
else
{
Ctrl->setGrayed(true);
}
}
}
// ***************************************************************************
bool CDBGroupListSheetBonusMalus::parse (xmlNodePtr cur, CInterfaceGroup *parentGroup)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
if(!CDBGroupListSheet::parse(cur, parentGroup))
return false;
CXMLAutoPtr prop;
XML_READ_BOOL(cur, "regen_text", _RegenTextEnabled, true);
XML_READ_SINT(cur, "regen_text_y", _RegenTextY, -14);
XML_READ_UINT(cur, "regen_text_fontsize", _RegenTextFontSize, 8);
XML_READ_COLOR(cur, "regen_text_color", _RegenTextColor, NLMISC::CRGBA::White);
XML_READ_COLOR(cur, "regen_text_disabled_color", _RegenTextDisabledColor, NLMISC::CRGBA(127, 127, 127));
XML_READ_STRING(cur, "regen_text_fct", _RegenTextFct, "");
return true;
}

@ -25,7 +25,6 @@
#include "nel/misc/types_nl.h"
#include "dbgroup_list_sheet.h"
// ***************************************************************************
/**
* Special list_sheet that display some disalbe bitmap if needed according to DB
@ -40,14 +39,34 @@ public:
/// Constructor
CDBGroupListSheetBonusMalus(const TCtorParam &param);
virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup);
// A child node
struct CSheetChildTimer : public CDBGroupListSheet::CSheetChild
{
CSheetChildTimer();
virtual void init(CDBGroupListSheet *pFather, uint index) NL_OVERRIDE;
virtual void update(CDBGroupListSheet *pFather) NL_OVERRIDE;
NLMISC::CCDBNodeLeaf *TimerDB;
NLMISC::CCDBNodeLeaf *DisabledDB;
uint TimerCache;
NLMISC::CRGBA _RegenTextColor;
NLMISC::CRGBA _RegenTextDisabledColor;
};
virtual bool parse(xmlNodePtr cur, CInterfaceGroup *parentGroup) NL_OVERRIDE;
virtual void draw ();
virtual CSheetChild *createSheetChild() NL_OVERRIDE { return new CSheetChildTimer; }
private:
sint32 _TextId;
friend CSheetChildTimer;
std::vector<NLMISC::CCDBNodeLeaf*> _DisableStates;
bool _RegenTextEnabled;
std::string _RegenTextFct;
sint32 _RegenTextY;
uint32 _RegenTextFontSize;
NLMISC::CRGBA _RegenTextColor;
NLMISC::CRGBA _RegenTextDisabledColor;
};

@ -28,6 +28,7 @@
#include "nel/gui/action_handler.h"
#include "../entities.h"
#include "nel/gui/group_paragraph.h" // For CCtrlLink
#include "nel/gui/view_bitmap.h"
#include "../net_manager.h"
#include "../string_manager_client.h"
#include "../login.h"
@ -644,14 +645,42 @@ void CGroupInSceneBubbleManager::addMessagePopupCenter (const ucstring &message,
"ui:interface", templateParams.empty()?NULL:&(templateParams[0]), (uint)templateParams.size());
if (group)
{
ucstring finalMessage = message;
ucstring::size_type pos = message.find(ucstring("|"));
if (pos != std::string::npos)
{
CViewBitmap *pViewIcon = dynamic_cast<CViewBitmap*>(group->getView("iconA"));
if (pViewIcon != NULL)
{
string texture = message.substr(0, pos).toString();
pViewIcon->setTexture(texture);
}
ucstring::size_type end = message.find(ucstring("|"), pos+1);
if (end != std::string::npos)
{
CViewBitmap *pViewIcon = dynamic_cast<CViewBitmap*>(group->getView("iconZ"));
if (pViewIcon != NULL)
{
string texture = message.substr(end+1).toString();
pViewIcon->setTexture(texture);
}
finalMessage = message.substr(pos+1, end-pos-1);
}
else
finalMessage = message.substr(pos+1);
}
// Skill name
CViewText *pViewName = dynamic_cast<CViewText*>(group->getView("name"));
if (pViewName != NULL)
{
pViewName->setTextFormatTaged(message);
pViewName->setTextFormatTaged(finalMessage);
pViewName->setColor (color);
}
// Link to the interface
CWidgetManager::getInstance()->addWindowToMasterGroup("ui:interface", group);
CInterfaceGroup *pRoot = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface"));
@ -846,16 +875,20 @@ void CGroupInSceneBubbleManager::chatOpen (uint32 nUID, const ucstring &ucsText,
// Clean bubble from translation system
CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_TRANSLATION_ONLY_AS_TOOLTIP_CB", false);
bool originalFirst = node->getValueBool();
ucstring::size_type pos = 0;
ucstring::size_type textSize = ucsText.size();
string::size_type startTr = ucsText.find(ucstring("{:"));
string::size_type endOfOriginal = ucsText.find(ucstring("}@{"));
if (endOfOriginal != string::npos)
{
if (!originalFirst)
if (startTr != string::npos && endOfOriginal != string::npos) {
bool inverse = false;
string lang = toUpper(ucsText.substr(startTr+2, 2)).toString();
CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:TRANSLATION:" + lang + ":INVERSE_DISPLAY", false);
if (node)
inverse = node->getValueBool();
if (!inverse)
{
pos = endOfOriginal+4;
}
@ -865,7 +898,7 @@ void CGroupInSceneBubbleManager::chatOpen (uint32 nUID, const ucstring &ucsText,
textSize = endOfOriginal;
}
}
// Output the message in a bubble
bool show = false;

@ -2654,7 +2654,7 @@ void CGroupMap::createContinentLandMarks()
static void hideTeleportButtonsInPopupMenuIfNotEnoughPriv()
{
bool showTeleport = (hasPrivilegeDEV() || hasPrivilegeSGM() || hasPrivilegeGM() || hasPrivilegeVG() || hasPrivilegeSG() || hasPrivilegeEM() || hasPrivilegeEG() || hasPrivilegeOBSERVER());
bool showTeleport = (hasPrivilegeDEV() || hasPrivilegeSGM() || hasPrivilegeGM() || hasPrivilegeVG() || hasPrivilegeSG() || hasPrivilegeEM() || hasPrivilegeEG() || hasPrivilegeOBSERVER()|| hasPrivilegeTESTER());
CInterfaceManager *im = CInterfaceManager::getInstance();
CInterfaceElement *ie = CWidgetManager::getInstance()->getElementFromId("ui:interface:map_menu:teleport");

@ -74,6 +74,8 @@ bool CGroupQuickHelp::submitEvent (const char *event)
// Update the text
updateParagraph ();
CLuaManager::getInstance().executeLuaScript(toString("\ngame:processTutorialEvent(\"%s\")\n", event), true);
}
}
return false;

@ -2523,6 +2523,17 @@ void CInterfaceManager::displaySystemInfo(const ucstring &str, const string &cat
CClientConfig::SSysInfoParam::TMode mode = CClientConfig::SSysInfoParam::Normal;
CRGBA color = CRGBA::White;
ucstring cleanStr = str;
ucstring::size_type pos = str.find(ucstring("|"));
if (pos != std::string::npos)
{
ucstring::size_type end = str.find(ucstring("|"), pos+1);
if (end != std::string::npos)
cleanStr = str.substr(pos+1, end-pos-1);
else
cleanStr = str.substr(pos+1);
}
// If broadcast, parse lua code
if (toLower(cat) == "bc" && str.size() > 3 && str[0]=='@' && str[1]=='L' && str[2]=='U' && str[3]=='A')
{
@ -2542,11 +2553,11 @@ void CInterfaceManager::displaySystemInfo(const ucstring &str, const string &cat
if (mode != CClientConfig::SSysInfoParam::OverOnly && mode != CClientConfig::SSysInfoParam::Around)
{
if (PeopleInterraction.SystemInfo)
PeopleInterraction.ChatInput.SystemInfo.displayMessage(str, color, 2);
PeopleInterraction.ChatInput.SystemInfo.displayMessage(cleanStr, color, 2);
else
{
CPeopleInterraction::CSysMsg sysMsg;
sysMsg.Str = str;
sysMsg.Str = cleanStr;
sysMsg.Cat = cat;
PeopleInterraction.SystemMessageBuffer.push_back( sysMsg );
}
@ -2557,10 +2568,10 @@ void CInterfaceManager::displaySystemInfo(const ucstring &str, const string &cat
// If over popup a string at the bottom of the screen
if ((mode == CClientConfig::SSysInfoParam::Over) || (mode == CClientConfig::SSysInfoParam::OverOnly))
InSceneBubbleManager.addMessagePopup(str, color);
InSceneBubbleManager.addMessagePopup(cleanStr, color);
else if ( (mode == CClientConfig::SSysInfoParam::Around || mode == CClientConfig::SSysInfoParam::CenterAround)
&& PeopleInterraction.AroundMe.Window)
PeopleInterraction.ChatInput.AroundMe.displayMessage(str, color, 2);
PeopleInterraction.ChatInput.AroundMe.displayMessage(cleanStr, color, 2);
}

@ -184,6 +184,21 @@ private:
REGISTER_ACTION_HANDLER(CHandlerLUA, "lua");
std::deque<CRefPtr<CCtrlBase> > CHandlerLUA::_UICallerStack;
// ***************************************************************************
class CHandlerSCRIPT : public IActionHandler
{
public:
void execute(CCtrlBase *pCaller, const std::string &sParams)
{
string script = sParams;
while(strFindReplace(script, "[", ""));
while(strFindReplace(script, "]", ""));
strFindReplace(script, "|", "\n");
CLuaManager::getInstance().executeLuaScript("\ngame:executeRyzomScript([["+script+"]])\n", true);
}
};
REGISTER_ACTION_HANDLER(CHandlerSCRIPT, "script");
// ***************************************************************************
// Allow also to call script from expression
static DECLARE_INTERFACE_USER_FCT(lua)
@ -566,6 +581,7 @@ void CLuaIHMRyzom::RegisterRyzomFunctions(NLGUI::CLuaState &ls)
LUABIND_FUNC(isFullyPatched),
LUABIND_FUNC(getSheetType),
LUABIND_FUNC(getSheetShape),
LUABIND_FUNC(getCharacterSheetScale),
LUABIND_FUNC(getSheetFamily),
LUABIND_FUNC(getSheetName),
LUABIND_FUNC(getFameIndex),
@ -3493,7 +3509,15 @@ std::string CLuaIHMRyzom::getSheetShape(const std::string &sheet)
return "";
}
// ***************************************************************************
float CLuaIHMRyzom::getCharacterSheetScale(const std::string &sheet)
{
const CEntitySheet *sheetPtr = SheetMngr.get(CSheetId(sheet));
const CCharacterSheet *charSheet = dynamic_cast<const CCharacterSheet*>(sheetPtr);
if (charSheet) return charSheet->Scale;
return 1;
}
// ***************************************************************************
std::string CLuaIHMRyzom::getSheetFamily(const std::string &sheet)
@ -3904,40 +3928,40 @@ sint32 CLuaIHMRyzom::getPlayerLevel()
// ***************************************************************************
std::string CLuaIHMRyzom::getPlayerVpaHex()
{
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E0:P" + toString("%d", CLFECOMMON::PROPERTY_VPA))->getValue64();
return NLMISC::toString("%X", prop);
sint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E0:P" + toString("%d", CLFECOMMON::PROPERTY_VPA))->getValue64();
return NLMISC::toString("%" NL_I64 "X", prop);
}
// ***************************************************************************
std::string CLuaIHMRyzom::getPlayerVpbHex()
{
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E0:P" + toString("%d", CLFECOMMON::PROPERTY_VPB))->getValue64();
return NLMISC::toString("%X", prop);
sint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E0:P" + toString("%d", CLFECOMMON::PROPERTY_VPB))->getValue64();
return NLMISC::toString("%" NL_I64 "X", prop);
}
// ***************************************************************************
std::string CLuaIHMRyzom::getPlayerVpcHex()
{
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E0:P" + toString("%d", CLFECOMMON::PROPERTY_VPC))->getValue64();
return NLMISC::toString("%X", prop);
sint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E0:P" + toString("%d", CLFECOMMON::PROPERTY_VPC))->getValue64();
return NLMISC::toString("%" NL_I64 "X", prop);
}
// ***************************************************************************
sint64 CLuaIHMRyzom::getPlayerVpa()
uint64 CLuaIHMRyzom::getPlayerVpa()
{
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E0:P" + toString("%d", CLFECOMMON::PROPERTY_VPA))->getValue64();
return prop;
}
// ***************************************************************************
sint64 CLuaIHMRyzom::getPlayerVpb()
uint64 CLuaIHMRyzom::getPlayerVpb()
{
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E0:P" + toString("%d", CLFECOMMON::PROPERTY_VPB))->getValue64();
return prop;
}
// ***************************************************************************
sint64 CLuaIHMRyzom::getPlayerVpc()
uint64 CLuaIHMRyzom::getPlayerVpc()
{
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E0:P" + toString("%d", CLFECOMMON::PROPERTY_VPC))->getValue64();
return prop;
@ -3989,8 +4013,8 @@ std::string CLuaIHMRyzom::getTargetVpaHex()
CEntityCL *target = getTargetEntity();
if (!target) return 0;
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPA))->getValue64();
return NLMISC::toString("%X", prop);
sint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPA))->getValue64();
return NLMISC::toString("%" NL_I64 "X", prop);
}
// ***************************************************************************
@ -3999,8 +4023,8 @@ std::string CLuaIHMRyzom::getTargetVpbHex()
CEntityCL *target = getTargetEntity();
if (!target) return 0;
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPB))->getValue64();
return NLMISC::toString("%X", prop);
sint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPB))->getValue64();
return NLMISC::toString("%" NL_I64 "X", prop);
}
// ***************************************************************************
@ -4009,40 +4033,37 @@ std::string CLuaIHMRyzom::getTargetVpcHex()
CEntityCL *target = getTargetEntity();
if (!target) return 0;
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPC))->getValue64();
return NLMISC::toString("%X", prop);
sint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPC))->getValue64();
return NLMISC::toString("%" NL_I64 "X", prop);
}
// ***************************************************************************
sint64 CLuaIHMRyzom::getTargetVpa()
uint64 CLuaIHMRyzom::getTargetVpa()
{
CEntityCL *target = getTargetEntity();
if (!target) return 0;
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPA))->getValue64();
return prop;
}
// ***************************************************************************
sint64 CLuaIHMRyzom::getTargetVpb()
uint64 CLuaIHMRyzom::getTargetVpb()
{
CEntityCL *target = getTargetEntity();
if (!target) return 0;
sint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPB))->getValue64();
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPB))->getValue64();
return prop;
}
// ***************************************************************************
sint64 CLuaIHMRyzom::getTargetVpc()
uint64 CLuaIHMRyzom::getTargetVpc()
{
CEntityCL *target = getTargetEntity();
if (!target) return 0;
sint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPC))->getValue64();
uint64 prop = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:Entities:E" + toString("%d", getTargetSlotNr()) + ":P" + toString("%d", CLFECOMMON::PROPERTY_VPC))->getValue64();
return prop;
}

@ -15,7 +15,7 @@ private:
static int luaClientCfgIndex(CLuaState &ls);
static int luaClientCfgNewIndex(CLuaState &ls);
// CInterfaceElement management on stack, stored by a CRefPtr.
public:
@ -204,6 +204,8 @@ private:
static bool isDynStringAvailable(sint32 dynStringId);
static bool isFullyPatched();
static std::string getSheetType(const std::string &sheet);
static std::string getSheetShape(const std::string &sheet);
static float getCharacterSheetScale(const std::string &sheet);
static std::string getSheetFamily(const std::string &sheet);
static std::string getSheetName(uint32 sheetId);
static sint32 getFameIndex(const std::string &factionName);
@ -251,7 +253,7 @@ private:
static int addRespawnPoint(CLuaState &ls);
static int delArkPoints(CLuaState &ls);
static int setArkPowoOptions(CLuaState &ls);
// open the window to do a tell to 'player', if 'msg' is not empty, then the message will be sent immediatly
// else, current command of the chat window will be replaced with tell 'player'
@ -260,7 +262,7 @@ private:
static void updateTooltipCoords();
// test if the ctrl key is down (NB nico : I didn't add other key,
// because it would be too easy to write a key recorder ...)
static bool isCtrlKeyDown();
static bool isCtrlKeyDown();
static std::string encodeURLUnicodeParam(const ucstring &text);
static std::string encodeURLParam(const std::string &text);
@ -271,9 +273,9 @@ private:
static std::string getPlayerVpaHex();
static std::string getPlayerVpbHex();
static std::string getPlayerVpcHex();
static sint64 getPlayerVpa();
static sint64 getPlayerVpb();
static sint64 getPlayerVpc();
static uint64 getPlayerVpa();
static uint64 getPlayerVpb();
static uint64 getPlayerVpc();
static sint32 getTargetLevel(); // get current, precise level of the selected target, or -1 if there's no such selected target
static sint32 getTargetForceRegion(); // get 'force region' for current target, or -1 if there's no selected target
static sint32 getTargetLevelForce(); // get 'level force' for current target, or -1 if there's no selected target
@ -281,9 +283,9 @@ private:
static std::string getTargetVpaHex();
static std::string getTargetVpbHex();
static std::string getTargetVpcHex();
static sint64 getTargetVpa();
static sint64 getTargetVpb();
static sint64 getTargetVpc();
static uint64 getTargetVpa();
static uint64 getTargetVpb();
static uint64 getTargetVpc();
static bool isTargetNPC(); // return 'true' if the target is an npc
static bool isTargetPlayer(); // return 'true' if the target is a player
static bool isTargetUser(); // return 'true' if the target is the user

@ -33,6 +33,7 @@
#include "game_share/chat_group.h"
#include "game_share/character_summary.h"
#include "game_share/sphrase_com.h"
#include "game_share/outpost.h"
#include "game_share/msg_client_server.h"
#include "game_share/ryzom_database_banks.h"
#include "game_share/msg_encyclopedia.h"
@ -3205,9 +3206,11 @@ void impulseUserBars(NLMISC::CBitMemStream &impulse)
void impulseOutpostChooseSide(NLMISC::CBitMemStream &impulse)
{
// read message
uint8 type;
bool outpostInFire;
bool playerGuildInConflict;
bool playerGuildIsAttacker;
impulse.serial(type);
impulse.serial(outpostInFire);
impulse.serial(playerGuildInConflict);
impulse.serial(playerGuildIsAttacker);
@ -3219,7 +3222,7 @@ void impulseOutpostChooseSide(NLMISC::CBitMemStream &impulse)
impulse.serial( declTimer );
// start
OutpostManager.startPvpJoinProposal(outpostInFire, playerGuildInConflict, playerGuildIsAttacker,
OutpostManager.startPvpJoinProposal((OUTPOSTENUMS::TPVPType)type, outpostInFire, playerGuildInConflict, playerGuildIsAttacker,
ownerGuildNameId, attackerGuildNameId, declTimer);
}

@ -680,6 +680,7 @@ bool CNetworkConnection::connect(string &result)
_LatestLoginTime = ryzomGetLocalTime ();
_LatestSyncTime = _LatestLoginTime;
_LatestProbeTime = _LatestLoginTime;
m_LoginAttempts = 0;
nlinfo("CNET[%p]: Client connected to shard, attempting login", this);
return true;
@ -1091,6 +1092,17 @@ bool CNetworkConnection::stateLogin()
{
sendSystemLogin();
_LatestLoginTime = _UpdateTime;
if (m_LoginAttempts > 24)
{
m_LoginAttempts = 0;
disconnect(); // will send disconnection message
nlwarning("CNET[%p]: Too many LOGIN attempts, connection problem", this);
return false; // exit now from loop, don't expect a new state
}
else
{
++m_LoginAttempts;
}
}
return false;
@ -2308,6 +2320,7 @@ bool CNetworkConnection::stateProbe()
else
{
nlwarning("CNET[%p]: received normal in state Probe", this);
_LatestProbeTime = _UpdateTime;
}
}
}

@ -822,6 +822,7 @@ private:
void sendSystemLogin();
bool stateLogin();
NLMISC::TTime _LatestLoginTime;
int m_LoginAttempts;
//
void receiveSystemSync(NLMISC::CBitMemStream &msgin);

@ -40,7 +40,7 @@ COutpostManager::COutpostManager()
// ***************************************************************************
void COutpostManager::startPvpJoinProposal(bool outpostInFire, bool playerGuildInConflict, bool playerGuildIsAttacker,
void COutpostManager::startPvpJoinProposal(OUTPOSTENUMS::TPVPType type, bool outpostInFire, bool playerGuildInConflict, bool playerGuildIsAttacker,
uint32 ownerGuildNameId, uint32 attackerGuildNameId, uint32 declTimer)
{
// reset counter that force player to be neutral (eg: 10 seconds)
@ -58,16 +58,28 @@ void COutpostManager::startPvpJoinProposal(bool outpostInFire, bool playerGuildI
node= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:PVP_PROPOSAL_DEFENDER");
if(node) node->setValue32(ownerGuildNameId);
node= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:PVP_PROPOSAL_TICK_END");
if(node) node->setValue32(_EndTickForPvpJoinProposal);
if(node) node->setValue32(_EndTickForPvpJoinProposal);
// open Popup
CCtrlBase *ctrl = dynamic_cast<CCtrlBase *>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_outpost_proposal:content:random"));
if (ctrl)
ctrl->setActive(outpostInFire);
ctrl->setActive(type != OUTPOSTENUMS::GVE && outpostInFire);
ctrl = dynamic_cast<CCtrlBase *>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_outpost_proposal:content:neutral"));
if (ctrl)
ctrl->setActive(!outpostInFire);
ctrl->setActive(type == OUTPOSTENUMS::GVE || !outpostInFire);
// GvE: only attacker guild can have the option
ctrl = dynamic_cast<CCtrlBase *>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_outpost_proposal:content:attack"));
if (ctrl && type == OUTPOSTENUMS::GVE)
ctrl->setActive(playerGuildIsAttacker);
// GvE : No defend option
ctrl = dynamic_cast<CCtrlBase *>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_outpost_proposal:content:defend"));
if (ctrl && type == OUTPOSTENUMS::GVE)
ctrl->setActive(false);
CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_outpost_proposal"));
if (pGC)

@ -40,7 +40,7 @@ public:
COutpostManager();
/// Called when the server ask to join for PVP in a Outpost Zone
void startPvpJoinProposal(bool outpostInFire, bool playerGuildInConflict, bool playerGuildIsAttacker,
void startPvpJoinProposal(OUTPOSTENUMS::TPVPType type, bool outpostInFire, bool playerGuildInConflict, bool playerGuildIsAttacker,
uint32 ownerGuildNameId, uint32 attackerGuildNameId, uint32 declTimer);
/// Called when the client answer to the join for PVP in a Outpost Zone

@ -264,6 +264,19 @@ namespace BRICK_FAMILIES
NL_STRING_CONVERSION_TABLE_ENTRY(BCOKARM02)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOKARR02)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOKART02)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOMARM01)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOMARR01)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOMART01)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOMARM02)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOMARR02)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOMART02)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOGENM01)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOGENR01)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOGENT01)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOGENM02)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOGENR02)
NL_STRING_CONVERSION_TABLE_ENTRY(BCOGENT02)
// Faber options
NL_STRING_CONVERSION_TABLE_ENTRY(BCOA)
@ -558,6 +571,7 @@ namespace BRICK_FAMILIES
NL_STRING_CONVERSION_TABLE_ENTRY(BSCMC)
NL_STRING_CONVERSION_TABLE_ENTRY(BSCMD)
NL_STRING_CONVERSION_TABLE_ENTRY(BSGMC)
NL_STRING_CONVERSION_TABLE_ENTRY(BSGMCB)
NL_STRING_CONVERSION_TABLE_ENTRY(BSXCA)

@ -297,7 +297,20 @@ namespace BRICK_FAMILIES
BCOKARM02,
BCOKARR02,
BCOKART02,
EndFaberMandatory = BCOKART02,
BCOMARM01,
BCOMARR01,
BCOMART01,
BCOMARM02,
BCOMARR02,
BCOMART02,
BCOGENM01,
BCOGENR01,
BCOGENT01,
BCOGENM02,
BCOGENR02,
BCOGENT02,
EndFaberMandatory = BCOGENT02,
// OPTION FABER
BeginFaberOption,
@ -675,7 +688,8 @@ namespace BRICK_FAMILIES
BSCMD, // heal Focus
EndPowerParameter = BSCMD,
BSGMC, // jewels s2e0
BSGMC, // allegories
BSGMCB, // boost allegories
BeginMagicPowerCredit,
BSXCA = BeginMagicPowerCredit, // recast time

@ -323,19 +323,6 @@ namespace EFFECT_FAMILIES
{ "thorn_wall_aura.sbrick", PowerThornWall },
{ "water_wall_aura.sbrick", PowerWaterWall },
{ "lightning_wall_aura.sbrick", PowerLightningWall },
{ "life_aura.sbrick", PowerRootLifeAura },
{ "stamina_aura.sbrick", PowerRootStaminaAura },
{ "sap_aura.sbrick", PowerRootSapAura },
{ "umbrella_aura.sbrick", PowerRootUmbrella },
{ "melee_protection_aura.sbrick", PowerRootProtection },
{ "anti_magic_shield_aura.sbrick", PowerRootAntiMagicShield },
{ "war_cry_aura.sbrick", PowerRootWarCry },
{ "fire_wall_aura.sbrick", PowerRootFireWall },
{ "thorn_wall_aura.sbrick", PowerRootThornWall },
{ "water_wall_aura.sbrick", PowerRootWaterWall },
{ "lightning_wall_aura.sbrick", PowerRootLightningWall },
{ "chg_charac.sbrick", PowerChgCharac },
{ "mod_defense.sbrick", PowerModDefenseSkill },
{ "mod_dodge.sbrick", PowerModDodgeSkill },

@ -534,7 +534,7 @@ void CStaticFames::loadTribeThreshold( const string& filename )
// check table structure
uint nbTribe = ws.size()-2;
nlassert(nbTribe<=_FameTableSize);
nlassert(ws.ColCount == 16); // 5 ( 4 people + neutral ) * 3 cult + 1 for tribe name
nlassert(ws.ColCount == 17); // 5 ( 4 people + neutral ) * 3 cult + 1 for tribe name + marauder
_TribeCultThresholdPerCiv.resize(nbTribe);
@ -548,7 +548,7 @@ void CStaticFames::loadTribeThreshold( const string& filename )
_TribeCultThresholdPerCiv[i-2].FameIndex = index;
for( uint c=1; c<ws.ColCount; c+=3)
for( uint c=1; c<ws.ColCount-1; c+=3)
{
sint32 thresholdKami, thresholdKaravan, thresholdNeutral;
fromString(ws.getData(i, c).toString(), thresholdKami);
@ -585,6 +585,15 @@ void CStaticFames::loadTribeThreshold( const string& filename )
// This message removed by Sadge because there is no context displayed, meaning that message must be useless
// nldebug(" %s", ws.getData(i, c).toString().c_str() );
}
// Special case for Marauders
sint32 thresholdMarauder;
fromString(ws.getData(i, ws.ColCount-1).toString(), thresholdMarauder);
CTribeCultThreshold * tc;
tc = &_TribeCultThresholdPerCiv[i-2].Marauder;
tc->setMarauder(thresholdMarauder*6000);
}
}
}
@ -624,7 +633,7 @@ sint32 CStaticFames::getStaticFameIndexed(uint factionIndex1, uint factionIndex2
if (factionIndex1 >= _FameTableSize || factionIndex2 >= _FameTableSize)
{
nlwarning("FAME: CStaticFames::getStaticFame invalid faction, return 0");
//nlwarning("FAME: CStaticFames::getStaticFame invalid faction, return 0");
return 0;
}

@ -52,26 +52,30 @@ public:
Kami = 0;
Karavan = 0;
Neutral = 0;
Marauder = 0;
}
void setKami(sint32 t) { Kami = t; }
void setKaravan(sint32 t) { Karavan = t; }
void setNeutral(sint32 t) { Neutral = t; }
void setMarauder(sint32 t) { Marauder = t; }
sint32 getKami() const { return Kami; }
sint32 getKaravan() const { return Karavan; }
sint32 getNeutral() const { return Neutral; }
sint32 getMarauder() const { return Marauder; }
private:
sint32 Kami;
sint32 Karavan;
sint32 Neutral;
sint32 Marauder;
};
class CTribeCultThresholdPerCiv
{
public:
bool getCultThresholdForCiv( PVP_CLAN::TPVPClan civ, sint32& kami, sint32& karavan, sint32& neutral) const
bool getCultThresholdForCiv( PVP_CLAN::TPVPClan civ, sint32& kami, sint32& karavan, sint32& neutral, sint32& marauder) const
{
const CTribeCultThreshold * tc = 0;
switch( civ )
@ -88,12 +92,16 @@ public:
case PVP_CLAN::Neutral:
tc = &Neutral;
break;
case PVP_CLAN::Marauder:
tc = &Marauder;
break;
default:
return false;
}
kami = tc->getKami();
karavan = tc->getKaravan();
neutral = tc->getNeutral();
marauder = tc->getMarauder();
return true;
}
@ -103,6 +111,7 @@ public:
CTribeCultThreshold Tryker;
CTribeCultThreshold Zorai;
CTribeCultThreshold Neutral;
CTribeCultThreshold Marauder;
};
// declare scoped constant value

@ -136,6 +136,7 @@ namespace MAGICFX
OtherFireWall = 14,
TeleportKami = 15, // No effect aura
TeleportKara = 16, // No effect aura
TeleportMarauder = 17, // No effect aura
};
}

@ -32,6 +32,8 @@ namespace OUTPOSTENUMS
NL_STRING_CONVERSION_TABLE_ENTRY(PVP)
NL_STRING_CONVERSION_TABLE_ENTRY(RVR)
NL_STRING_CONVERSION_TABLE_ENTRY(Full)
NL_STRING_CONVERSION_TABLE_ENTRY(GVE)
NL_STRING_CONVERSION_TABLE_ENTRY(GVG)
NL_STRING_CONVERSION_TABLE_ENTRY(UnknownPVPType)
NL_END_STRING_CONVERSION_TABLE(TPVPType, StaticCOutpostTPVPTypeConversion, UnknownPVPType)

@ -50,7 +50,9 @@ namespace OUTPOSTENUMS
PVE, // can only be attacked if the outpost is held by a tribe and if the attacking guild comes from the same continent as the outpost
PVP, // can only be attacked if the attacking guild comes from the same continent as the outpost
RVR, // can only be attacked if the attacking guild comes from another continent as the outpost
Full // same as RVR but cant be set by the high council
Full, // same as RVR but cant be set by the high council
GVE, // Only one guild vs tribes
GVG, // Only one guild vs another guild
};
enum TPVPSide

@ -37,7 +37,7 @@ struct SPropVisualA
uint64 JacketColor : 3; // max: 8 current: 8
uint64 TrouserModel : 8; // max: 256 current: 104
uint64 TrouserColor : 3; // max: 8 current: 8
uint64 WeaponRightHand : 10; // max: 1024 current: 457
uint64 WeaponRightHand : 10; // max: 1024 current: 625
uint64 WeaponLeftHand : 8; // max: 256 current: 63
uint64 ArmModel : 8; // max: 256 current: 94
uint64 ArmColor : 3; // max: 8 current: 8

Loading…
Cancel
Save