[Feature] Add Support for item textures higher than 65,535 (#3494)

* [Feature] Add Support for item textures higher than 65,535

# Notes
- We were previously using `uint16` which has a max of `65,535`, but some of the new Live textures that are being used have values way beyond this.
- Updates quest API, commands, and database tables that also used `uint16`.

* Update version.h
This commit is contained in:
Alex King 2023-07-14 18:49:59 -04:00 committed by GitHub
parent b01486d767
commit e55f9b9d27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 178 additions and 262 deletions

View File

@ -4778,6 +4778,17 @@ UNIQUE KEY `name` (`name`)
ADD COLUMN `marked_npc_3` SMALLINT UNSIGNED DEFAULT(0) NOT NULL AFTER `marked_npc_2`;
)",
},
ManifestEntry{
.version = 9231,
.description = "2023_07_14_npc_unsigned_melee_texture.sql",
.check = "SHOW COLUMNS FROM `npc_types` LIKE 'd_melee_texture1'",
.condition = "contains",
.match = "int(11) signed",
.sql = R"(ALTER TABLE `npc_types`
MODIFY COLUMN `d_melee_texture1` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `armortint_blue`,
MODIFY COLUMN `d_melee_texture2` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `d_melee_texture1`;
)",
},
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{

View File

@ -66,8 +66,8 @@ public:
uint8_t armortint_red;
uint8_t armortint_green;
uint8_t armortint_blue;
int32_t d_melee_texture1;
int32_t d_melee_texture2;
uint32_t d_melee_texture1;
uint32_t d_melee_texture2;
std::string ammo_idfile;
uint8_t prim_melee_type;
uint8_t sec_melee_type;
@ -583,7 +583,7 @@ public:
e.exp_mod = 100;
e.heroic_strikethrough = 0;
e.faction_amount = 0;
e.keeps_sold_items = 0;
e.keeps_sold_items = 1;
return e;
}
@ -666,8 +666,8 @@ public:
e.armortint_red = static_cast<uint8_t>(strtoul(row[43], nullptr, 10));
e.armortint_green = static_cast<uint8_t>(strtoul(row[44], nullptr, 10));
e.armortint_blue = static_cast<uint8_t>(strtoul(row[45], nullptr, 10));
e.d_melee_texture1 = static_cast<int32_t>(atoi(row[46]));
e.d_melee_texture2 = static_cast<int32_t>(atoi(row[47]));
e.d_melee_texture1 = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.d_melee_texture2 = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.ammo_idfile = row[48] ? row[48] : "";
e.prim_melee_type = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
e.sec_melee_type = static_cast<uint8_t>(strtoul(row[50], nullptr, 10));
@ -1289,8 +1289,8 @@ public:
e.armortint_red = static_cast<uint8_t>(strtoul(row[43], nullptr, 10));
e.armortint_green = static_cast<uint8_t>(strtoul(row[44], nullptr, 10));
e.armortint_blue = static_cast<uint8_t>(strtoul(row[45], nullptr, 10));
e.d_melee_texture1 = static_cast<int32_t>(atoi(row[46]));
e.d_melee_texture2 = static_cast<int32_t>(atoi(row[47]));
e.d_melee_texture1 = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.d_melee_texture2 = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.ammo_idfile = row[48] ? row[48] : "";
e.prim_melee_type = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
e.sec_melee_type = static_cast<uint8_t>(strtoul(row[50], nullptr, 10));
@ -1440,8 +1440,8 @@ public:
e.armortint_red = static_cast<uint8_t>(strtoul(row[43], nullptr, 10));
e.armortint_green = static_cast<uint8_t>(strtoul(row[44], nullptr, 10));
e.armortint_blue = static_cast<uint8_t>(strtoul(row[45], nullptr, 10));
e.d_melee_texture1 = static_cast<int32_t>(atoi(row[46]));
e.d_melee_texture2 = static_cast<int32_t>(atoi(row[47]));
e.d_melee_texture1 = static_cast<uint32_t>(strtoul(row[46], nullptr, 10));
e.d_melee_texture2 = static_cast<uint32_t>(strtoul(row[47], nullptr, 10));
e.ammo_idfile = row[48] ? row[48] : "";
e.prim_melee_type = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
e.sec_melee_type = static_cast<uint8_t>(strtoul(row[50], nullptr, 10));

View File

@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9230
#define CURRENT_BINARY_DATABASE_VERSION 9231
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9039

View File

