// -------- begin of function ItemRes::can_equip ----------// // int ItemRes::can_equip( short itemId, int unitId, Skill &skill ) { if( !itemId ) return 0; if( !unit_res[unitId]->race_id || unitId == UNIT_WAGON ) // only human or monster can equip return 0; err_when( itemId > ITEM_TYPE_COUNT ); // if an item has ITEM_ABILITY_ARROW_DAMAGE but no ITEM_ABILITY_DAMAGE // it must be wear by an archer unit Item tempItem( itemId, 0 ); if( ability( tempItem, ITEM_ABILITY_ARROW_DAMAGE) > 0 && ability( tempItem, ITEM_ABILITY_DAMAGE) == 0 ) { // find unit attack record to see if any range attack int canRangeAttack = 0; UnitInfo *unitInfo = unit_res[unitId]; for( int curAttack = unitInfo->attack_count-1; curAttack >= 0; --curAttack ) { AttackInfo *attackInfo = unit_res.get_attack_info( unitInfo->first_attack + curAttack ); if( attackInfo->attack_range > 1 && skill.actual_skill_level(NULL) >= attackInfo->combat_level ) { canRangeAttack = 1; } } if( !canRangeAttack ) return 0; } return 1; }
/** * @brief Draw the base inventory * @return The full height requested by the current view (not the node height) */ static int UI_BaseInventoryNodeDrawItems (uiNode_t* node, const objDef_t* highlightType) { bool outOfNode = false; vec2_t nodepos; int items = 0; int rowHeight = 0; const int cellWidth = node->box.size[0] / EXTRADATA(node).columns; containerItemIterator_t iterator; int currentHeight = 0; UI_GetNodeAbsPos(node, nodepos); UI_ContainerItemIteratorInit(&iterator, node); for (; iterator.itemID < csi.numODs; UI_ContainerItemIteratorNext(&iterator)) { const int id = iterator.itemID; const objDef_t* obj = INVSH_GetItemByIDX(id); Item tempItem(obj, nullptr, 1); vec3_t pos; vec3_t ammopos; const float* color; bool isHighlight = false; int amount; const int col = items % EXTRADATA(node).columns; int cellHeight = 0; const Item* icItem = iterator.itemFound; /* skip items over and bellow the node view */ if (outOfNode || currentHeight < EXTRADATA(node).scrollY.viewPos) { int height; R_FontTextSize("f_verysmall", _(obj->name), cellWidth - 5, LONGLINES_WRAP, nullptr, &height, nullptr, nullptr); height += obj->sy * C_UNIT + 10; if (height > rowHeight) rowHeight = height; if (outOfNode || currentHeight + rowHeight < EXTRADATA(node).scrollY.viewPos) { if (col == EXTRADATA(node).columns - 1) { currentHeight += rowHeight; rowHeight = 0; } items++; continue; } } Vector2Copy(nodepos, pos); pos[0] += cellWidth * col; pos[1] += currentHeight - EXTRADATA(node).scrollY.viewPos; pos[2] = 0; if (highlightType) { if (obj->isAmmo()) isHighlight = obj->isLoadableInWeapon(highlightType); else isHighlight = highlightType->isLoadableInWeapon(obj); } if (icItem != nullptr) { if (isHighlight) color = colorLoadable; else color = colorDefault; } else { if (isHighlight) color = colorDisabledLoadable; else color = colorDisabledHiden; } if (icItem) amount = icItem->getAmount(); else amount = 0; /* draw item */ pos[0] += obj->sx * C_UNIT / 2.0; pos[1] += obj->sy * C_UNIT / 2.0; UI_DrawItem(node, pos, &tempItem, -1, -1, scale, color); UI_DrawString("f_verysmall", ALIGN_LC, pos[0] + obj->sx * C_UNIT / 2.0, pos[1] + obj->sy * C_UNIT / 2.0, pos[0] + obj->sx * C_UNIT / 2.0, cellWidth - 5, /* maxWidth */ 0, va("x%i", amount)); pos[0] -= obj->sx * C_UNIT / 2.0; pos[1] += obj->sy * C_UNIT / 2.0; cellHeight += obj->sy * C_UNIT; /* save position for ammo */ Vector2Copy(pos, ammopos); ammopos[2] = 0; ammopos[0] += obj->sx * C_UNIT + 10; /* draw the item name. */ cellHeight += UI_DrawString("f_verysmall", ALIGN_UL, pos[0], pos[1], pos[0], cellWidth - 5, /* max width */ 0, _(obj->name)); /* draw ammos of weapon */ if (obj->weapon && EXTRADATA(node).displayAmmoOfWeapon) { for (int ammoIdx = 0; ammoIdx < obj->numAmmos; ammoIdx++) { tempItem.setDef(obj->ammos[ammoIdx]); /* skip weapos that are their own ammo -- oneshot and such */ if (obj == tempItem.def()) continue; /* skip unusable ammo */ if (!GAME_ItemIsUseable(tempItem.def())) continue; /* find and skip none existing ammo */ icItem = UI_ContainerNodeGetExistingItem(node, tempItem.def(), (itemFilterTypes_t) EXTRADATA(node).filterEquipType); if (!icItem) continue; /* Calculate the center of the item model/image. */ ammopos[0] += icItem->def()->sx * C_UNIT / 2.0; ammopos[1] -= icItem->def()->sy * C_UNIT / 2.0; UI_DrawItem(node, ammopos, &tempItem, -1, -1, scale, colorDefault); UI_DrawString("f_verysmall", ALIGN_LC, ammopos[0] + icItem->def()->sx * C_UNIT / 2.0, ammopos[1] + icItem->def()->sy * C_UNIT / 2.0, ammopos[0] + icItem->def()->sx * C_UNIT / 2.0, cellWidth - 5 - ammopos[0], /* maxWidth */ 0, va("x%i", icItem->getAmount())); ammopos[0] += icItem->def()->sx * C_UNIT / 2.0; ammopos[1] += icItem->def()->sy * C_UNIT / 2.0; } } cellHeight += 10; if (cellHeight > rowHeight) { rowHeight = cellHeight; } /* add a marge between rows */ if (col == EXTRADATA(node).columns - 1) { currentHeight += rowHeight; rowHeight = 0; if (currentHeight - EXTRADATA(node).scrollY.viewPos >= node->box.size[1]) outOfNode = true; } /* count items */ items++; } if (rowHeight != 0) { currentHeight += rowHeight; } return currentHeight; }