(RoF+) Added herosforgemodel field to the npc_types table. Not fully functional yet for NPCs (currently only displays helm correctly).

(RoF2) Updated item links from #npcstat command output.
This commit is contained in:
Trevius 2014-12-24 02:31:37 -06:00
parent f6dc138dc8
commit c48d2d9888
10 changed files with 116 additions and 86 deletions

View File

@ -1,5 +1,9 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) 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: (RoF2) Updated item links from #npcstat command output.
== 12/23/2014 == == 12/23/2014 ==
Uleat: Tidied up some ItemInst* declarations and added some nullptr checks. Uleat: Tidied up some ItemInst* declarations and added some nullptr checks.
Trevius: (RoF+) Added support for Hero's Forge Robe Models. Set herosforgemodel field in items table to exact model such as 11607, 11707, etc. Trevius: (RoF+) Added support for Hero's Forge Robe Models. Set herosforgemodel field in items table to exact model such as 11607, 11707, etc.

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/ */
#define CURRENT_BINARY_DATABASE_VERSION 9063 #define CURRENT_BINARY_DATABASE_VERSION 9064
#define COMPILE_DATE __DATE__ #define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__ #define COMPILE_TIME __TIME__
#ifndef WIN32 #ifndef WIN32

View File

@ -317,6 +317,7 @@
9061|2014_12_13_inventory_table_update.sql|SHOW COLUMNS FROM `inventory` LIKE 'ornament_hero_model'|empty| 9061|2014_12_13_inventory_table_update.sql|SHOW COLUMNS FROM `inventory` LIKE 'ornament_hero_model'|empty|
9062|2014_12_15_multiple_table_updates.sql|SHOW COLUMNS FROM `items` LIKE 'augslot6type'|empty| 9062|2014_12_15_multiple_table_updates.sql|SHOW COLUMNS FROM `items` LIKE 'augslot6type'|empty|
9063|2014_12_24_npc_types_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'd_melee_texture1'|empty| 9063|2014_12_24_npc_types_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'd_melee_texture1'|empty|
9064|2014_12_24_npc_types_table_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'herosforgemodel'|empty|
# Upgrade conditions: # Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not # This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1 @@
ALTER TABLE `npc_types` ADD `herosforgemodel` int( 11 ) NOT NULL DEFAULT '0' AFTER `helmtexture`;

View File

