Changed: Display stat buff and enchant info on item icon

--HG--
branch : feature-item-icon-buffs
hg/atys
Nimetu 6 years ago
parent e0a1cd3c4a
commit 2f883ddb1d

@ -75,52 +75,52 @@ const uint64 NOTIFY_ANIM_MS_DURATION = 1000;
// *************************************************************************** // ***************************************************************************
void CControlSheetInfoWaiter::sendRequest()
// **********************************************************************************************************
class CControlSheetTooltipInfoWaiter : public IItemInfoWaiter
{ {
public: Requesting = true;
// The item used to open this window getInventory().addItemInfoWaiter(this);
CDBCtrlSheet* CtrlSheet; }
string LuaMethodName;
public:
ucstring infoValidated(CDBCtrlSheet* ctrlSheet, string luaMethodName);
virtual void infoReceived();
};
static CControlSheetTooltipInfoWaiter ControlSheetTooltipUpdater;
void CControlSheetTooltipInfoWaiter::infoReceived() void CControlSheetInfoWaiter::infoReceived()
{ {
getInventory().removeItemInfoWaiter(&ControlSheetTooltipUpdater); if (!Requesting) {
infoValidated(CtrlSheet, LuaMethodName); return;
}
getInventory().removeItemInfoWaiter(this);
infoValidated();
CtrlSheet->infoReceived();
Requesting = false;
} }
ucstring CControlSheetTooltipInfoWaiter::infoValidated(CDBCtrlSheet* ctrlSheet, string luaMethodName) ucstring CControlSheetInfoWaiter::infoValidated() const
{ {
ucstring help; ucstring help;
// delegate setup of context he help ( & window ) to lua if (CtrlSheet && !LuaMethodName.empty())
CInterfaceManager *im = CInterfaceManager::getInstance();
CLuaState *ls= CLuaManager::getInstance().getLuaState();
{ {
CLuaStackRestorer lsr(ls, 0); // delegate setup of context he help ( & window ) to lua
CInterfaceManager *im = CInterfaceManager::getInstance();
CLuaState *ls= CLuaManager::getInstance().getLuaState();
{
CLuaStackRestorer lsr(ls, 0);
CLuaIHM::pushReflectableOnStack(*ls, (CReflectableRefPtrTarget *)ctrlSheet); CLuaIHM::pushReflectableOnStack(*ls, (CReflectableRefPtrTarget *)CtrlSheet);
ls->pushGlobalTable(); ls->pushGlobalTable();
CLuaObject game(*ls); CLuaObject game(*ls);
game = game["game"]; game = game["game"];
game.callMethodByNameNoThrow(luaMethodName.c_str(), 1, 1); game.callMethodByNameNoThrow(LuaMethodName.c_str(), 1, 1);
// retrieve result from stack // retrieve result from stack
if (!ls->empty()) if (!ls->empty())
{ {
CLuaIHM::pop(*ls, help); CLuaIHM::pop(*ls, help);
} }
else else
{ {
nlwarning(toString("Ucstring result expected when calling '%s', possible script error", luaMethodName.c_str()).c_str()); nlwarning(toString("Ucstring result expected when calling '%s', possible script error", LuaMethodName.c_str()).c_str());
}
} }
} }
@ -137,7 +137,7 @@ int CDBCtrlSheet::luaGetDraggedSheet(CLuaState &ls)
// *************************************************************************** // ***************************************************************************
int CDBCtrlSheet::luaGetItemInfo(CLuaState &ls) int CDBCtrlSheet::luaGetItemInfo(CLuaState &ls)
{ {
CDBCtrlSheet *ctrlSheet = const_cast<CDBCtrlSheet*>(this); CDBCtrlSheet *ctrlSheet = const_cast<CDBCtrlSheet *>(this);
uint32 itemSlotId = getInventory().getItemSlotId(ctrlSheet); uint32 itemSlotId = getInventory().getItemSlotId(ctrlSheet);
CClientItemInfo itemInfo = getInventory().getItemInfo(itemSlotId); CClientItemInfo itemInfo = getInventory().getItemInfo(itemSlotId);
@ -203,7 +203,7 @@ int CDBCtrlSheet::luaGetCreatorName(CLuaState &ls)
ucstring creatorName; ucstring creatorName;
STRING_MANAGER::CStringManagerClient::instance()->getString(itemInfo.CreatorName, creatorName); STRING_MANAGER::CStringManagerClient::instance()->getString(itemInfo.CreatorName, creatorName);
CLuaIHM::push(ls, creatorName); CLuaIHM::push(ls, creatorName);
return 1; return 1;
} }
@ -236,7 +236,6 @@ int CDBCtrlSheet::luaWaitInfo(CLuaState &ls)
// *************************************************************************** // ***************************************************************************
int CDBCtrlSheet::luaBuildCrystallizedSpellListBrick(CLuaState &ls) int CDBCtrlSheet::luaBuildCrystallizedSpellListBrick(CLuaState &ls)
{ {
CDBCtrlSheet *ctrlSheet = const_cast<CDBCtrlSheet*>(this); CDBCtrlSheet *ctrlSheet = const_cast<CDBCtrlSheet*>(this);
uint32 itemSlotId= getInventory().getItemSlotId(ctrlSheet); uint32 itemSlotId= getInventory().getItemSlotId(ctrlSheet);
@ -257,7 +256,7 @@ int CDBCtrlSheet::luaBuildCrystallizedSpellListBrick(CLuaState &ls)
} }
} }
// Reset other to 0. // Reset other to 0.
for(;;currentBrick++) for(;;currentBrick++)
{ {
@ -505,6 +504,7 @@ CCtrlDraggable(param)
_Useable= true; _Useable= true;
_GrayedLink= NULL; _GrayedLink= NULL;
_NeedSetup= true; _NeedSetup= true;
_ItemInfoChanged = true;
_IconW = 0; _IconW = 0;
_IconH = 0; _IconH = 0;
_SetupInit= false; _SetupInit= false;
@ -528,6 +528,11 @@ CCtrlDraggable(param)
_ItemRMClassType= NULL; _ItemRMClassType= NULL;
_ItemRMFaberStatType= NULL; _ItemRMFaberStatType= NULL;
_NotifyAnimEndTime = 0; _NotifyAnimEndTime = 0;
_HpBuffIcon = "ico_heal.tga";
_SapBuffIcon = "ico_sap.tga";
_StaBuffIcon = "ico_stamina.tga";
_FocusBuffIcon = "ico_focus.tga";
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -535,6 +540,11 @@ CDBCtrlSheet::~CDBCtrlSheet()
{ {
NL3D::UDriver *Driver = CViewRenderer::getInstance()->getDriver(); NL3D::UDriver *Driver = CViewRenderer::getInstance()->getDriver();
if (_ItemInfoWaiter.Requesting)
{
getInventory().removeItemInfoWaiter(&_ItemInfoWaiter);
}
if (_GuildBack) if (_GuildBack)
{ {
if (Driver) if (Driver)
@ -613,6 +623,22 @@ bool CDBCtrlSheet::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup)
prop = (char*) xmlGetProp( cur, (xmlChar*)"slot" ); prop = (char*) xmlGetProp( cur, (xmlChar*)"slot" );
if(prop) _DrawSlot= CInterfaceElement::convertBool(prop); if(prop) _DrawSlot= CInterfaceElement::convertBool(prop);
//
_HpBuffIcon = "ico_heal.tga";
prop = (char*) xmlGetProp( cur, (xmlChar*)"hp_buff_icon" );
if (prop) _HpBuffIcon = string((const char *)prop);
_SapBuffIcon = "ico_sap.tga";
prop = (char*) xmlGetProp( cur, (xmlChar*)"sap_buff_icon" );
if (prop) _SapBuffIcon = string((const char *)prop);
_StaBuffIcon = "ico_stamina.tga";
prop = (char*) xmlGetProp( cur, (xmlChar*)"sta_buff_icon" );
if (prop) _StaBuffIcon = string((const char *)prop);
_FocusBuffIcon = "ico_focus.tga";
prop = (char*) xmlGetProp( cur, (xmlChar*)"focus_buff_icon" );
if (prop) _FocusBuffIcon = string((const char *)prop);
updateActualType(); updateActualType();
// Init size for Type // Init size for Type
@ -1040,6 +1066,64 @@ void CDBCtrlSheet::updateIconSize()
} }
} }
// ***************************************************************************
void CDBCtrlSheet::infoReceived()
{
if (!_ItemSheet)
{
return;
}
const CClientItemInfo *itemInfo = getInventory().getItemInfoCache(getItemSerial(), getItemCreateTime());
if (itemInfo == NULL)
{
// schedule for recheck on next draw()
_ItemInfoChanged = true;
return;
}
// crystallized spell
{
_EnchantIcons.clear();
CViewRenderer &rVR = *CViewRenderer::getInstance();
CSBrickManager *pBM= CSBrickManager::getInstance();
for(uint i=0; i<itemInfo->Enchantment.Bricks.size(); ++i)
{
const CSBrickSheet *brick = pBM->getBrick(itemInfo->Enchantment.Bricks[i]);
if (brick)
{
if (!brick->isRoot() && !brick->isCredit() && !brick->isParameter())
{
_EnchantIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(brick->getIcon()), brick->IconColor));
rVR.getTextureSizeFromId(_EnchantIcons.back().TextureId, _EnchantIcons.back().IconW, _EnchantIcons.back().IconH);
}
else if (brick->isRoot())
{
// there should be single root icon and it should be first one
_EnchantIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(brick->getIconBack()), brick->IconBackColor));
rVR.getTextureSizeFromId(_EnchantIcons.back().TextureId, _EnchantIcons.back().IconW, _EnchantIcons.back().IconH);
}
}
}
}
// buff icons
{
_BuffIcons.clear();
CViewRenderer &rVR = *CViewRenderer::getInstance();
if (itemInfo->HpBuff > 0) _BuffIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(_HpBuffIcon)));
if (itemInfo->SapBuff > 0) _BuffIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(_SapBuffIcon)));
if (itemInfo->StaBuff > 0) _BuffIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(_StaBuffIcon)));
if (itemInfo->FocusBuff > 0) _BuffIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(_FocusBuffIcon)));
// update sizes
for(uint i = 0; i < _BuffIcons.size(); ++i)
{
rVR.getTextureSizeFromId(_BuffIcons[i].TextureId, _BuffIcons[i].IconW, _BuffIcons[i].IconH);
}
}
}
// *************************************************************************** // ***************************************************************************
void CDBCtrlSheet::setupPact() void CDBCtrlSheet::setupPact()
@ -1103,6 +1187,7 @@ void CDBCtrlSheet::setupItem ()
CInterfaceManager *pIM= CInterfaceManager::getInstance(); CInterfaceManager *pIM= CInterfaceManager::getInstance();
sint32 sheet = _SheetId.getSInt32(); sint32 sheet = _SheetId.getSInt32();
// If this is the same sheet, need to resetup // If this is the same sheet, need to resetup
if (_LastSheetId != sheet || _NeedSetup) if (_LastSheetId != sheet || _NeedSetup)
{ {
@ -1203,6 +1288,9 @@ void CDBCtrlSheet::setupItem ()
// Special Item requirement // Special Item requirement
updateItemCharacRequirement(_LastSheetId); updateItemCharacRequirement(_LastSheetId);
// update item info markers
_ItemInfoChanged = true;
} }
else else
{ {
@ -1277,6 +1365,13 @@ void CDBCtrlSheet::setupItem ()
_Useable = CSkillManager::getInstance()->checkBaseSkillMetRequirement(_ItemSheet->RequiredSkill, _ItemSheet->RequiredSkillLevel); _Useable = CSkillManager::getInstance()->checkBaseSkillMetRequirement(_ItemSheet->RequiredSkill, _ItemSheet->RequiredSkillLevel);
} }
*/ */
// at each frame, update item info icon if changed
if (_ItemInfoChanged)
{
_ItemInfoChanged = false;
setupItemInfoWaiter();
}
} }
@ -1857,7 +1952,7 @@ void CDBCtrlSheet::draw()
CInterfaceManager *pIM = CInterfaceManager::getInstance(); CInterfaceManager *pIM = CInterfaceManager::getInstance();
CViewRenderer &rVR = *CViewRenderer::getInstance(); CViewRenderer &rVR = *CViewRenderer::getInstance();
if (_Type != SheetType_Macro) if (_Type != SheetType_Macro)
{ {
if (_LastSheetId != _SheetId.getSInt32()) if (_LastSheetId != _SheetId.getSInt32())
@ -1949,13 +2044,13 @@ void CDBCtrlSheet::draw()
rVR.getTextureSizeFromId(frontTex, texWidth, texHeight); rVR.getTextureSizeFromId(frontTex, texWidth, texHeight);
CQuadUV regenTris[5]; CQuadUV regenTris[5];
uint numTris = buildPie(regenTris, 0.f, amount, texWidth); uint numTris = buildPie(regenTris, 0.f, amount, texWidth);
nlassert(numTris <= sizeofarray(regenTris)); nlassert(numTris <= sizeofarray(regenTris));
for (uint tri = 0; tri < numTris; ++tri) for (uint tri = 0; tri < numTris; ++tri)
{ {
rVR.drawQuad(_RenderLayer + 1, regenTris[tri], frontTex, CRGBA::White, false); rVR.drawQuad(_RenderLayer + 1, regenTris[tri], frontTex, CRGBA::White, false);
} }
numTris = buildPie(regenTris, amount, 1.f, texWidth); numTris = buildPie(regenTris, amount, 1.f, texWidth);
nlassert(numTris <= sizeofarray(regenTris)); nlassert(numTris <= sizeofarray(regenTris));
for (uint tri = 0; tri < numTris; ++tri) for (uint tri = 0; tri < numTris; ++tri)
{ {
@ -1977,7 +2072,7 @@ void CDBCtrlSheet::draw()
if (texId != -1) if (texId != -1)
{ {
sint32 texWidth, texHeight; sint32 texWidth, texHeight;
rVR.getTextureSizeFromId(texId, texWidth, texHeight); rVR.getTextureSizeFromId(texId, texWidth, texHeight);
const float freq0 = 1.f; const float freq0 = 1.f;
const float phase0 = 0.f; const float phase0 = 0.f;
const float freq1 = -1.f; const float freq1 = -1.f;
@ -1994,20 +2089,20 @@ void CDBCtrlSheet::draw()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void CDBCtrlSheet::drawRotatedQuad(CViewRenderer &vr, float angle, float scale, uint renderLayer, uint32 texId, sint32 texWidth, sint32 texHeight) void CDBCtrlSheet::drawRotatedQuad(CViewRenderer &vr, float angle, float scale, uint renderLayer, uint32 texId, sint32 texWidth, sint32 texHeight)
{ {
NLMISC::CQuadUV quv; NLMISC::CQuadUV quv;
float cosA = cosf(angle); float cosA = cosf(angle);
float sinA = sinf(angle); float sinA = sinf(angle);
// //
quv.V0.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (- cosA + sinA), quv.V0.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (- cosA + sinA),
_YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (- sinA - cosA), 0.5f); _YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (- sinA - cosA), 0.5f);
// //
quv.V1.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (cosA + sinA), quv.V1.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (cosA + sinA),
_YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (sinA - cosA), 0.5f); _YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (sinA - cosA), 0.5f);
// //
quv.V2.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (cosA - sinA), quv.V2.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (cosA - sinA),
_YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (sinA + cosA), 0.5f); _YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (sinA + cosA), 0.5f);
// //
quv.V3.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (- cosA - sinA), quv.V3.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (- cosA - sinA),
_YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (- sinA + cosA), 0.5f); _YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (- sinA + cosA), 0.5f);
// //
quv.Uv0.set(0.f, 0.f); quv.Uv0.set(0.f, 0.f);
@ -2022,13 +2117,13 @@ void CDBCtrlSheet::drawRotatedQuad(CViewRenderer &vr, float angle, float scale,
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
inline void CDBCtrlSheet::uvToScreen(float x, float y, CVector &screenPos, uint texSize) const inline void CDBCtrlSheet::uvToScreen(float x, float y, CVector &screenPos, uint texSize) const
{ {
screenPos.set(_XReal + texSize * x, _YReal + texSize * (1.f - y), 0.5f); screenPos.set(_XReal + texSize * x, _YReal + texSize * (1.f - y), 0.5f);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void CDBCtrlSheet::buildPieCorner(float angle, CUV &uv, CVector &pos, uint texSize) const void CDBCtrlSheet::buildPieCorner(float angle, CUV &uv, CVector &pos, uint texSize) const
{ {
float radAngle = angle * 2.f * float(NLMISC::Pi); float radAngle = angle * 2.f * float(NLMISC::Pi);
// angle origin is at 12'o'clock // angle origin is at 12'o'clock
float x = cosf(0.5f * float(NLMISC::Pi) - radAngle); float x = cosf(0.5f * float(NLMISC::Pi) - radAngle);
@ -2061,33 +2156,33 @@ void CDBCtrlSheet::buildPieCorner(float angle, CUV &uv, CVector &pos, uint texSi
y /= -x; y /= -x;
x = -1.f; x = -1.f;
} }
} }
// remap to unit quad // remap to unit quad
// (well we could have worked with tan() too, I find it simpler this way ....) // (well we could have worked with tan() too, I find it simpler this way ....)
uv.set(0.5f * x + 0.5f, 0.5f - 0.5f * y); uv.set(0.5f * x + 0.5f, 0.5f - 0.5f * y);
uvToScreen(uv.U, uv.V, pos, texSize); uvToScreen(uv.U, uv.V, pos, texSize);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
uint CDBCtrlSheet::buildPie(CQuadUV *triPtr, float startAngle, float endAngle, uint texSize) uint CDBCtrlSheet::buildPie(CQuadUV *triPtr, float startAngle, float endAngle, uint texSize)
{ {
static volatile bool exit1 = false; static volatile bool exit1 = false;
nlassert(startAngle <= endAngle); nlassert(startAngle <= endAngle);
const sint32 factor = 65536; const sint32 factor = 65536;
const float invFactor = 1.f / factor; const float invFactor = 1.f / factor;
sint32 iCurr = (uint32) (startAngle * factor) ; sint32 iCurr = (uint32) (startAngle * factor) ;
sint32 iEnd = (uint32) (endAngle * factor); sint32 iEnd = (uint32) (endAngle * factor);
clamp(iCurr, 0, factor); clamp(iCurr, 0, factor);
clamp(iEnd, 0, factor); clamp(iEnd, 0, factor);
uint triCount = 0; uint triCount = 0;
CVector quadCenter; CVector quadCenter;
uvToScreen(0.5f, 0.5f, quadCenter, texSize); uvToScreen(0.5f, 0.5f, quadCenter, texSize);
while (iCurr != iEnd) while (iCurr != iEnd)
{ {
sint32 iNext = iCurr + (factor / 4); sint32 iNext = iCurr + (factor / 4);
iNext -= ((iNext - factor / 8) % (factor / 4)); // snap to nearest corner iNext -= ((iNext - factor / 8) % (factor / 4)); // snap to nearest corner
iNext = std::min(iNext, iEnd); iNext = std::min(iNext, iEnd);
// well, not really a quad, but we don't have yet simple triangles rendering in the ui // well, not really a quad, but we don't have yet simple triangles rendering in the ui
triPtr->Uv0.set(0.5f, 0.5f); triPtr->Uv0.set(0.5f, 0.5f);
triPtr->V0 = quadCenter; triPtr->V0 = quadCenter;
@ -2220,6 +2315,69 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti
rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, _DispOver2BmpId, fastMulRGB(curSheetColor, _IconOver2Color)); rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, _DispOver2BmpId, fastMulRGB(curSheetColor, _IconOver2Color));
} }
if (!_BuffIcons.empty())
{
// there is max 4 icons
sint32 hArea = (hSheet / 4);
sint32 xIcon = x;
sint32 yIcon = y;
for (uint i = 0; i < _BuffIcons.size(); ++i)
{
sint32 wIcon = _BuffIcons[i].IconW;
sint32 hIcon = _BuffIcons[i].IconH;
if (hIcon > hArea)
{
wIcon = wIcon * ((float)hArea / hIcon);
hIcon = hArea;
}
rVR.drawRotFlipBitmap (_RenderLayer+1, xIcon, yIcon, wIcon, hIcon, 0, false, _BuffIcons[i].TextureId, fastMulRGB(curSheetColor, _BuffIcons[i].Color));
xIcon += wIcon;
// move up the row for 3rd/4th icon
if (i % 3 == 1) {
xIcon = x;
yIcon += hIcon;
}
}
}
// Is the item enchanted ?
sint32 enchant = _Enchant.getSInt32();
if (enchant > 0)
{
// Yes draw the additionnal bitmap and the charge (number of enchanted spell we can launch with the enchanted item)
enchant--;
rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, rVR.getSystemTextureId(CViewRenderer::ItemEnchantedTexture), curSheetColor);
drawNumber(x+1, y-2+hSheet-rVR.getFigurTextureH(), wSheet, hSheet, numberColor, enchant, false);
}
if (!_EnchantIcons.empty())
{
// should only only 2 icons at most
// draw them in single line, top-right
sint32 hArea = (hSheet / 3);
sint32 xIcon = x + wSheet - 1;
sint32 yIcon = y + hSheet - 1/* - hArea*/;
// 0 is expected to be background
for (uint i = 1; i < _EnchantIcons.size(); ++i)
{
sint32 wIcon = _EnchantIcons[i].IconW;
sint32 hIcon = _EnchantIcons[i].IconH;
if (hIcon > hArea)
{
wIcon = wIcon * ((float)hArea / hIcon);
hIcon = hArea;
}
// need to move x before draw because of right aligned
if (i == 1)
{
xIcon -= wIcon;
}
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));
}
}
// Draw Quality. -1 for lookandfeel. Draw it with global color // Draw Quality. -1 for lookandfeel. Draw it with global color
if (_DispQuality != -1) if (_DispQuality != -1)
{ {
@ -2242,15 +2400,6 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti
} }
drawNumber(x+1+crossW, y+1, wSheet, hSheet, curSheetColor, quantity, false); drawNumber(x+1+crossW, y+1, wSheet, hSheet, curSheetColor, quantity, false);
} }
// Is the item enchanted ?
sint32 enchant = _Enchant.getSInt32();
if (enchant > 0)
{
// Yes draw the additionnal bitmap and the charge (number of enchanted spell we can launch with the enchanted item)
enchant--;
rVR.draw11RotFlipBitmap (_RenderLayer+2, x, y, 0, false, rVR.getSystemTextureId(CViewRenderer::ItemEnchantedTexture), curSheetColor);
drawNumber(x+1, y-2+hSheet-rVR.getFigurTextureH(), wSheet, hSheet, numberColor, enchant, false);
}
// if a raw material for example, must add special icon text. // if a raw material for example, must add special icon text.
displayCharBitmaps(_RenderLayer+2, x, y, curSheetColor); displayCharBitmaps(_RenderLayer+2, x, y, curSheetColor);
@ -2348,8 +2497,8 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti
case SheetType_SPhrase : setupSPhrase(); break; case SheetType_SPhrase : setupSPhrase(); break;
default: nlassert(true); break; default: nlassert(true); break;
} }
bool showOutOfRangeSymbol = false; bool showOutOfRangeSymbol = false;
bool forceGrayed = false; bool forceGrayed = false;
@ -2361,15 +2510,15 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti
{ {
CSPhraseManager *pPM= CSPhraseManager::getInstance(); CSPhraseManager *pPM= CSPhraseManager::getInstance();
const CSPhraseCom &phrase= pPM->getPhrase(phraseId); const CSPhraseCom &phrase= pPM->getPhrase(phraseId);
// get the phrase Data version, to check if it had changed. // get the phrase Data version, to check if it had changed.
uint32 totalActionMalus = pPM->getTotalActionMalus(phrase); uint32 totalActionMalus = pPM->getTotalActionMalus(phrase);
uint8 targetSlot = UserEntity->targetSlot(); uint8 targetSlot = UserEntity->targetSlot();
if (targetSlot < CLFECOMMON::INVALID_SLOT) if (targetSlot < CLFECOMMON::INVALID_SLOT)
{ {
CEntityCL *target = EntitiesMngr.entity(targetSlot); CEntityCL *target = EntitiesMngr.entity(targetSlot);
if (target && UserEntity) if (target && UserEntity)
{ {
double dist2 = (target->pos() - UserEntity->pos()).sqrnorm(); double dist2 = (target->pos() - UserEntity->pos()).sqrnorm();
CSBrickManager *pBM= CSBrickManager::getInstance(); CSBrickManager *pBM= CSBrickManager::getInstance();
CSBrickSheet *rootBrick= NULL; CSBrickSheet *rootBrick= NULL;
if(phrase.Bricks.size()) if(phrase.Bricks.size())
@ -2396,7 +2545,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti
break; break;
} }
} }
if (!isPrimalMagic) if (!isPrimalMagic)
{ {
forceGrayed = !(target->isPlayer() && target->isFriend()); forceGrayed = !(target->isPlayer() && target->isFriend());
@ -2405,21 +2554,21 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti
{ {
forceGrayed = false; forceGrayed = false;
} }
} }
if (!forceGrayed) if (!forceGrayed)
{ {
sint phraseRange; sint phraseRange;
sint rangeMalus; sint rangeMalus;
pPM->getPhraseMagicRange(phrase, totalActionMalus, phraseRange, rangeMalus); pPM->getPhraseMagicRange(phrase, totalActionMalus, phraseRange, rangeMalus);
double rangeDist = (float) (phraseRange + rangeMalus); double rangeDist = (float) (phraseRange + rangeMalus);
if (phraseRange != 0) // if range is '0' then it is a 'self' action if (phraseRange != 0) // if range is '0' then it is a 'self' action
{ {
rangeDist += 0.5 + target->getSheetScale() * target->getSheetColRadius(); // player radius rangeDist += 0.5 + target->getSheetScale() * target->getSheetColRadius(); // player radius
if (dist2 > rangeDist * rangeDist) if (dist2 > rangeDist * rangeDist)
{ {
showOutOfRangeSymbol = true; showOutOfRangeSymbol = true;
} }
} }
} }
@ -2451,11 +2600,11 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti
if (isTaunt && !forceGrayed) if (isTaunt && !forceGrayed)
{ {
double rangeDist = (float) maxRange; double rangeDist = (float) maxRange;
rangeDist += 0.5 + target->getSheetScale() * target->getSheetColRadius(); // player radius rangeDist += 0.5 + target->getSheetScale() * target->getSheetColRadius(); // player radius
if (dist2 > rangeDist * rangeDist) if (dist2 > rangeDist * rangeDist)
{ {
showOutOfRangeSymbol = true; showOutOfRangeSymbol = true;
} }
} }
} }
@ -2522,15 +2671,15 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti
// if the pointer is over the button // if the pointer is over the button
if (_Over) if (_Over)
// Draw -1,-1 because the slot over is 26x26 // Draw -1,-1 because the slot over is 26x26
rVR.draw11RotFlipBitmap (_RenderLayer+1, x-1, y-1, 0, false, _TextureIdOver, curSheetColor ); rVR.draw11RotFlipBitmap (_RenderLayer+1, x-1, y-1, 0, false, _TextureIdOver, curSheetColor );
} }
if (showOutOfRangeSymbol) if (showOutOfRangeSymbol)
{ {
rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, rVR.getSystemTextureId(CViewRenderer::OutOfRangeTexture), CRGBA::White); rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, rVR.getSystemTextureId(CViewRenderer::OutOfRangeTexture), CRGBA::White);
} }
} }
break; break;
case CCtrlSheetInfo::SheetType_OutpostBuilding: case CCtrlSheetInfo::SheetType_OutpostBuilding:
setupOutpostBuilding(); setupOutpostBuilding();
if (_DispBackBmpId != -1) if (_DispBackBmpId != -1)
@ -3114,6 +3263,53 @@ const COutpostBuildingSheet *CDBCtrlSheet::asOutpostBuildingSheet() const
return NULL; return NULL;
} }
// ***************************************************************************
void CDBCtrlSheet::setupItemInfoWaiter()
{
const CItemSheet *item = asItemSheet();
if(!item)
return;
if (!useItemInfoForFamily(item->Family))
return;
if (getItemSerial() == 0 || getItemCreateTime() == 0)
return;
string luaMethodName = ((item->Family == ITEMFAMILY::CRYSTALLIZED_SPELL) ? "updateCrystallizedSpellTooltip" : "updateBuffItemTooltip");
CDBCtrlSheet *ctrlSheet = const_cast<CDBCtrlSheet*>(this);
uint itemSlotId = getInventory().getItemSlotId(ctrlSheet);
// Prepare the waiter for tooltips
_ItemInfoWaiter.ItemSheet= ctrlSheet->getSheetId();
_ItemInfoWaiter.LuaMethodName = luaMethodName;
_ItemInfoWaiter.ItemSlotId= itemSlotId;
_ItemInfoWaiter.CtrlSheet = ctrlSheet;
// send out request only if cache is not set
const CClientItemInfo *itemInfo = getInventory().getItemInfoCache(getItemSerial(), getItemCreateTime());
if (itemInfo)
{
infoReceived();
}
else
{
// Using isInventoryPresent/Available() will fail for packers when out of range
// Getting server item however will work correctly for packer/room/guild
const CItemImage *itemImage = getInventory().getServerItem(itemSlotId);
if (itemImage)
{
_ItemInfoWaiter.sendRequest();
}
else
{
// schedule for next draw() - if inventory should not be available (ie guild),
// but user opens it anyway, then this will loop back here on every draw()
_ItemInfoChanged = true;
}
}
}
// *************************************************************************** // ***************************************************************************
void CDBCtrlSheet::getContextHelp(ucstring &help) const void CDBCtrlSheet::getContextHelp(ucstring &help) const
{ {
@ -3177,34 +3373,17 @@ void CDBCtrlSheet::getContextHelp(ucstring &help) const
{ {
if (useItemInfoForFamily(item->Family)) if (useItemInfoForFamily(item->Family))
{ {
string luaMethodName = ( (item->Family == ITEMFAMILY::CRYSTALLIZED_SPELL) ? "updateCrystallizedSpellTooltip" : "updateBuffItemTooltip"); // call lua function to update tooltip window
CDBCtrlSheet *ctrlSheet = const_cast<CDBCtrlSheet*>(this); help = _ItemInfoWaiter.infoValidated();
CCtrlBase *ctrlBase = const_cast<CDBCtrlSheet*>(this); }
if ( ! getInventory().isItemInfoUpToDate(getInventory().getItemSlotId(ctrlSheet))) else if (!_ContextHelp.empty())
{ {
// Prepare the waiter help = _ContextHelp;
ControlSheetTooltipUpdater.ItemSheet= ctrlSheet->getSheetId();
ControlSheetTooltipUpdater.LuaMethodName = luaMethodName;
ControlSheetTooltipUpdater.ItemSlotId= getInventory().getItemSlotId(ctrlSheet);
ControlSheetTooltipUpdater.CtrlSheet = ctrlSheet;
// Add the waiter
getInventory().addItemInfoWaiter(&ControlSheetTooltipUpdater);
}
if (!_ContextHelp.empty())
{
help= _ContextHelp;
ctrlBase->setDefaultContextHelp(ucstring());
}
else
help = ControlSheetTooltipUpdater.infoValidated(ctrlSheet, luaMethodName);
} }
else else
if (!_ContextHelp.empty()) {
help= _ContextHelp; help = getItemActualName();
else }
help= getItemActualName();
} }
else else
help= _ContextHelp; help= _ContextHelp;
@ -3247,18 +3426,18 @@ void CDBCtrlSheet::getContextHelp(ucstring &help) const
} }
else else
{ {
// delegate setup of context he help ( & window ) to lua // delegate setup of context he help ( & window ) to lua
CInterfaceManager *im = CInterfaceManager::getInstance(); CInterfaceManager *im = CInterfaceManager::getInstance();
CLuaState *ls= CLuaManager::getInstance().getLuaState(); CLuaState *ls= CLuaManager::getInstance().getLuaState();
{ {
CLuaStackRestorer lsr(ls, 0); CLuaStackRestorer lsr(ls, 0);
CSPhraseManager *pPM= CSPhraseManager::getInstance(); CSPhraseManager *pPM= CSPhraseManager::getInstance();
_PhraseAdapter = new CSPhraseComAdpater; _PhraseAdapter = new CSPhraseComAdpater;
_PhraseAdapter->Phrase = pPM->getPhrase(phraseId); _PhraseAdapter->Phrase = pPM->getPhrase(phraseId);
CLuaIHM::pushReflectableOnStack(*ls, _PhraseAdapter); CLuaIHM::pushReflectableOnStack(*ls, _PhraseAdapter);
ls->pushGlobalTable(); ls->pushGlobalTable();
CLuaObject game(*ls); CLuaObject game(*ls);
game = game["game"]; game = game["game"];
game.callMethodByNameNoThrow("updatePhraseTooltip", 1, 1); game.callMethodByNameNoThrow("updatePhraseTooltip", 1, 1);
// retrieve result from stack // retrieve result from stack
help = ucstring(); help = ucstring();
@ -3322,21 +3501,7 @@ void CDBCtrlSheet::getContextHelpToolTip(ucstring &help) const
{ {
if (useItemInfoForFamily(item->Family)) if (useItemInfoForFamily(item->Family))
{ {
string luaMethodName = (item->Family == ITEMFAMILY::CRYSTALLIZED_SPELL) ? "updateCrystallizedSpellTooltip" : "updateBuffItemTooltip"; help = _ItemInfoWaiter.infoValidated();
CDBCtrlSheet *ctrlSheet = const_cast<CDBCtrlSheet*>(this);
if ( ! getInventory().isItemInfoUpToDate(getInventory().getItemSlotId(ctrlSheet)))
{
// Prepare the waiter
ControlSheetTooltipUpdater.ItemSheet= ctrlSheet->getSheetId();
ControlSheetTooltipUpdater.LuaMethodName = luaMethodName;
ControlSheetTooltipUpdater.ItemSlotId= getInventory().getItemSlotId(ctrlSheet);
ControlSheetTooltipUpdater.CtrlSheet = ctrlSheet;
// Add the waiter
getInventory().addItemInfoWaiter(&ControlSheetTooltipUpdater);
}
help = ControlSheetTooltipUpdater.infoValidated(ctrlSheet, luaMethodName);
return; return;
} }
} }
@ -3551,6 +3716,10 @@ void CDBCtrlSheet::resetAllTexIDs()
_Stackable= 1; _Stackable= 1;
_IconW = 0; _IconW = 0;
_IconH = 0; _IconH = 0;
_ItemInfoChanged = true;
_EnchantIcons.clear();
_BuffIcons.clear();
} }

@ -37,7 +37,7 @@
#include "game_share/item_family.h" #include "game_share/item_family.h"
// //
#include "../time_client.h" #include "../time_client.h"
#include "item_info_waiter.h"
class CItemSheet; class CItemSheet;
class CPactSheet; class CPactSheet;
@ -53,6 +53,25 @@ namespace NLGUI
class CViewRenderer; class CViewRenderer;
} }
class CDBCtrlSheet;
// ***************************************************************************
// Item info request from server
class CControlSheetInfoWaiter : public IItemInfoWaiter
{
public:
CDBCtrlSheet* CtrlSheet;
string LuaMethodName;
bool Requesting;
CControlSheetInfoWaiter()
: IItemInfoWaiter(), Requesting(false)
{ }
public:
ucstring infoValidated() const;
void sendRequest();
virtual void infoReceived();
};
// *************************************************************************** // ***************************************************************************
/** Common info for CDBCtrlSheet and CDBGroupListSheet /** Common info for CDBCtrlSheet and CDBGroupListSheet
@ -576,12 +595,14 @@ public:
// For auras, powers, etc. set the range of ticks during which regen occurs // For auras, powers, etc. set the range of ticks during which regen occurs
void setRegenTickRange(const CTickRange &tickRange); void setRegenTickRange(const CTickRange &tickRange);
const CTickRange &getRegenTickRange() const { return _RegenTickRange; } const CTickRange &getRegenTickRange() const { return _RegenTickRange; }
// start notify anim (at the end of regen usually) // start notify anim (at the end of regen usually)
void startNotifyAnim(); void startNotifyAnim();
protected: // callback from info waiter
void infoReceived();
protected:
inline bool useItemInfoForFamily(ITEMFAMILY::EItemFamily family) const; inline bool useItemInfoForFamily(ITEMFAMILY::EItemFamily family) const;
void setupItem(); void setupItem();
@ -622,6 +643,7 @@ protected:
NLMISC::CCDBNodeLeaf *_ItemRMFaberStatType; NLMISC::CCDBNodeLeaf *_ItemRMFaberStatType;
mutable sint32 _LastSheetId; mutable sint32 _LastSheetId;
bool _ItemInfoChanged;
/// Display /// Display
sint32 _DispSlotBmpId; // Display slot bitmap id sint32 _DispSlotBmpId; // Display slot bitmap id
@ -632,6 +654,26 @@ protected:
sint32 _DispOverBmpId; // Over Icon sint32 _DispOverBmpId; // Over Icon
sint32 _DispOver2BmpId; // Over Icon N0 2 for bricks / items. Useful for items when _DispOverBmpId is used to paint user color on the item. sint32 _DispOver2BmpId; // Over Icon N0 2 for bricks / items. Useful for items when _DispOverBmpId is used to paint user color on the item.
std::string _HpBuffIcon;
std::string _SapBuffIcon;
std::string _StaBuffIcon;
std::string _FocusBuffIcon;
// texture ids to show
struct SBuffIcon
{
SBuffIcon(sint32 txid, NLMISC::CRGBA col=NLMISC::CRGBA::White)
:TextureId(txid), Color(col), IconW(0), IconH(0)
{ }
sint32 TextureId;
NLMISC::CRGBA Color;
sint32 IconW;
sint32 IconH;
};
std::vector<SBuffIcon> _BuffIcons;
std::vector<SBuffIcon> _EnchantIcons;
// Level Brick or Quality // Level Brick or Quality
union union
{ {
@ -751,6 +793,7 @@ protected:
sint64 _NotifyAnimEndTime; sint64 _NotifyAnimEndTime;
CControlSheetInfoWaiter _ItemInfoWaiter;
private: private:
mutable TSheetType _ActualType; mutable TSheetType _ActualType;
@ -769,17 +812,20 @@ private:
// special for items // special for items
void updateItemCharacRequirement(sint32 sheetId); void updateItemCharacRequirement(sint32 sheetId);
// Send ITEM_INFO:GET request to server to fetch Buffs, Enchant info
void setupItemInfoWaiter();
// update armour color, and cache // update armour color, and cache
void updateArmourColor(sint8 col); void updateArmourColor(sint8 col);
// setup sheet DB. _DbBranchName must be ok, and _SecondIndexInDb and _IndexInDb as well // setup sheet DB. _DbBranchName must be ok, and _SecondIndexInDb and _IndexInDb as well
void setupSheetDbLinks (); void setupSheetDbLinks ();
// 'regen' rendering // 'regen' rendering
// convert from uv coordinates in the [0, 1] x [0, 1] range to screen coords // convert from uv coordinates in the [0, 1] x [0, 1] range to screen coords
inline void uvToScreen(float x, float y, NLMISC::CVector &screenPos, uint texSize) const; inline void uvToScreen(float x, float y, NLMISC::CVector &screenPos, uint texSize) const;
// from an angle in the [0, 1] range, return both uv & screen coords for that angle // from an angle in the [0, 1] range, return both uv & screen coords for that angle
// (angle is projected on the side of rectangle of the 'regen' texture) // (angle is projected on the side of rectangle of the 'regen' texture)
void buildPieCorner(float angle, NLMISC::CUV &uv, NLMISC::CVector &pos, uint texSize) const; void buildPieCorner(float angle, NLMISC::CUV &uv, NLMISC::CVector &pos, uint texSize) const;
// from a start and end angle in the [0, 1] range, build the set of uv mapped triangles necessary // from a start and end angle in the [0, 1] range, build the set of uv mapped triangles necessary

@ -31,7 +31,7 @@ namespace NLMISC{
class CCDBNodeBranch; class CCDBNodeBranch;
} }
class CDBCtrlSheet; class CDBCtrlSheet;
class IItermInfoWaiter;
const uint MAX_TEMPINV_ENTRIES = INVENTORIES::NbTempInvSlots; const uint MAX_TEMPINV_ENTRIES = INVENTORIES::NbTempInvSlots;
const uint MAX_BAGINV_ENTRIES = INVENTORIES::NbBagSlots; const uint MAX_BAGINV_ENTRIES = INVENTORIES::NbBagSlots;
@ -153,21 +153,6 @@ private:
TItemInfoCacheMap _ItemInfoCacheMap; TItemInfoCacheMap _ItemInfoCacheMap;
}; };
class IItemInfoWaiter
{
public:
IItemInfoWaiter() {ItemSlotId= 0; ItemSheet= 0;}
virtual ~IItemInfoWaiter() {}
// The item SheetId. If differ from current sheet in the SlotId, the infos are not updated / requested
uint ItemSheet;
// The item SlotId to retrieve info.
uint ItemSlotId;
// Called when the info is received for this slot.
virtual void infoReceived() =0;
};
// *************************************************************************** // ***************************************************************************
/** This manager gives direct access to inventory slots (bag, temporary inventory, hands, and equip inventory) /** This manager gives direct access to inventory slots (bag, temporary inventory, hands, and equip inventory)
* This also give access to player money * This also give access to player money

@ -0,0 +1,39 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 RZ_ITEM_INFO_WAITER_H
#define RZ_ITEM_INFO_WAITER_H
class IItemInfoWaiter
{
public:
IItemInfoWaiter() {ItemSlotId= 0; ItemSheet= 0;}
virtual ~IItemInfoWaiter() {}
// The item SheetId. If differ from current sheet in the SlotId, the infos are not updated / requested
uint ItemSheet;
// The item SlotId to retrieve info.
uint ItemSlotId;
// Called when the info is received for this slot.
virtual void infoReceived() =0;
};
#endif // RZ_DBCTRL_SHEET_INFO_WAITER_H
/* End of item_info_waiter.h */
Loading…
Cancel
Save