@ -2315,17 +2315,17 @@ void Perl__removetitle(int title_set)
quest_manager.removetitle(title_set);
}
void Perl__wearchange(uint8 slot, uint16 texture_id)
void Perl__wearchange(uint8 slot, uint32 texture_id)
{
quest_manager.wearchange(slot, texture_id);
}
void Perl__wearchange(uint8 slot, uint16 texture_id, uint32 hero_forge_model_id)
void Perl__wearchange(uint8 slot, uint32 texture_id, uint32 hero_forge_model_id)
{
quest_manager.wearchange(slot, texture_id, hero_forge_model_id);
}
void Perl__wearchange(uint8 slot, uint16 texture_id, uint32 hero_forge_model_id, uint32 elite_material_id)
void Perl__wearchange(uint8 slot, uint32 texture_id, uint32 hero_forge_model_id, uint32 elite_material_id)
{
quest_manager.wearchange(slot, texture_id, hero_forge_model_id, elite_material_id);
}
@ -6214,9 +6214,9 @@ void perl_register_quest()
package.add("varlink", (std::string(*)(uint32, int16, uint32, uint32, uint32, uint32, uint32, uint32, bool))&Perl__varlink);
package.add("voicetell", &Perl__voicetell);
package.add("we", &Perl__we);
package.add("wearchange", (void(*)(uint8, uint16))&Perl__wearchange);
package.add("wearchange", (void(*)(uint8, uint16, uint32))&Perl__wearchange);
package.add("wearchange", (void(*)(uint8, uint16, uint32, uint32))&Perl__wearchange);
package.add("wearchange", (void(*)(uint8, uint32))&Perl__wearchange);
package.add("wearchange", (void(*)(uint8, uint32, uint32))&Perl__wearchange);
package.add("wearchange", (void(*)(uint8, uint32, uint32, uint32))&Perl__wearchange);
package.add("whisper", &Perl__whisper);
package.add("write", &Perl__write);
package.add("ze", &Perl__ze);

View File

