diff --git a/changelog.txt b/changelog.txt index 60a1e4b9d..0c9bed583 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,8 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 12/24/2014 == -Trevius: (RoF+) Added herosforgemodel field to the npc_types table. Not fully functional yet for NPCs (currently only displays helm correctly). +Trevius: (RoF+) Added herosforgemodel field to the npc_types table. Trevius: (RoF2) Updated item links from #npcstat command output. +Trevius: (RoF+) Implemented Hero's Forge Armor for NPCs. Set the herosforgemodel field in npc_types table to the model (example: 84 for full set, or 12107 for robe). +Trevius: (RoF+) Hero's Forge Armor now overrides NPC texture settings. To display Hero's Forge Armor Helms, set helmtexture field to anything other than 0. == 12/23/2014 == Uleat: Tidied up some ItemInst* declarations and added some nullptr checks. diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 8a998b94a..c57266f0a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3742,7 +3742,7 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_tattoo); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_details); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2); // unknown8 + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown9 VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown10 VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->helm); // unknown11 diff --git a/zone/mob.cpp b/zone/mob.cpp index 455a1c4ef..8baf361bd 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -925,7 +925,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.animation = 0; ns->spawn.findable = findable?1:0; ns->spawn.light = light; - ns->spawn.showhelm = 1; + ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0; ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players ns->spawn.NPC = IsClient() ? 0 : 1; @@ -945,11 +945,11 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.drakkin_heritage = drakkin_heritage; ns->spawn.drakkin_tattoo = drakkin_tattoo; ns->spawn.drakkin_details = drakkin_details; - ns->spawn.equip_chest2 = texture; + ns->spawn.equip_chest2 = GetHerosForgeModel(1) != 0 ? 0xff : texture; // ns->spawn.invis2 = 0xff;//this used to be labeled beard.. if its not FF it will turn mob invis - if(helmtexture && helmtexture != 0xFF) + if (helmtexture && helmtexture != 0xFF && GetHerosForgeModel(0) == 0) { ns->spawn.helm=helmtexture; } else { @@ -2770,8 +2770,8 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const if (IsNPC()) { HeroModel = CastToNPC()->GetHeroForgeModel(); - // Robes require full model number, and should only be sent to chest slot - if (HeroModel > 1000 && material_slot != 1) + // Robes require full model number, and should only be sent to chest, arms, wrists, and legs slots + if (HeroModel > 1000 && material_slot != 1 && material_slot != 2 && material_slot != 3 && material_slot != 5) { HeroModel = 0; } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 8d5bc1dd0..d067411e6 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1790,7 +1790,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->gender = atoi(row[7]); tmpNPCType->texture = atoi(row[8]); tmpNPCType->helmtexture = atoi(row[9]); - tmpNPCType->herosforgemodel = atoi(row[10]); + tmpNPCType->herosforgemodel = atoul(row[10]); tmpNPCType->size = atof(row[11]); tmpNPCType->loottable_id = atoi(row[12]); tmpNPCType->merchanttype = atoi(row[13]); @@ -1816,7 +1816,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->max_dmg = atoi(row[33]); tmpNPCType->attack_count = atoi(row[34]); - if (row[34] != nullptr) + if (row[35] != nullptr) strn0cpy(tmpNPCType->special_abilities, row[35], 512); else tmpNPCType->special_abilities[0] = '\0'; @@ -1835,7 +1835,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->hp_regen = atoi(row[47]); tmpNPCType->mana_regen = atoi(row[48]); - // set defaultvalue for aggroradius + // set default value for aggroradius tmpNPCType->aggroradius = (int32)atoi(row[49]); if (tmpNPCType->aggroradius <= 0) tmpNPCType->aggroradius = 70; @@ -1844,7 +1844,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { if (tmpNPCType->assistradius <= 0) tmpNPCType->assistradius = tmpNPCType->aggroradius; - if (row[50] && strlen(row[50])) + if (row[51] && strlen(row[51])) tmpNPCType->bodytype = (uint8)atoi(row[51]); else tmpNPCType->bodytype = 0; @@ -1869,10 +1869,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->armor_tint[0] |= (atoi(row[66]) & 0xFF); tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; - if (armor_tint_id == 0) - for (int index = MaterialChest; index <= EmuConstants::MATERIAL_END; index++) - tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; - else if (tmpNPCType->armor_tint[0] == 0) + if (armor_tint_id != 0) { std::string armortint_query = StringFormat("SELECT red1h, grn1h, blu1h, " "red2c, grn2c, blu2c, " @@ -1887,23 +1884,34 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { armor_tint_id); auto armortint_results = QueryDatabase(armortint_query); if (!armortint_results.Success() || armortint_results.RowCount() == 0) - armor_tint_id = 0; - else { + { + armor_tint_id = 0; + } + else + { auto armorTint_row = armortint_results.begin(); - for (int index = EmuConstants::MATERIAL_BEGIN; index <= EmuConstants::MATERIAL_END; index++) { + for (int index = EmuConstants::MATERIAL_BEGIN; index <= EmuConstants::MATERIAL_END; index++) + { tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); tmpNPCType->armor_tint[index] |= (tmpNPCType->armor_tint[index]) ? (0xFF << 24) : 0; } } - } else - armor_tint_id = 0; + } + // Try loading npc_types tint fields if armor tint is 0 or query failed to get results + if (armor_tint_id == 0) + { + for (int index = MaterialChest; index < _MaterialCount; index++) + { + tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; + } + } tmpNPCType->see_invis = atoi(row[67]); tmpNPCType->see_invis_undead = atoi(row[68]) == 0? false: true; // Set see_invis_undead flag - if (row[68] != nullptr) + if (row[69] != nullptr) strn0cpy(tmpNPCType->lastname, row[69], 32); tmpNPCType->qglobal = atoi(row[70]) == 0? false: true; // qglobal