@ -978,7 +978,8 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName));
for (i = 0; i < _MaterialCount; i++) //for (i = 0; i < _MaterialCount; i++)
for (i = 0; i < 9; i++)
{ {
// Only Player Races Wear Armor // Only Player Races Wear Armor
if (Mob::IsPlayerRace(race) || i > 6) if (Mob::IsPlayerRace(race) || i > 6)
@ -2733,7 +2734,6 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
int32 Mob::GetHerosForgeModel(uint8 material_slot) const int32 Mob::GetHerosForgeModel(uint8 material_slot) const
{ {
uint32 HeroModel = 0; uint32 HeroModel = 0;
if (material_slot >= 0 && material_slot < MaterialPrimary) if (material_slot >= 0 && material_slot < MaterialPrimary)
{ {
@ -2744,7 +2744,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const
if (item != 0 && invslot != INVALID_INDEX) if (item != 0 && invslot != INVALID_INDEX)
{ {
if (this->IsClient()) if (IsClient())
{ {
const ItemInst* inst = CastToClient()->m_inv[invslot]; const ItemInst* inst = CastToClient()->m_inv[invslot];
if (inst) if (inst)
@ -2766,6 +2766,16 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const
HeroModel = item->HerosForgeModel; HeroModel = item->HerosForgeModel;
} }
} }
if (IsNPC())
{
HeroModel = CastToNPC()->GetHeroForgeModel();
// Robes require full model number, and should only be sent to chest slot
if (HeroModel > 1000 && material_slot != 1)
{
HeroModel = 0;
}
}
} }
// Auto-Convert Hero Model to match the slot // Auto-Convert Hero Model to match the slot

View File

@ -263,6 +263,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
d_melee_texture1 = d->d_melee_texture1; d_melee_texture1 = d->d_melee_texture1;
d_melee_texture2 = d->d_melee_texture2; d_melee_texture2 = d->d_melee_texture2;
herosforgemodel = d->herosforgemodel;
ammo_idfile = d->ammo_idfile; ammo_idfile = d->ammo_idfile;
memset(equipment, 0, sizeof(equipment)); memset(equipment, 0, sizeof(equipment));
prim_melee_type = d->prim_melee_type; prim_melee_type = d->prim_melee_type;
@ -508,7 +510,11 @@ void NPC::QueryLoot(Client* to) {
for(; cur != end; ++cur) { for(; cur != end; ++cur) {
const Item_Struct* item = database.GetItem((*cur)->item_id); const Item_Struct* item = database.GetItem((*cur)->item_id);
if (item) if (item)
if (to->GetClientVersion() >= EQClientRoF) if (to->GetClientVersion() >= EQClientRoF2)
{
to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X00000000000000000000000000000000000000000000000000%s%c", (*cur)->min_level, (*cur)->max_level, (int)item->ID, 0x12, item->ID, item->Name, 0x12);
}
else if (to->GetClientVersion() >= EQClientRoF)
{ {
to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(*cur)->min_level, (*cur)->max_level, (int) item->ID,0x12, item->ID, item->Name, 0x12); to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(*cur)->min_level, (*cur)->max_level, (int) item->ID,0x12, item->ID, item->Name, 0x12);
} }

View File

@ -403,6 +403,9 @@ public:
void mod_npc_killed(Mob* oos); void mod_npc_killed(Mob* oos);
void AISpellsList(Client *c); void AISpellsList(Client *c);
uint32 GetHeroForgeModel() const { return herosforgemodel; }
void SetHeroForgeModel(uint32 model) { herosforgemodel = model; }
bool IsRaidTarget() const { return raid_target; }; bool IsRaidTarget() const { return raid_target; };
protected: protected:
@ -492,6 +495,8 @@ protected:
uint16 skills[HIGHEST_SKILL+1]; uint16 skills[HIGHEST_SKILL+1];
uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //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; //this is an item Material value uint16 d_melee_texture1; //this is an item Material value
uint16 d_melee_texture2; //this is an item Material value (offhand) uint16 d_melee_texture2; //this is an item Material value (offhand)
const char* ammo_idfile; //this determines projectile graphic "IT###" (see item field 'idfile') const char* ammo_idfile; //this determines projectile graphic "IT###" (see item field 'idfile')

View File

@ -393,6 +393,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
npc_type->gender = monster->gender; npc_type->gender = monster->gender;
npc_type->luclinface = monster->luclinface; npc_type->luclinface = monster->luclinface;
npc_type->helmtexture = monster->helmtexture; npc_type->helmtexture = monster->helmtexture;
npc_type->herosforgemodel = monster->herosforgemodel;
} else } else
LogFile->write(EQEMuLog::Error, "Error loading NPC data for monster summoning pet (NPC ID %d)", monsterid); LogFile->write(EQEMuLog::Error, "Error loading NPC data for monster summoning pet (NPC ID %d)", monsterid);

View File

@ -1740,7 +1740,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) {
// according to spawn2. // according to spawn2.
std::string query = StringFormat("SELECT npc_types.id, npc_types.name, npc_types.level, npc_types.race, " std::string query = StringFormat("SELECT npc_types.id, npc_types.name, npc_types.level, npc_types.race, "
"npc_types.class, npc_types.hp, npc_types.mana, npc_types.gender, " "npc_types.class, npc_types.hp, npc_types.mana, npc_types.gender, "
"npc_types.texture, npc_types.helmtexture, npc_types.size, " "npc_types.texture, npc_types.helmtexture, npc_types.herosforgemodel, npc_types.size, "
"npc_types.loottable_id, npc_types.merchant_id, npc_types.alt_currency_id, " "npc_types.loottable_id, npc_types.merchant_id, npc_types.alt_currency_id, "
"npc_types.adventure_template_id, npc_types.trap_template, npc_types.attack_speed, " "npc_types.adventure_template_id, npc_types.trap_template, npc_types.attack_speed, "
"npc_types.STR, npc_types.STA, npc_types.DEX, npc_types.AGI, npc_types._INT, " "npc_types.STR, npc_types.STA, npc_types.DEX, npc_types.AGI, npc_types._INT, "
@ -1790,82 +1790,83 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) {
tmpNPCType->gender = atoi(row[7]); tmpNPCType->gender = atoi(row[7]);
tmpNPCType->texture = atoi(row[8]); tmpNPCType->texture = atoi(row[8]);
tmpNPCType->helmtexture = atoi(row[9]); tmpNPCType->helmtexture = atoi(row[9]);
tmpNPCType->size = atof(row[10]); tmpNPCType->herosforgemodel = atoi(row[10]);
tmpNPCType->loottable_id = atoi(row[11]); tmpNPCType->size = atof(row[11]);
tmpNPCType->merchanttype = atoi(row[12]); tmpNPCType->loottable_id = atoi(row[12]);
tmpNPCType->alt_currency_type = atoi(row[13]); tmpNPCType->merchanttype = atoi(row[13]);
tmpNPCType->adventure_template = atoi(row[14]); tmpNPCType->alt_currency_type = atoi(row[14]);
tmpNPCType->trap_template = atoi(row[15]); tmpNPCType->adventure_template = atoi(row[15]);
tmpNPCType->attack_speed = atof(row[16]); tmpNPCType->trap_template = atoi(row[16]);
tmpNPCType->STR = atoi(row[17]); tmpNPCType->attack_speed = atof(row[17]);
tmpNPCType->STA = atoi(row[18]); tmpNPCType->STR = atoi(row[18]);
tmpNPCType->DEX = atoi(row[19]); tmpNPCType->STA = atoi(row[19]);
tmpNPCType->AGI = atoi(row[20]); tmpNPCType->DEX = atoi(row[20]);
tmpNPCType->INT = atoi(row[21]); tmpNPCType->AGI = atoi(row[21]);
tmpNPCType->WIS = atoi(row[22]); tmpNPCType->INT = atoi(row[22]);
tmpNPCType->CHA = atoi(row[23]); tmpNPCType->WIS = atoi(row[23]);
tmpNPCType->MR = atoi(row[24]); tmpNPCType->CHA = atoi(row[24]);
tmpNPCType->CR = atoi(row[25]); tmpNPCType->MR = atoi(row[25]);
tmpNPCType->DR = atoi(row[26]); tmpNPCType->CR = atoi(row[26]);
tmpNPCType->FR = atoi(row[27]); tmpNPCType->DR = atoi(row[27]);
tmpNPCType->PR = atoi(row[28]); tmpNPCType->FR = atoi(row[28]);
tmpNPCType->Corrup = atoi(row[29]); tmpNPCType->PR = atoi(row[29]);
tmpNPCType->PhR = atoi(row[30]); tmpNPCType->Corrup = atoi(row[30]);
tmpNPCType->min_dmg = atoi(row[31]); tmpNPCType->PhR = atoi(row[31]);
tmpNPCType->max_dmg = atoi(row[32]); tmpNPCType->min_dmg = atoi(row[32]);
tmpNPCType->attack_count = atoi(row[33]); tmpNPCType->max_dmg = atoi(row[33]);
tmpNPCType->attack_count = atoi(row[34]);
if (row[34] != nullptr) if (row[34] != nullptr)
strn0cpy(tmpNPCType->special_abilities, row[34], 512); strn0cpy(tmpNPCType->special_abilities, row[35], 512);
else else
tmpNPCType->special_abilities[0] = '\0'; tmpNPCType->special_abilities[0] = '\0';
tmpNPCType->npc_spells_id = atoi(row[35]); tmpNPCType->npc_spells_id = atoi(row[36]);
tmpNPCType->npc_spells_effects_id = atoi(row[36]); tmpNPCType->npc_spells_effects_id = atoi(row[37]);
tmpNPCType->d_melee_texture1 = atoi(row[37]); tmpNPCType->d_melee_texture1 = atoi(row[38]);
tmpNPCType->d_melee_texture2 = atoi(row[38]); tmpNPCType->d_melee_texture2 = atoi(row[39]);
strn0cpy(tmpNPCType->ammo_idfile, row[39], 30); strn0cpy(tmpNPCType->ammo_idfile, row[40], 30);
tmpNPCType->prim_melee_type = atoi(row[40]); tmpNPCType->prim_melee_type = atoi(row[41]);
tmpNPCType->sec_melee_type = atoi(row[41]); tmpNPCType->sec_melee_type = atoi(row[42]);
tmpNPCType->ranged_type = atoi(row[42]); tmpNPCType->ranged_type = atoi(row[43]);
tmpNPCType->runspeed= atof(row[43]); tmpNPCType->runspeed= atof(row[44]);
tmpNPCType->findable = atoi(row[44]) == 0? false : true; tmpNPCType->findable = atoi(row[45]) == 0? false : true;
tmpNPCType->trackable = atoi(row[45]) == 0? false : true; tmpNPCType->trackable = atoi(row[46]) == 0? false : true;
tmpNPCType->hp_regen = atoi(row[46]); tmpNPCType->hp_regen = atoi(row[47]);
tmpNPCType->mana_regen = atoi(row[47]); tmpNPCType->mana_regen = atoi(row[48]);
// set defaultvalue for aggroradius // set defaultvalue for aggroradius
tmpNPCType->aggroradius = (int32)atoi(row[48]); tmpNPCType->aggroradius = (int32)atoi(row[49]);
if (tmpNPCType->aggroradius <= 0) if (tmpNPCType->aggroradius <= 0)
tmpNPCType->aggroradius = 70; tmpNPCType->aggroradius = 70;
tmpNPCType->assistradius = (int32)atoi(row[49]); tmpNPCType->assistradius = (int32)atoi(row[50]);
if (tmpNPCType->assistradius <= 0) if (tmpNPCType->assistradius <= 0)
tmpNPCType->assistradius = tmpNPCType->aggroradius; tmpNPCType->assistradius = tmpNPCType->aggroradius;
if (row[50] && strlen(row[50])) if (row[50] && strlen(row[50]))
tmpNPCType->bodytype = (uint8)atoi(row[50]); tmpNPCType->bodytype = (uint8)atoi(row[51]);
else else
tmpNPCType->bodytype = 0; tmpNPCType->bodytype = 0;
tmpNPCType->npc_faction_id = atoi(row[51]); tmpNPCType->npc_faction_id = atoi(row[52]);
tmpNPCType->luclinface = atoi(row[52]); tmpNPCType->luclinface = atoi(row[53]);
tmpNPCType->hairstyle = atoi(row[53]); tmpNPCType->hairstyle = atoi(row[54]);
tmpNPCType->haircolor = atoi(row[54]); tmpNPCType->haircolor = atoi(row[55]);
tmpNPCType->eyecolor1 = atoi(row[55]); tmpNPCType->eyecolor1 = atoi(row[56]);
tmpNPCType->eyecolor2 = atoi(row[56]); tmpNPCType->eyecolor2 = atoi(row[57]);
tmpNPCType->beardcolor = atoi(row[57]); tmpNPCType->beardcolor = atoi(row[58]);
tmpNPCType->beard = atoi(row[58]); tmpNPCType->beard = atoi(row[59]);
tmpNPCType->drakkin_heritage = atoi(row[59]); tmpNPCType->drakkin_heritage = atoi(row[60]);
tmpNPCType->drakkin_tattoo = atoi(row[60]); tmpNPCType->drakkin_tattoo = atoi(row[61]);
tmpNPCType->drakkin_details = atoi(row[61]); tmpNPCType->drakkin_details = atoi(row[62]);
uint32 armor_tint_id = atoi(row[62]); uint32 armor_tint_id = atoi(row[63]);
tmpNPCType->armor_tint[0] = (atoi(row[63]) & 0xFF) << 16; tmpNPCType->armor_tint[0] = (atoi(row[64]) & 0xFF) << 16;
tmpNPCType->armor_tint[0] |= (atoi(row[64]) & 0xFF) << 8; tmpNPCType->armor_tint[0] |= (atoi(row[65]) & 0xFF) << 8;
tmpNPCType->armor_tint[0] |= (atoi(row[65]) & 0xFF); tmpNPCType->armor_tint[0] |= (atoi(row[66]) & 0xFF);
tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0;
if (armor_tint_id == 0) if (armor_tint_id == 0)
@ -1900,32 +1901,32 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) {
} else } else
armor_tint_id = 0; armor_tint_id = 0;
tmpNPCType->see_invis = atoi(row[66]); tmpNPCType->see_invis = atoi(row[67]);
tmpNPCType->see_invis_undead = atoi(row[67]) == 0? false: true; // Set see_invis_undead flag tmpNPCType->see_invis_undead = atoi(row[68]) == 0? false: true; // Set see_invis_undead flag
if (row[68] != nullptr) if (row[68] != nullptr)
strn0cpy(tmpNPCType->lastname, row[68], 32); strn0cpy(tmpNPCType->lastname, row[69], 32);
tmpNPCType->qglobal = atoi(row[69]) == 0? false: true; // qglobal tmpNPCType->qglobal = atoi(row[70]) == 0? false: true; // qglobal
tmpNPCType->AC = atoi(row[70]); tmpNPCType->AC = atoi(row[71]);
tmpNPCType->npc_aggro = atoi(row[71]) == 0? false: true; tmpNPCType->npc_aggro = atoi(row[72]) == 0? false: true;
tmpNPCType->spawn_limit = atoi(row[72]); tmpNPCType->spawn_limit = atoi(row[73]);
tmpNPCType->see_hide = atoi(row[73]) == 0? false: true; tmpNPCType->see_hide = atoi(row[74]) == 0? false: true;
tmpNPCType->see_improved_hide = atoi(row[74]) == 0? false: true; tmpNPCType->see_improved_hide = atoi(row[75]) == 0? false: true;
tmpNPCType->ATK = atoi(row[75]); tmpNPCType->ATK = atoi(row[76]);
tmpNPCType->accuracy_rating = atoi(row[76]); tmpNPCType->accuracy_rating = atoi(row[77]);
tmpNPCType->avoidance_rating = atoi(row[77]); tmpNPCType->avoidance_rating = atoi(row[78]);
tmpNPCType->slow_mitigation = atoi(row[78]); tmpNPCType->slow_mitigation = atoi(row[79]);
tmpNPCType->maxlevel = atoi(row[79]); tmpNPCType->maxlevel = atoi(row[80]);
tmpNPCType->scalerate = atoi(row[80]); tmpNPCType->scalerate = atoi(row[81]);
tmpNPCType->private_corpse = atoi(row[81]) == 1 ? true: false; tmpNPCType->private_corpse = atoi(row[82]) == 1 ? true: false;
tmpNPCType->unique_spawn_by_name = atoi(row[82]) == 1 ? true: false; tmpNPCType->unique_spawn_by_name = atoi(row[83]) == 1 ? true: false;
tmpNPCType->underwater = atoi(row[83]) == 1 ? true: false; tmpNPCType->underwater = atoi(row[84]) == 1 ? true: false;
tmpNPCType->emoteid = atoi(row[84]); tmpNPCType->emoteid = atoi(row[85]);
tmpNPCType->spellscale = atoi(row[85]); tmpNPCType->spellscale = atoi(row[86]);
tmpNPCType->healscale = atoi(row[86]); tmpNPCType->healscale = atoi(row[87]);
tmpNPCType->no_target_hotkey = atoi(row[87]) == 1 ? true: false; tmpNPCType->no_target_hotkey = atoi(row[88]) == 1 ? true: false;
tmpNPCType->raid_target = atoi(row[88]) == 0 ? false: true; tmpNPCType->raid_target = atoi(row[89]) == 0 ? false: true;
tmpNPCType->attack_delay = atoi(row[89]); tmpNPCType->attack_delay = atoi(row[90]);
// If NPC with duplicate NPC id already in table, // If NPC with duplicate NPC id already in table,
// free item we attempted to add. // free item we attempted to add.

View File

@ -49,6 +49,7 @@ struct NPCType
uint32 npc_id; uint32 npc_id;
uint8 texture; uint8 texture;
uint8 helmtexture; uint8 helmtexture;
uint32 herosforgemodel;
uint32 loottable_id; uint32 loottable_id;
uint32 npc_spells_id; uint32 npc_spells_id;
uint32 npc_spells_effects_id; uint32 npc_spells_effects_id;