@ -19,13 +19,14 @@ void command_wc(Client *c, const Seperator *sep)
t = c->GetTarget();
}
const auto slot_id = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[1]));
const auto texture = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[2]));
uint32 hero_forge_model = 0;
uint32 elite_material = 0;
const uint8 slot_id = Strings::ToUnsignedInt(sep->arg[1]);
const uint32 texture = Strings::ToUnsignedInt(sep->arg[2]);
uint32 hero_forge_model = 0;
uint32 elite_material = 0;
if (arguments >= 3 && sep->IsNumber(3)) {
hero_forge_model = Strings::ToUnsignedInt(sep->arg[3]);
if (EQ::ValueWithin(hero_forge_model, 1, 999)) { // Shorthand Hero Forge ID. Otherwise use the value the user entered.
hero_forge_model = (hero_forge_model * 100) + slot_id;
}
@ -35,7 +36,7 @@ void command_wc(Client *c, const Seperator *sep)
elite_material = Strings::ToUnsignedInt(sep->arg[4]);
}
c->GetTarget()->SendTextureWC(
t->SendTextureWC(
slot_id,
texture,
hero_forge_model,

View File

@ -3135,21 +3135,6 @@ uint32 Client::GetEquippedItemFromTextureSlot(uint8 material_slot) const
return 0;
}
#if 0
int32 Client::GetEquipmentMaterial(uint8 material_slot)
{
const ItemData *item;
item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
if(item != 0)
{
return item->Material;
}
return 0;
}
#endif
uint32 Client::GetEquipmentColor(uint8 material_slot) const
{
if (material_slot > EQ::textures::LastTexture)

View File

@ -5145,8 +5145,8 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float
LuaCreateNPCParse(max_dmg, uint32, 4);
LuaCreateNPCParse(attack_count, int16, 0);
LuaCreateNPCParseString(special_abilities, 512, "");
LuaCreateNPCParse(d_melee_texture1, uint16, 0);
LuaCreateNPCParse(d_melee_texture2, uint16, 0);
LuaCreateNPCParse(d_melee_texture1, uint32, 0);
LuaCreateNPCParse(d_melee_texture2, uint32, 0);
LuaCreateNPCParseString(ammo_idfile, 30, "");
LuaCreateNPCParse(prim_melee_type, uint8, 0);
LuaCreateNPCParse(sec_melee_type, uint8, 0);

View File

@ -1902,17 +1902,17 @@ void Lua_Mob::SetSlotTint(int material_slot, int red_tint, int green_tint, int b
self->SetSlotTint(material_slot, red_tint, green_tint, blue_tint);
}
void Lua_Mob::WearChange(uint8 material_slot, uint16 texture) {
void Lua_Mob::WearChange(uint8 material_slot, uint32 texture) {
Lua_Safe_Call_Void();
self->WearChange(material_slot, texture);
}
void Lua_Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color) {
void Lua_Mob::WearChange(uint8 material_slot, uint32 texture, uint32 color) {
Lua_Safe_Call_Void();
self->WearChange(material_slot, texture, color);
}
void Lua_Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 heros_forge_model) {
void Lua_Mob::WearChange(uint8 material_slot, uint32 texture, uint32 color, uint32 heros_forge_model) {
Lua_Safe_Call_Void();
self->WearChange(material_slot, texture, color, heros_forge_model);
}
@ -3649,9 +3649,9 @@ luabind::scope lua_register_mob() {
.def("TryMoveAlong", (void(Lua_Mob::*)(float,float,bool))&Lua_Mob::TryMoveAlong)
.def("UnStun", (void(Lua_Mob::*)(void))&Lua_Mob::UnStun)
.def("WalkTo", (void(Lua_Mob::*)(double, double, double))&Lua_Mob::WalkTo)
.def("WearChange", (void(Lua_Mob::*)(uint8,uint16))&Lua_Mob::WearChange)
.def("WearChange", (void(Lua_Mob::*)(uint8,uint16,uint32))&Lua_Mob::WearChange)
.def("WearChange", (void(Lua_Mob::*)(uint8,uint16,uint32,uint32))&Lua_Mob::WearChange)
.def("WearChange", (void(Lua_Mob::*)(uint8,uint32))&Lua_Mob::WearChange)
.def("WearChange", (void(Lua_Mob::*)(uint8,uint32,uint32))&Lua_Mob::WearChange)
.def("WearChange", (void(Lua_Mob::*)(uint8,uint32,uint32,uint32))&Lua_Mob::WearChange)
.def("WipeHateList", (void(Lua_Mob::*)(void))&Lua_Mob::WipeHateList);
}

View File

@ -386,9 +386,9 @@ public:
void TarGlobal(const char *varname, const char *value, const char *duration, int npc_id, int char_id, int zone_id);
void DelGlobal(const char *varname);
void SetSlotTint(int material_slot, int red_tint, int green_tint, int blue_tint);
void WearChange(uint8 material_slot, uint16 texture);
void WearChange(uint8 material_slot, uint16 texture, uint32 color);
void WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 heros_forge_model);
void WearChange(uint8 material_slot, uint32 texture);
void WearChange(uint8 material_slot, uint32 texture, uint32 color);
void WearChange(uint8 material_slot, uint32 texture, uint32 color, uint32 heros_forge_model);
void DoKnockback(Lua_Mob caster, uint32 push_back, uint32 push_up);
void AddNimbusEffect(int effect_id);
void RemoveNimbusEffect(int effect_id);

View File

@ -277,8 +277,8 @@ protected:
uint16 skills[EQ::skills::HIGHEST_SKILL + 1];
uint32 equipment[EQ::invslot::EQUIPMENT_COUNT]; //this is an array of item IDs
uint16 d_melee_texture1; //this is an item Material value
uint16 d_melee_texture2; //this is an item Material value (offhand)
uint32 d_melee_texture1; //this is an item Material value
uint32 d_melee_texture2; //this is an item Material value (offhand)
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation

View File

@ -290,15 +290,15 @@ public:
EQ::skills::SkillType AttackAnimation(int Hand, const EQ::ItemInstance* weapon, EQ::skills::SkillType skillinuse = EQ::skills::Skill1HBlunt);
int32 GetTextureProfileMaterial(uint8 material_slot) const;
int32 GetTextureProfileColor(uint8 material_slot) const;
int32 GetTextureProfileHeroForgeModel(uint8 material_slot) const;
uint32 GetTextureProfileMaterial(uint8 material_slot) const;
uint32 GetTextureProfileColor(uint8 material_slot) const;
uint32 GetTextureProfileHeroForgeModel(uint8 material_slot) const;
virtual void SendArmorAppearance(Client *one_client = nullptr);
virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, uint32 unknown06 = 0, uint32 unknown18 = 0);
virtual void SendTextureWC(uint8 slot, uint32 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, uint32 unknown06 = 0, uint32 unknown18 = 0);
virtual void SendWearChange(uint8 material_slot, Client *one_client = nullptr);
virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint);
virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color = 0, uint32 hero_forge_model = 0);
virtual void WearChange(uint8 material_slot, uint32 texture, uint32 color = 0, uint32 hero_forge_model = 0);
void ChangeSize(float in_size, bool bNoRestriction = false);
void DoAnim(const int animation_id, int animation_speed = 0, bool ackreq = true, eqFilterType filter = FilterNone);
@ -308,7 +308,7 @@ public:
void SendLevelAppearance();
void SendStunAppearance();
void SendTargetable(bool on, Client *specific_target = nullptr);
void SetMobTextureProfile(uint8 material_slot, uint16 texture, uint32 color = 0, uint32 hero_forge_model = 0);
void SetMobTextureProfile(uint8 material_slot, uint32 texture, uint32 color = 0, uint32 hero_forge_model = 0);
//Spell
void SendSpellEffect(uint32 effect_id, uint32 duration, uint32 finish_delay, bool zone_wide,
@ -503,9 +503,9 @@ public:
virtual uint8 ConvertItemTypeToSkillID(uint8 item_type);
virtual uint16 GetSkill(EQ::skills::SkillType skill_num) const { return 0; }
virtual uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const { return(0); }
virtual int32 GetEquipmentMaterial(uint8 material_slot) const;
virtual uint32 GetEquipmentMaterial(uint8 material_slot) const;
virtual uint8 GetEquipmentType(uint8 material_slot) const;
virtual int32 GetHerosForgeModel(uint8 material_slot) const;
virtual uint32 GetHerosForgeModel(uint8 material_slot) const;
virtual uint32 GetEquipmentColor(uint8 material_slot) const;
virtual uint32 IsEliteMaterialItem(uint8 material_slot) const;
bool CanClassEquipItem(uint32 item_id);

View File

@ -30,18 +30,15 @@
#include "bot.h"
/**
* Stores internal representation of mob texture by material slot
*
* @param material_slot
* @param texture
* @param color
* @param hero_forge_model
*/
void Mob::SetMobTextureProfile(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model)
void Mob::SetMobTextureProfile(
uint8 material_slot,
uint32 texture,
uint32 color,
uint32 hero_forge_model
)
{
Log(Logs::Detail, Logs::MobAppearance,
"[%s] material_slot: %u texture: %u color: %u hero_forge_model: %u",
LogMobAppearanceDetail(
"[{}] material_slot [{}] texture [{}] color [{}] hero_forge_model [{}]",
GetCleanName(),
material_slot,
texture,
@ -100,13 +97,7 @@ void Mob::SetMobTextureProfile(uint8 material_slot, uint16 texture, uint32 color
}
}
/**
* Returns internal representation of mob texture by material
*
* @param material_slot
* @return
*/
int32 Mob::GetTextureProfileMaterial(uint8 material_slot) const
uint32 Mob::GetTextureProfileMaterial(uint8 material_slot) const
{
switch (material_slot) {
case EQ::textures::armorHead:
@ -132,13 +123,7 @@ int32 Mob::GetTextureProfileMaterial(uint8 material_slot) const
}
}
/**
* Returns internal representation of mob texture by color
*
* @param material_slot
* @return
*/
int32 Mob::GetTextureProfileColor(uint8 material_slot) const
uint32 Mob::GetTextureProfileColor(uint8 material_slot) const
{
switch (material_slot) {
case EQ::textures::armorHead:
@ -164,13 +149,7 @@ int32 Mob::GetTextureProfileColor(uint8 material_slot) const
}
}
/**
* Returns internal representation of mob texture by HerosForgeModel
*
* @param material_slot
* @return
*/
int32 Mob::GetTextureProfileHeroForgeModel(uint8 material_slot) const
uint32 Mob::GetTextureProfileHeroForgeModel(uint8 material_slot) const
{
switch (material_slot) {
case EQ::textures::armorHead:
@ -196,25 +175,19 @@ int32 Mob::GetTextureProfileHeroForgeModel(uint8 material_slot) const
}
}
/**
* Gets the material or texture for a slot (leather / plate etc.)
*
* @param material_slot
* @return
*/
int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
uint32 Mob::GetEquipmentMaterial(uint8 material_slot) const
{
uint32 equipment_material = 0;
int32 texture_profile_material = GetTextureProfileMaterial(material_slot);
uint32 equipment_material = 0;
const uint32 texture_profile_material = GetTextureProfileMaterial(material_slot);
LogMobAppearance(
"[{}] material_slot: {} texture_profile_material: {}",
"[{}] material_slot [{}] texture_profile_material [{}]",
clean_name,
material_slot,
texture_profile_material
);
if (texture_profile_material > 0) {
if (texture_profile_material) {
return texture_profile_material;
}
@ -230,7 +203,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
return 0;
}
const auto* inst = CastToClient()->m_inv[inventory_slot];
const auto inst = CastToClient()->m_inv[inventory_slot];
if (inst) {
const auto augment = inst->GetOrnamentationAugment();
@ -238,7 +211,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
if (augment) {
item = augment->GetItem();
if (item && strlen(item->IDFile) > 2 && Strings::IsNumber(&item->IDFile[2])) {
equipment_material = Strings::ToInt(&item->IDFile[2]);
equipment_material = Strings::ToUnsignedInt(&item->IDFile[2]);
}
} else if (inst->GetOrnamentationIDFile()) {
equipment_material = inst->GetOrnamentationIDFile();
@ -247,10 +220,9 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
}
if (!equipment_material && strlen(item->IDFile) > 2 && Strings::IsNumber(&item->IDFile[2])) {
equipment_material = Strings::ToInt(&item->IDFile[2]);
equipment_material = Strings::ToUnsignedInt(&item->IDFile[2]);
}
}
else {
} else {
equipment_material = item->Material;
}
}
@ -260,8 +232,8 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
uint8 Mob::GetEquipmentType(uint8 material_slot) const
{
auto item_type = static_cast<uint8>(EQ::item::ItemType2HBlunt);
auto item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
const auto item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
auto item_type = static_cast<uint8>(EQ::item::ItemType2HBlunt);
if (item) {
const auto is_equipped_weapon = EQ::ValueWithin(material_slot, EQ::textures::weaponPrimary, EQ::textures::weaponSecondary);
@ -273,7 +245,7 @@ uint8 Mob::GetEquipmentType(uint8 material_slot) const
return item_type;
}
const auto* inst = CastToClient()->m_inv[inventory_slot];
const auto inst = CastToClient()->m_inv[inventory_slot];
if (inst) {
item_type = inst->GetItemType();
}
@ -284,36 +256,26 @@ uint8 Mob::GetEquipmentType(uint8 material_slot) const
return item_type;
}
/**
* @param material_slot
* @return
*/
uint32 Mob::GetEquipmentColor(uint8 material_slot) const
{
const EQ::ItemData *item = nullptr;
if (armor_tint.Slot[material_slot].Color) {
return armor_tint.Slot[material_slot].Color;
}
item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
if (item != nullptr) {
const auto item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
if (item) {
return item->Color;
}
return 0;
}
/**
* @param material_slot
* @return
*/
int32 Mob::GetHerosForgeModel(uint8 material_slot) const
uint32 Mob::GetHerosForgeModel(uint8 material_slot) const
{
uint32 hero_model = 0;
uint32 heros_forge_model = 0;
if (EQ::ValueWithin(material_slot, 0, EQ::textures::weaponPrimary)) {
const EQ::ItemData *item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
const auto slot = EQ::InventoryProfile::CalcSlotFromMaterial(material_slot);
auto item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
const auto slot = EQ::InventoryProfile::CalcSlotFromMaterial(material_slot);
if (item && slot != INVALID_INDEX) {
if (IsClient()) {
@ -322,33 +284,33 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const
const auto augment = inst->GetOrnamentationAugment();
if (augment) {
item = augment->GetItem();
hero_model = item->HerosForgeModel;
item = augment->GetItem();
heros_forge_model = item->HerosForgeModel;
} else if (inst->GetOrnamentHeroModel()) {
hero_model = inst->GetOrnamentHeroModel();
heros_forge_model = inst->GetOrnamentHeroModel();
}
}
}
if (hero_model == 0) {
hero_model = item->HerosForgeModel;
if (!heros_forge_model) {
heros_forge_model = item->HerosForgeModel;
}
}
if (IsNPC()) {
hero_model = CastToNPC()->GetHeroForgeModel();
heros_forge_model = CastToNPC()->GetHeroForgeModel();
/**
* Robes require full model number, and should only be sent to chest, arms, wrists, and legs slots
*/
if (
hero_model > 1000 &&
heros_forge_model > 1000 &&
material_slot != EQ::textures::armorChest &&
material_slot != EQ::textures::armorArms &&
material_slot != EQ::textures::armorWrist &&
material_slot != EQ::textures::armorLegs
) {
hero_model = 0;
heros_forge_model = 0;
}
}
}
@ -359,21 +321,21 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const
* Otherwise, use the exact Model if model is > 999
* Robes for example are 11607 to 12107 in RoF
*/
if (EQ::ValueWithin(hero_model, 1, 999)) {
hero_model *= 100;
hero_model += material_slot;
if (EQ::ValueWithin(heros_forge_model, 1, 999)) {
heros_forge_model *= 100;
heros_forge_model += material_slot;
}
return hero_model;
return heros_forge_model;
}
uint32 NPC::GetEquippedItemFromTextureSlot(uint8 material_slot) const
{
if (material_slot > 8) {
if (material_slot >= EQ::textures::materialCount) {
return 0;
}
int16 inventory_slot = EQ::InventoryProfile::CalcSlotFromMaterial(material_slot);
const int16 inventory_slot = EQ::InventoryProfile::CalcSlotFromMaterial(material_slot);
if (inventory_slot == INVALID_INDEX) {
return 0;
}
@ -381,10 +343,6 @@ uint32 NPC::GetEquippedItemFromTextureSlot(uint8 material_slot) const
return equipment[inventory_slot];
}
/**
* NPCs typically use this function for sending appearance
* @param one_client
*/
void Mob::SendArmorAppearance(Client *one_client)
{
/**
@ -402,114 +360,84 @@ void Mob::SendArmorAppearance(Client *one_client)
if (IsPlayerRace(race)) {
if (!IsClient()) {
for (uint8 i = 0; i <= EQ::textures::materialCount; ++i) {
const EQ::ItemData *item = database.GetItem(GetEquippedItemFromTextureSlot(i));
if (item != nullptr) {
SendWearChange(i, one_client);
for (uint8 slot_id = 0; slot_id <= EQ::textures::materialCount; ++slot_id) {
const auto item = database.GetItem(GetEquippedItemFromTextureSlot(slot_id));
if (item) {
SendWearChange(slot_id, one_client);
}
}
}
}
for (uint8 i = 0; i <= EQ::textures::materialCount; ++i) {
if (GetTextureProfileMaterial(i)) {
SendWearChange(i, one_client);
for (uint8 slot_id = 0; slot_id <= EQ::textures::materialCount; ++slot_id) {
if (GetTextureProfileMaterial(slot_id)) {
SendWearChange(slot_id, one_client);
}
}
}
/**
* @param material_slot
* @param one_client
*/
void Mob::SendWearChange(uint8 material_slot, Client *one_client)
{
auto packet = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
auto *wear_change = (WearChange_Struct *) packet->pBuffer;
auto packet = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
auto w = (WearChange_Struct *) packet->pBuffer;
Log(Logs::Detail, Logs::MobAppearance, "[%s]",
GetCleanName()
);
wear_change->spawn_id = GetID();
wear_change->material = static_cast<uint32>(GetEquipmentMaterial(material_slot));
wear_change->elite_material = IsEliteMaterialItem(material_slot);
wear_change->hero_forge_model = static_cast<uint32>(GetHerosForgeModel(material_slot));
w->spawn_id = GetID();
w->material = static_cast<uint32>(GetEquipmentMaterial(material_slot));
w->elite_material = IsEliteMaterialItem(material_slot);
w->hero_forge_model = static_cast<uint32>(GetHerosForgeModel(material_slot));
if (IsBot()) {
auto item_inst = CastToBot()->GetBotItem(EQ::InventoryProfile::CalcSlotFromMaterial(material_slot));
if (item_inst)
wear_change->color.Color = item_inst->GetColor();
else
wear_change->color.Color = 0;
}
else {
wear_change->color.Color = GetEquipmentColor(material_slot);
const auto item_inst = CastToBot()->GetBotItem(EQ::InventoryProfile::CalcSlotFromMaterial(material_slot));
w->color.Color = item_inst ? item_inst->GetColor() : 0;
} else {
w->color.Color = GetEquipmentColor(material_slot);
}
wear_change->wear_slot_id = material_slot;
w->wear_slot_id = material_slot;
// Part of a bug fix to ensure heroforge models send to other clients in zone.
queue_wearchange_slot = wear_change->hero_forge_model ? material_slot : -1;
queue_wearchange_slot = w->hero_forge_model ? material_slot : -1;
if (!one_client) {
entity_list.QueueClients(this, packet);
}
else {
} else {
one_client->QueuePacket(packet, false, Client::CLIENT_CONNECTED);
}
safe_delete(packet);
}
/**
*
* @param slot
* @param texture
* @param hero_forge_model
* @param elite_material
* @param unknown06
* @param unknown18
*/
void Mob::SendTextureWC(
uint8 slot,
uint16 texture,
uint32 texture,
uint32 hero_forge_model,
uint32 elite_material,
uint32 unknown06,
uint32 unknown18
)
{
auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
auto *wear_change = (WearChange_Struct *) outapp->pBuffer;
auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
auto w = (WearChange_Struct *) outapp->pBuffer;
if (IsClient()) {
wear_change->color.Color = GetEquipmentColor(slot);
}
else {
wear_change->color.Color = GetArmorTint(slot);
}
w->color.Color = IsClient() ? GetEquipmentColor(slot) : GetArmorTint(slot);
w->spawn_id = GetID();
w->material = texture;
w->wear_slot_id = slot;
w->unknown06 = unknown06;
w->elite_material = elite_material;
w->hero_forge_model = hero_forge_model;
w->unknown18 = unknown18;
wear_change->spawn_id = GetID();
wear_change->material = texture;
wear_change->wear_slot_id = slot;
wear_change->unknown06 = unknown06;
wear_change->elite_material = elite_material;
wear_change->hero_forge_model = hero_forge_model;
wear_change->unknown18 = unknown18;
SetMobTextureProfile(slot, texture, wear_change->color.Color, hero_forge_model);
SetMobTextureProfile(slot, texture, w->color.Color, hero_forge_model);
entity_list.QueueClients(this, outapp);
safe_delete(outapp);
}
/**
* @param material_slot
* @param red_tint
* @param green_tint
* @param blue_tint
*/
void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint)
{
uint32 color;
@ -520,13 +448,13 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin
armor_tint.Slot[material_slot].Color = color;
auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
auto *wc = (WearChange_Struct *) outapp->pBuffer;
auto w = (WearChange_Struct *) outapp->pBuffer;
wc->spawn_id = GetID();
wc->material = GetEquipmentMaterial(material_slot);
wc->hero_forge_model = GetHerosForgeModel(material_slot);
wc->color.Color = color;
wc->wear_slot_id = material_slot;
w->spawn_id = GetID();
w->material = GetEquipmentMaterial(material_slot);
w->hero_forge_model = GetHerosForgeModel(material_slot);
w->color.Color = color;
w->wear_slot_id = material_slot;
SetMobTextureProfile(material_slot, texture, color);
@ -534,32 +462,25 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin
safe_delete(outapp);
}
/**
* @param material_slot
* @param texture
* @param color
* @param hero_forge_model
*/
void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model)
void Mob::WearChange(
uint8 material_slot,
uint32 texture,
uint32 color,
uint32 hero_forge_model
)
{
armor_tint.Slot[material_slot].Color = color;
/**
* Change internal values
*/
SetMobTextureProfile(material_slot, texture, color, hero_forge_model);
/**
* Packet update
*/
auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
auto *wear_change = (WearChange_Struct *) outapp->pBuffer;
auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
auto w = (WearChange_Struct *) outapp->pBuffer;
wear_change->spawn_id = GetID();
wear_change->material = texture;
wear_change->hero_forge_model = hero_forge_model;
wear_change->color.Color = color;
wear_change->wear_slot_id = material_slot;
w->spawn_id = GetID();
w->material = texture;
w->hero_forge_model = hero_forge_model;
w->color.Color = color;
w->wear_slot_id = material_slot;
entity_list.QueueClients(this, outapp);
safe_delete(outapp);

View File

@ -1408,8 +1408,8 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
npc_type->texture = Strings::ToInt(sep.arg[3]);
npc_type->light = 0;
npc_type->runspeed = 1.25f;
npc_type->d_melee_texture1 = Strings::ToInt(sep.arg[7]);
npc_type->d_melee_texture2 = Strings::ToInt(sep.arg[8]);
npc_type->d_melee_texture1 = Strings::ToUnsignedInt(sep.arg[7]);
npc_type->d_melee_texture2 = Strings::ToUnsignedInt(sep.arg[8]);
npc_type->merchanttype = Strings::ToInt(sep.arg[9]);
npc_type->bodytype = Strings::ToInt(sep.arg[10]);
@ -1789,16 +1789,16 @@ uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_ver
return false;
}
int32 NPC::GetEquipmentMaterial(uint8 material_slot) const
uint32 NPC::GetEquipmentMaterial(uint8 material_slot) const
{
int32 texture_profile_material = GetTextureProfileMaterial(material_slot);
const uint32 texture_profile_material = GetTextureProfileMaterial(material_slot);
Log(Logs::Detail, Logs::MobAppearance, "[%s] material_slot: %u",
clean_name,
material_slot
);
if (texture_profile_material > 0) {
if (texture_profile_material) {
return texture_profile_material;
}
@ -1833,12 +1833,12 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const
return d_melee_texture2;
default:
//they have nothing in the slot, and its not a special slot... they get nothing.
return (0);
return 0;
}
}
//they have some loot item in this slot, pass it up to the default handler
return (Mob::GetEquipmentMaterial(material_slot));
return Mob::GetEquipmentMaterial(material_slot);
}
uint32 NPC::GetMaxDamage(uint8 tlevel)
@ -2967,15 +2967,13 @@ uint32 NPC::GetSpawnPointID() const
return 0;
}
void NPC::NPCSlotTexture(uint8 slot, uint16 texture)
void NPC::NPCSlotTexture(uint8 slot, uint32 texture)
{
if (slot == EQ::invslot::slotNeck) {
if (slot == EQ::textures::TextureSlot::weaponPrimary) {
d_melee_texture1 = texture;
}
else if (slot == EQ::invslot::slotBack) {
} else if (slot == EQ::textures::TextureSlot::weaponSecondary) {
d_melee_texture2 = texture;
}
else if (slot < EQ::invslot::slotShoulders) {
} else {
// Reserved for texturing individual armor slots
}
}

View File

@ -350,7 +350,7 @@ public:
int GetClosestWaypoint(const glm::vec3& location);
uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const; // returns item id
int32 GetEquipmentMaterial(uint8 material_slot) const;
uint32 GetEquipmentMaterial(uint8 material_slot) const;
void NextGuardPosition();
void SaveGuardSpot(bool ClearGuardSpot = false);
@ -452,7 +452,7 @@ public:
bool GetDepop() { return p_depop; }
void NPCSlotTexture(uint8 slot, uint16 texture); // Sets new material values for slots
void NPCSlotTexture(uint8 slot, uint32 texture); // Sets new material values for slots
uint32 GetAdventureTemplate() const { return adventure_template_id; }
void AddSpellToNPCList(int16 iPriority, uint16 iSpellID, uint32 iType, int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust, int8 min_hp, int8 max_hp);
@ -648,9 +648,9 @@ protected:
uint32 equipment[EQ::invslot::EQUIPMENT_COUNT]; //this is an array of item IDs
uint32 herosforgemodel; //this is the Hero Forge Armor Model (i.e 63 or 84 or 203)
uint16 d_melee_texture1;
uint32 d_melee_texture1;
//this is an item Material value
uint16 d_melee_texture2; //this is an item Material value (offhand)
uint32 d_melee_texture2; //this is an item Material value (offhand)
const char* ammo_idfile; //this determines projectile graphic "IT###" (see item field 'idfile')
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation

View File

@ -176,17 +176,17 @@ void Perl_Mob_SendWearChange(Mob* self, uint8_t material_slot) // @categories Sc
self->SendWearChange(material_slot);
}
int32_t Perl_Mob_GetEquipment(Mob* self, uint8_t material_slot) // @categories Inventory and Items
uint32_t Perl_Mob_GetEquipment(Mob* self, uint8_t material_slot) // @categories Inventory and Items
{
return self->GetEquippedItemFromTextureSlot(material_slot);
}
int32_t Perl_Mob_GetEquipmentMaterial(Mob* self, uint8_t material_slot) // @categories Inventory and Items
uint32_t Perl_Mob_GetEquipmentMaterial(Mob* self, uint8_t material_slot) // @categories Inventory and Items
{
return self->GetEquipmentMaterial(material_slot);
}
int32_t Perl_Mob_GetEquipmentColor(Mob* self, uint8_t material_slot) // @categories Inventory and Items
uint32_t Perl_Mob_GetEquipmentColor(Mob* self, uint8_t material_slot) // @categories Inventory and Items
{
return self->GetEquipmentColor(material_slot);
}
@ -2062,17 +2062,17 @@ void Perl_Mob_SetSlotTint(Mob* self, uint8 material_slot, uint8 red_tint, uint8
self->SetSlotTint(material_slot, red_tint, green_tint, blue_tint);
}
void Perl_Mob_WearChange(Mob* self, uint8 material_slot, uint16 texture) // @categories Script Utility
void Perl_Mob_WearChange(Mob* self, uint8 material_slot, uint32 texture) // @categories Script Utility
{
self->WearChange(material_slot, texture);
}
void Perl_Mob_WearChange(Mob* self, uint8 material_slot, uint16 texture, uint32 color) // @categories Script Utility
void Perl_Mob_WearChange(Mob* self, uint8 material_slot, uint32 texture, uint32 color) // @categories Script Utility
{
self->WearChange(material_slot, texture, color);
}
void Perl_Mob_WearChange(Mob* self, uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model) // @categories Script Utility
void Perl_Mob_WearChange(Mob* self, uint8 material_slot, uint32 texture, uint32 color, uint32 hero_forge_model) // @categories Script Utility
{
self->WearChange(material_slot, texture, color, hero_forge_model);
}
@ -3705,9 +3705,9 @@ void perl_register_mob()
package.add("TypesTempPet", (void(*)(Mob*, uint32, const char*, uint32, bool, Mob*))&Perl_Mob_TypesTempPet);
package.add("TypesTempPet", (void(*)(Mob*, uint32, const char*, uint32, bool, Mob*, bool))&Perl_Mob_TypesTempPet);
package.add("WalkTo", &Perl_Mob_WalkTo);
package.add("WearChange", (void(*)(Mob*, uint8, uint16))&Perl_Mob_WearChange);
package.add("WearChange", (void(*)(Mob*, uint8, uint16, uint32))&Perl_Mob_WearChange);
package.add("WearChange", (void(*)(Mob*, uint8, uint16, uint32, uint32))&Perl_Mob_WearChange);
package.add("WearChange", (void(*)(Mob*, uint8, uint32))&Perl_Mob_WearChange);
package.add("WearChange", (void(*)(Mob*, uint8, uint32, uint32))&Perl_Mob_WearChange);
package.add("WearChange", (void(*)(Mob*, uint8, uint32, uint32, uint32))&Perl_Mob_WearChange);
package.add("WipeHateList", &Perl_Mob_WipeHateList);
}

View File

@ -3573,7 +3573,7 @@ void QuestManager::removetitle(int titleset) {
initiator->RemoveTitle(titleset);
}
void QuestManager::wearchange(uint8 slot, uint16 texture, uint32 hero_forge_model /*= 0*/, uint32 elite_material /*= 0*/)
void QuestManager::wearchange(uint8 slot, uint32 texture, uint32 hero_forge_model, uint32 elite_material)
{
QuestManagerCurrentQuestVars();

View File

@ -298,7 +298,7 @@ public:
bool IsRunning();
void FlyMode(GravityBehavior flymode);
uint8 FactionValue();
void wearchange(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0);
void wearchange(uint8 slot, uint32 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0);
void voicetell(const char *str, int macronum, int racenum, int gendernum);
void LearnRecipe(uint32 recipe_id);
void SendMail(const char *to, const char *from, const char *subject, const char *message);

View File

@ -2269,8 +2269,8 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client
else
tmpNPCType->special_abilities[0] = '\0';
tmpNPCType->d_melee_texture1 = Strings::ToInt(row[28]);
tmpNPCType->d_melee_texture2 = Strings::ToInt(row[29]);
tmpNPCType->d_melee_texture1 = Strings::ToUnsignedInt(row[28]);
tmpNPCType->d_melee_texture2 = Strings::ToUnsignedInt(row[29]);
tmpNPCType->prim_melee_type = Strings::ToInt(row[30]);
tmpNPCType->sec_melee_type = Strings::ToInt(row[31]);
tmpNPCType->runspeed = Strings::ToFloat(row[32]);

View File

@ -99,8 +99,8 @@ struct NPCType
int charm_atk;
int16 attack_count;
char special_abilities[512];
uint16 d_melee_texture1;
uint16 d_melee_texture2;
uint32 d_melee_texture1;
uint32 d_melee_texture2;
char ammo_idfile[30];
uint8 prim_melee_type;
uint8 sec_melee_type;