the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 873 lines 20 kB view raw
1#include "stdafx.h" 2#include "com.mojang.nbt.h" 3#include "net.minecraft.locale.h" 4#include "net.minecraft.stats.h" 5#include "net.minecraft.world.entity.h" 6#include "net.minecraft.world.entity.ai.attributes.h" 7#include "net.minecraft.world.entity.monster.h" 8#include "net.minecraft.world.entity.player.h" 9#include "net.minecraft.world.level.h" 10#include "net.minecraft.world.level.tile.h" 11#include "net.minecraft.world.item.h" 12#include "net.minecraft.world.item.enchantment.h" 13#include "Item.h" 14#include "ItemInstance.h" 15#include "HtmlString.h" 16 17const wstring ItemInstance::ATTRIBUTE_MODIFIER_FORMAT = L"#.###"; 18 19const wchar_t *ItemInstance::TAG_ENCH_ID = L"id"; 20const wchar_t *ItemInstance::TAG_ENCH_LEVEL = L"lvl"; 21 22void ItemInstance::_init(int id, int count, int auxValue) 23{ 24 this->popTime = 0; 25 this->id = id; 26 this->count = count; 27 this->auxValue = auxValue; 28 this->tag = NULL; 29 this->frame = nullptr; 30 // 4J-PB - for trading menu 31 this->m_bForceNumberDisplay=false; 32} 33 34ItemInstance::ItemInstance(Tile *tile) 35{ 36 _init(tile->id, 1, 0); 37} 38 39ItemInstance::ItemInstance(Tile *tile, int count) 40{ 41 _init(tile->id, count, 0); 42} 43// 4J-PB - added 44ItemInstance::ItemInstance(MapItem *item, int count) 45{ 46 _init(item->id, count, 0); 47} 48 49ItemInstance::ItemInstance(Tile *tile, int count, int auxValue) 50{ 51 _init(tile->id, count, auxValue); 52} 53 54ItemInstance::ItemInstance(Item *item) 55{ 56 _init(item->id, 1, 0); 57} 58 59 60 61ItemInstance::ItemInstance(Item *item, int count) 62{ 63 _init(item->id, count, 0); 64} 65 66ItemInstance::ItemInstance(Item *item, int count, int auxValue) 67{ 68 _init(item->id, count, auxValue); 69} 70 71ItemInstance::ItemInstance(int id, int count, int damage) 72{ 73 _init(id,count,damage); 74 if (auxValue < 0) 75 { 76 auxValue = 0; 77 } 78} 79 80shared_ptr<ItemInstance> ItemInstance::fromTag(CompoundTag *itemTag) 81{ 82 shared_ptr<ItemInstance> itemInstance = shared_ptr<ItemInstance>(new ItemInstance()); 83 itemInstance->load(itemTag); 84 return itemInstance->getItem() != NULL ? itemInstance : nullptr; 85} 86 87ItemInstance::~ItemInstance() 88{ 89 if(tag != NULL) delete tag; 90} 91 92shared_ptr<ItemInstance> ItemInstance::remove(int count) 93{ 94 shared_ptr<ItemInstance> ii = shared_ptr<ItemInstance>( new ItemInstance(id, count, auxValue) ); 95 if (tag != NULL) ii->tag = (CompoundTag *) tag->copy(); 96 this->count -= count; 97 98 // 4J Stu Fix for duplication glitch, make sure that item count is in range 99 if(this->count <= 0) 100 { 101 this->count = 0; 102 } 103 return ii; 104} 105 106Item *ItemInstance::getItem() const 107{ 108 return Item::items[id]; 109} 110 111Icon *ItemInstance::getIcon() 112{ 113 return getItem()->getIcon(shared_from_this()); 114} 115 116int ItemInstance::getIconType() 117{ 118 return getItem()->getIconType(); 119} 120 121bool ItemInstance::useOn(shared_ptr<Player> player, Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, bool bTestUseOnOnly) 122{ 123 return getItem()->useOn(shared_from_this(), player, level, x, y, z, face, clickX, clickY, clickZ, bTestUseOnOnly); 124} 125 126float ItemInstance::getDestroySpeed(Tile *tile) 127{ 128 return getItem()->getDestroySpeed(shared_from_this(), tile); 129} 130 131bool ItemInstance::TestUse(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player) 132{ 133 return getItem()->TestUse( itemInstance, level, player); 134} 135 136shared_ptr<ItemInstance> ItemInstance::use(Level *level, shared_ptr<Player> player) 137{ 138 return getItem()->use(shared_from_this(), level, player); 139} 140 141shared_ptr<ItemInstance> ItemInstance::useTimeDepleted(Level *level, shared_ptr<Player> player) 142{ 143 return getItem()->useTimeDepleted(shared_from_this(), level, player); 144} 145 146CompoundTag *ItemInstance::save(CompoundTag *compoundTag) 147{ 148 compoundTag->putShort(L"id", (short) id); 149 compoundTag->putByte(L"Count", (byte) count); 150 compoundTag->putShort(L"Damage", (short) auxValue); 151 if (tag != NULL) compoundTag->put(L"tag", tag->copy()); 152 return compoundTag; 153} 154 155void ItemInstance::load(CompoundTag *compoundTag) 156{ 157 popTime = 0; 158 id = compoundTag->getShort(L"id"); 159 count = compoundTag->getByte(L"Count"); 160 auxValue = compoundTag->getShort(L"Damage"); 161 if (auxValue < 0) 162 { 163 auxValue = 0; 164 } 165 if (compoundTag->contains(L"tag")) 166 { 167 delete tag; 168 tag = (CompoundTag *)compoundTag->getCompound(L"tag")->copy(); 169 } 170} 171 172int ItemInstance::getMaxStackSize() const 173{ 174 return getItem()->getMaxStackSize(); 175} 176 177bool ItemInstance::isStackable() 178{ 179 return getMaxStackSize() > 1 && (!isDamageableItem() || !isDamaged()); 180} 181 182bool ItemInstance::isDamageableItem() 183{ 184 return Item::items[id]->getMaxDamage() > 0; 185} 186 187/** 188* Returns true if this item type only can be stacked with items that have 189* the same auxValue data. 190* 191* @return 192*/ 193 194bool ItemInstance::isStackedByData() 195{ 196 return Item::items[id]->isStackedByData(); 197} 198 199bool ItemInstance::isDamaged() 200{ 201 return isDamageableItem() && auxValue > 0; 202} 203 204int ItemInstance::getDamageValue() 205{ 206 return auxValue; 207} 208 209int ItemInstance::getAuxValue() const 210{ 211 return auxValue; 212} 213 214void ItemInstance::setAuxValue(int value) 215{ 216 auxValue = value; 217 if (auxValue < 0) 218 { 219 auxValue = 0; 220 } 221} 222 223int ItemInstance::getMaxDamage() 224{ 225 return Item::items[id]->getMaxDamage(); 226} 227 228bool ItemInstance::hurt(int dmg, Random *random) 229{ 230 if (!isDamageableItem()) 231 { 232 return false; 233 } 234 235 if (dmg > 0) 236 { 237 int level = EnchantmentHelper::getEnchantmentLevel(Enchantment::digDurability->id, shared_from_this()); 238 239 int drop = 0; 240 for (int y = 0; level > 0 && y < dmg; y++) 241 { 242 if (DigDurabilityEnchantment::shouldIgnoreDurabilityDrop(shared_from_this(), level, random)) 243 { 244 drop++; 245 } 246 } 247 dmg -= drop; 248 249 if (dmg <= 0) return false; 250 } 251 252 auxValue += dmg; 253 254 return auxValue > getMaxDamage(); 255} 256 257void ItemInstance::hurtAndBreak(int dmg, shared_ptr<LivingEntity> owner) 258{ 259 shared_ptr<Player> player = dynamic_pointer_cast<Player>(owner); 260 if (player != NULL && player->abilities.instabuild) return; 261 if (!isDamageableItem()) return; 262 263 if (hurt(dmg, owner->getRandom())) 264 { 265 owner->breakItem(shared_from_this()); 266 267 count--; 268 if (player != NULL) 269 { 270 //player->awardStat(Stats::itemBroke[id], 1); 271 if (count == 0 && dynamic_cast<BowItem *>( getItem() ) != NULL) 272 { 273 player->removeSelectedItem(); 274 } 275 } 276 if (count < 0) count = 0; 277 auxValue = 0; 278 } 279} 280 281void ItemInstance::hurtEnemy(shared_ptr<LivingEntity> mob, shared_ptr<Player> attacker) 282{ 283 //bool used = 284 Item::items[id]->hurtEnemy(shared_from_this(), mob, attacker); 285} 286 287void ItemInstance::mineBlock(Level *level, int tile, int x, int y, int z, shared_ptr<Player> owner) 288{ 289 //bool used = 290 Item::items[id]->mineBlock( shared_from_this(), level, tile, x, y, z, owner); 291} 292 293bool ItemInstance::canDestroySpecial(Tile *tile) 294{ 295 return Item::items[id]->canDestroySpecial(tile); 296} 297 298bool ItemInstance::interactEnemy(shared_ptr<Player> player, shared_ptr<LivingEntity> mob) 299{ 300 return Item::items[id]->interactEnemy(shared_from_this(), player, mob); 301} 302 303shared_ptr<ItemInstance> ItemInstance::copy() const 304{ 305 shared_ptr<ItemInstance> copy = shared_ptr<ItemInstance>( new ItemInstance(id, count, auxValue) ); 306 if (tag != NULL) 307 { 308 copy->tag = (CompoundTag *) tag->copy(); 309 } 310 return copy; 311} 312 313// 4J Stu - Added this as we need it in the recipe code 314ItemInstance *ItemInstance::copy_not_shared() const 315{ 316 ItemInstance *copy = new ItemInstance(id, count, auxValue); 317 if (tag != NULL) 318 { 319 copy->tag = (CompoundTag *) tag->copy(); 320 if (!copy->tag->equals(tag)) 321 { 322 return copy; 323 } 324 } 325 return copy; 326} 327 328// 4J Brought forward from 1.2 329bool ItemInstance::tagMatches(shared_ptr<ItemInstance> a, shared_ptr<ItemInstance> b) 330{ 331 if (a == NULL && b == NULL) return true; 332 if (a == NULL || b == NULL) return false; 333 334 if (a->tag == NULL && b->tag != NULL) 335 { 336 return false; 337 } 338 if (a->tag != NULL && !a->tag->equals(b->tag)) 339 { 340 return false; 341 } 342 return true; 343} 344 345bool ItemInstance::matches(shared_ptr<ItemInstance> a, shared_ptr<ItemInstance> b) 346{ 347 if (a == NULL && b == NULL) return true; 348 if (a == NULL || b == NULL) return false; 349 return a->matches(b); 350} 351 352bool ItemInstance::matches(shared_ptr<ItemInstance> b) 353{ 354 if (count != b->count) return false; 355 if (id != b->id) return false; 356 if (auxValue != b->auxValue) return false; 357 if (tag == NULL && b->tag != NULL) 358 { 359 return false; 360 } 361 if (tag != NULL && !tag->equals(b->tag)) 362 { 363 return false; 364 } 365 return true; 366} 367 368/** 369* Checks if this item is the same item as the other one, disregarding the 370* 'count' value. 371* 372* @param b 373* @return 374*/ 375bool ItemInstance::sameItem(shared_ptr<ItemInstance> b) 376{ 377 return id == b->id && auxValue == b->auxValue; 378} 379 380bool ItemInstance::sameItemWithTags(shared_ptr<ItemInstance> b) 381{ 382 if (id != b->id) return false; 383 if (auxValue != b->auxValue) return false; 384 if (tag == NULL && b->tag != NULL) 385 { 386 return false; 387 } 388 if (tag != NULL && !tag->equals(b->tag)) 389 { 390 return false; 391 } 392 return true; 393} 394 395// 4J Stu - Added this for the one time when we compare with a non-shared pointer 396bool ItemInstance::sameItem_not_shared(const ItemInstance *b) 397{ 398 return id == b->id && auxValue == b->auxValue; 399} 400 401unsigned int ItemInstance::getUseDescriptionId() 402{ 403 return Item::items[id]->getUseDescriptionId(shared_from_this()); 404} 405 406unsigned int ItemInstance::getDescriptionId(int iData /*= -1*/) 407{ 408 return Item::items[id]->getDescriptionId(shared_from_this()); 409} 410 411ItemInstance *ItemInstance::setDescriptionId(unsigned int id) 412{ 413 // 4J Stu - I don't think this function is ever used. It if is, it should probably return shared_from_this() 414 assert(false); 415 return this; 416} 417 418shared_ptr<ItemInstance> ItemInstance::clone(shared_ptr<ItemInstance> item) 419{ 420 return item == NULL ? nullptr : item->copy(); 421} 422 423wstring ItemInstance::toString() 424{ 425 //return count + "x" + Item::items[id]->getDescriptionId() + "@" + auxValue; 426 427 std::wostringstream oss; 428 // 4J-PB - TODO - temp fix until ore recipe issue is fixed 429 if(Item::items[id]==NULL) 430 { 431 oss << std::dec << count << L"x" << L" Item::items[id] is NULL " << L"@" << auxValue; 432 } 433 else 434 { 435 oss << std::dec << count << L"x" << Item::items[id]->getDescription(shared_from_this()) << L"@" << auxValue; 436 } 437 return oss.str(); 438} 439 440void ItemInstance::inventoryTick(Level *level, shared_ptr<Entity> owner, int slot, bool selected) 441{ 442 if (popTime > 0) popTime--; 443 Item::items[id]->inventoryTick(shared_from_this(), level, owner, slot, selected); 444} 445 446void ItemInstance::onCraftedBy(Level *level, shared_ptr<Player> player, int craftCount) 447{ 448 // 4J Stu Added for tutorial callback 449 player->onCrafted(shared_from_this()); 450 451 player->awardStat( 452 GenericStats::itemsCrafted(id), 453 GenericStats::param_itemsCrafted(id, auxValue, craftCount) 454 ); 455 456 Item::items[id]->onCraftedBy(shared_from_this(), level, player); 457} 458 459bool ItemInstance::equals(shared_ptr<ItemInstance> ii) 460{ 461 return id == ii->id && count == ii->count && auxValue == ii->auxValue; 462} 463 464int ItemInstance::getUseDuration() 465{ 466 return getItem()->getUseDuration(shared_from_this()); 467} 468 469UseAnim ItemInstance::getUseAnimation() 470{ 471 return getItem()->getUseAnimation(shared_from_this()); 472} 473 474void ItemInstance::releaseUsing(Level *level, shared_ptr<Player> player, int durationLeft) 475{ 476 getItem()->releaseUsing(shared_from_this(), level, player, durationLeft); 477} 478 479// 4J Stu - Brought forward these functions for enchanting/game rules 480bool ItemInstance::hasTag() 481{ 482 return tag != NULL; 483} 484 485CompoundTag *ItemInstance::getTag() 486{ 487 return tag; 488} 489 490ListTag<CompoundTag> *ItemInstance::getEnchantmentTags() 491{ 492 if (tag == NULL) 493 { 494 return NULL; 495 } 496 return (ListTag<CompoundTag> *) tag->get(L"ench"); 497} 498 499void ItemInstance::setTag(CompoundTag *tag) 500{ 501 delete this->tag; 502 this->tag = tag; 503} 504 505wstring ItemInstance::getHoverName() 506{ 507 wstring title = getItem()->getHoverName(shared_from_this()); 508 509 if (tag != NULL && tag->contains(L"display")) 510 { 511 CompoundTag *display = tag->getCompound(L"display"); 512 513 if (display->contains(L"Name")) 514 { 515 title = display->getString(L"Name"); 516 } 517 } 518 519 return title; 520} 521 522void ItemInstance::setHoverName(const wstring &name) 523{ 524 if (tag == NULL) tag = new CompoundTag(); 525 if (!tag->contains(L"display")) tag->putCompound(L"display", new CompoundTag()); 526 tag->getCompound(L"display")->putString(L"Name", name); 527} 528 529void ItemInstance::resetHoverName() 530{ 531 if (tag == NULL) return; 532 if (!tag->contains(L"display")) return; 533 CompoundTag *display = tag->getCompound(L"display"); 534 display->remove(L"Name"); 535 536 if (display->isEmpty()) 537 { 538 tag->remove(L"display"); 539 540 if (tag->isEmpty()) 541 { 542 setTag(NULL); 543 } 544 } 545} 546 547bool ItemInstance::hasCustomHoverName() 548{ 549 if (tag == NULL) return false; 550 if (!tag->contains(L"display")) return false; 551 return tag->getCompound(L"display")->contains(L"Name"); 552} 553 554vector<HtmlString> *ItemInstance::getHoverText(shared_ptr<Player> player, bool advanced) 555{ 556 vector<HtmlString> *lines = new vector<HtmlString>(); 557 Item *item = Item::items[id]; 558 HtmlString title = HtmlString(getHoverName()); 559 560 if (hasCustomHoverName()) 561 { 562 title.italics = true; 563 } 564 565 // 4J: This is for showing aux values, not useful in console version 566 /* 567 if (advanced) 568 { 569 wstring suffix = L""; 570 571 if (title.length() > 0) 572 { 573 title += L" ("; 574 suffix = L")"; 575 } 576 577 if (isStackedByData()) 578 { 579 title += String.format("#%04d/%d%s", id, auxValue, suffix); 580 } 581 else 582 { 583 title += String.format("#%04d%s", id, suffix); 584 } 585 } 586 else if (!hasCustomHoverName() && id == Item::map_Id) 587 */ 588 589 /*if (!hasCustomHoverName() && id == Item::map_Id) 590 { 591 title.text += L" #" + _toString(auxValue); 592 }*/ 593 594 lines->push_back(title); 595 596 item->appendHoverText(shared_from_this(), player, lines, advanced); 597 598 if (hasTag()) 599 { 600 ListTag<CompoundTag> *list = getEnchantmentTags(); 601 if (list != NULL) 602 { 603 for (int i = 0; i < list->size(); i++) 604 { 605 int type = list->get(i)->getShort((wchar_t *)TAG_ENCH_ID); 606 int level = list->get(i)->getShort((wchar_t *)TAG_ENCH_LEVEL); 607 608 if (Enchantment::enchantments[type] != NULL) 609 { 610 wstring unformatted = L""; 611 lines->push_back(Enchantment::enchantments[type]->getFullname(level)); 612 } 613 } 614 } 615 616 if (tag->contains(L"display")) 617 { 618 //CompoundTag *display = tag->getCompound(L"display"); 619 620 //if (display->contains(L"color")) 621 //{ 622 // if (advanced) 623 // { 624 // wchar_t text [256]; 625 // swprintf(text, 256, L"Color: LOCALISE #%08X", display->getInt(L"color")); 626 // lines->push_back(HtmlString(text)); 627 // } 628 // else 629 // { 630 // lines->push_back(HtmlString(L"Dyed LOCALISE", eMinecraftColour_NOT_SET, true)); 631 // } 632 //} 633 634 // 4J: Lore isn't in use in game 635 /*if (display->contains(L"Lore")) 636 { 637 ListTag<StringTag> *lore = (ListTag<StringTag> *) display->getList(L"Lore"); 638 if (lore->size() > 0) 639 { 640 for (int i = 0; i < lore->size(); i++) 641 { 642 //lines->push_back(ChatFormatting::DARK_PURPLE + "" + ChatFormatting::ITALIC + lore->get(i)->data); 643 lines->push_back(lore->get(i)->data); 644 } 645 } 646 }*/ 647 } 648 } 649 650 attrAttrModMap *modifiers = getAttributeModifiers(); 651 652 if (!modifiers->empty()) 653 { 654 // New line 655 lines->push_back(HtmlString(L"")); 656 657 // Modifier descriptions 658 for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) 659 { 660 // 4J: Moved modifier string building to AttributeModifier 661 lines->push_back(it->second->getHoverText(it->first)); 662 } 663 } 664 665 // Delete modifiers map 666 for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) 667 { 668 AttributeModifier *modifier = it->second; 669 delete modifier; 670 } 671 delete modifiers; 672 673 if (advanced) 674 { 675 if (isDamaged()) 676 { 677 wstring damageStr = L"Durability: LOCALISE " + _toString<int>((getMaxDamage()) - getDamageValue()) + L" / " + _toString<int>(getMaxDamage()); 678 lines->push_back(HtmlString(damageStr)); 679 } 680 } 681 682 return lines; 683} 684 685// 4J Added 686vector<HtmlString> *ItemInstance::getHoverTextOnly(shared_ptr<Player> player, bool advanced) 687{ 688 vector<HtmlString> *lines = new vector<HtmlString>(); 689 Item *item = Item::items[id]; 690 691 item->appendHoverText(shared_from_this(), player, lines, advanced); 692 693 if (hasTag()) 694 { 695 ListTag<CompoundTag> *list = getEnchantmentTags(); 696 if (list != NULL) 697 { 698 for (int i = 0; i < list->size(); i++) 699 { 700 int type = list->get(i)->getShort((wchar_t *)TAG_ENCH_ID); 701 int level = list->get(i)->getShort((wchar_t *)TAG_ENCH_LEVEL); 702 703 if (Enchantment::enchantments[type] != NULL) 704 { 705 wstring unformatted = L""; 706 lines->push_back(Enchantment::enchantments[type]->getFullname(level)); 707 } 708 } 709 } 710 } 711 return lines; 712} 713 714bool ItemInstance::isFoil() 715{ 716 return getItem()->isFoil(shared_from_this()); 717} 718 719const Rarity *ItemInstance::getRarity() 720{ 721 return getItem()->getRarity(shared_from_this()); 722} 723 724bool ItemInstance::isEnchantable() 725{ 726 if (!getItem()->isEnchantable(shared_from_this())) return false; 727 if (isEnchanted()) return false; 728 return true; 729} 730 731void ItemInstance::enchant(const Enchantment *enchantment, int level) 732{ 733 if (tag == NULL) this->setTag(new CompoundTag()); 734 if (!tag->contains(L"ench")) tag->put(L"ench", new ListTag<CompoundTag>(L"ench")); 735 736 ListTag<CompoundTag> *list = (ListTag<CompoundTag> *) tag->get(L"ench"); 737 CompoundTag *ench = new CompoundTag(); 738 ench->putShort((wchar_t *)TAG_ENCH_ID, (short) enchantment->id); 739 ench->putShort((wchar_t *)TAG_ENCH_LEVEL, (byte) level); 740 list->add(ench); 741} 742 743bool ItemInstance::isEnchanted() 744{ 745 if (tag != NULL && tag->contains(L"ench")) return true; 746 return false; 747} 748 749void ItemInstance::addTagElement(wstring name, Tag *tag) 750{ 751 if (this->tag == NULL) 752 { 753 setTag(new CompoundTag()); 754 } 755 this->tag->put((wchar_t *)name.c_str(), tag); 756} 757 758bool ItemInstance::mayBePlacedInAdventureMode() 759{ 760 return getItem()->mayBePlacedInAdventureMode(); 761} 762 763bool ItemInstance::isFramed() 764{ 765 return frame != NULL; 766} 767 768void ItemInstance::setFramed(shared_ptr<ItemFrame> frame) 769{ 770 this->frame = frame; 771} 772 773shared_ptr<ItemFrame> ItemInstance::getFrame() 774{ 775 return frame; 776} 777 778int ItemInstance::getBaseRepairCost() 779{ 780 if (hasTag() && tag->contains(L"RepairCost")) 781 { 782 return tag->getInt(L"RepairCost"); 783 } 784 else 785 { 786 return 0; 787 } 788} 789 790void ItemInstance::setRepairCost(int cost) 791{ 792 if (!hasTag()) tag = new CompoundTag(); 793 tag->putInt(L"RepairCost", cost); 794} 795 796attrAttrModMap *ItemInstance::getAttributeModifiers() 797{ 798 attrAttrModMap *result = NULL; 799 800 if (hasTag() && tag->contains(L"AttributeModifiers")) 801 { 802 result = new attrAttrModMap(); 803 ListTag<CompoundTag> *entries = (ListTag<CompoundTag> *) tag->getList(L"AttributeModifiers"); 804 805 for (int i = 0; i < entries->size(); i++) 806 { 807 CompoundTag *entry = entries->get(i); 808 AttributeModifier *attribute = SharedMonsterAttributes::loadAttributeModifier(entry); 809 810 // 4J Not sure why but this is a check that the attribute ID is not empty 811 /*if (attribute->getId()->getLeastSignificantBits() != 0 && attribute->getId()->getMostSignificantBits() != 0) 812 {*/ 813 result->insert(std::pair<eATTRIBUTE_ID, AttributeModifier *>(static_cast<eATTRIBUTE_ID>(entry->getInt(L"ID")), attribute)); 814 /*}*/ 815 } 816 } 817 else 818 { 819 result = getItem()->getDefaultAttributeModifiers(); 820 } 821 822 return result; 823} 824 825void ItemInstance::set4JData(int data) 826{ 827 if(tag == NULL && data == 0) return; 828 if (tag == NULL) this->setTag(new CompoundTag()); 829 830 if (tag->contains(L"4jdata")) 831 { 832 IntTag *dataTag = (IntTag *)tag->get(L"4jdata"); 833 dataTag->data = data; 834 } 835 else if(data != 0) 836 { 837 tag->put(L"4jdata", new IntTag(L"4jdata",data)); 838 } 839} 840 841int ItemInstance::get4JData() 842{ 843 if(tag == NULL || !tag->contains(L"4jdata")) return 0; 844 else 845 { 846 IntTag *dataTag = (IntTag *)tag->get(L"4jdata"); 847 return dataTag->data; 848 } 849} 850// 4J Added - to show strength on potions 851bool ItemInstance::hasPotionStrengthBar() 852{ 853 // exclude a bottle of water from this 854 if((id==Item::potion_Id) && (auxValue !=0))// && (!MACRO_POTION_IS_AKWARD(auxValue))) 4J-PB leaving the bar on an awkward potion so we can differentiate it from a water bottle 855 { 856 return true; 857 } 858 859 return false; 860} 861 862int ItemInstance::GetPotionStrength() 863{ 864 if(MACRO_POTION_IS_INSTANTDAMAGE(auxValue) || MACRO_POTION_IS_INSTANTHEALTH(auxValue) ) 865 { 866 // The two instant potions don't have extended versions 867 return (auxValue&MASK_LEVEL2)>>5; 868 } 869 else 870 { 871 return (auxValue&MASK_LEVEL2EXTENDED)>>5; 872 } 873}