Changes to how valid light sources are critiqued

This commit is contained in:
Uleat 2015-02-26 18:46:12 -05:00
parent e47f9d95b0
commit 1f0b86a0d5
20 changed files with 357 additions and 159 deletions

View File

@ -1,5 +1,8 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 02/26/2015 ==
Uleat: Updated light source criteria to (hopefully) match what the client uses (still needs tweaking)
== 02/23/2015 == == 02/23/2015 ==
Uleat: Fix for RoF+ clients showing active 'Return Home' button when action is not available (swapped 'GoHome' and 'Enabled' fields in RoF-era CharacterSelectEntry structs) Uleat: Fix for RoF+ clients showing active 'Return Home' button when action is not available (swapped 'GoHome' and 'Enabled' fields in RoF-era CharacterSelectEntry structs)

View File

@ -21,6 +21,53 @@
#include "skills.h" #include "skills.h"
#include "types.h" #include "types.h"
/*
** Light Types
**
*/
enum LightTypes
{
lightTypeNone = 0,
lightTypeCandle,
lightTypeTorch,
lightTypeTinyGlowingSkull,
lightTypeSmallLantern,
lightTypeSteinOfMoggok,
lightTypeLargeLantern,
lightTypeFlamelessLantern,
lightTypeGlobeOfStars,
lightTypeLightGlobe,
lightTypeLightstone,
lightTypeGreaterLightstone,
lightTypeFireBeetleEye,
lightTypeColdlight,
lightTypeUnknown1,
lightTypeUnknown2
};
#define LIGHT_TYPES_COUNT 16
/*
** Light Levels
**
*/
enum LightLevels
{
lightLevelUnlit = 0,
lightLevelCandle,
lightLevelTorch,
lightLevelSmallMagic,
lightLevelRedLight,
lightLevelBlueLight,
lightLevelSmallLantern,
lightLevelMagicLantern,
lightLevelLargeLantern,
lightLevelLargeMagic,
lightLevelBrilliant
};
#define LIGHT_LEVELS_COUNT 11
/* /*
** Item attributes ** Item attributes
** **

View File

@ -993,34 +993,46 @@ int Inventory::GetSlotByItemInst(ItemInst *inst) {
return INVALID_INDEX; return INVALID_INDEX;
} }
uint8 Inventory::FindHighestLightValue() uint8 Inventory::FindBrightestLightType()
{ {
uint8 light_value = NOT_USED; uint8 brightest_light_type = 0;
// NOTE: The client does not recognize augment light sources, applied or otherwise, and should not be parsed
for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) {
if ((iter->first < EmuConstants::EQUIPMENT_BEGIN || iter->first > EmuConstants::EQUIPMENT_END) && iter->first != MainPowerSource) { continue; } if ((iter->first < EmuConstants::EQUIPMENT_BEGIN || iter->first > EmuConstants::EQUIPMENT_END) && iter->first != MainPowerSource) { continue; }
if (iter->first == MainAmmo) { continue; }
auto inst = iter->second; auto inst = iter->second;
if (inst == nullptr) { continue; } if (inst == nullptr) { continue; }
auto item = inst->GetItem(); auto item = inst->GetItem();
if (item == nullptr) { continue; } if (item == nullptr) { continue; }
if (item->Light & 0xF0) { continue; }
if (item->Light > light_value) { light_value = item->Light; } if (LightProfile_Struct::IsLevelGreater(item->Light, brightest_light_type))
brightest_light_type = item->Light;
} }
for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) {
if (iter->first < EmuConstants::GENERAL_BEGIN || iter->first > EmuConstants::GENERAL_END) { continue; } if (iter->first < EmuConstants::GENERAL_BEGIN || iter->first > EmuConstants::GENERAL_END) { continue; }
auto inst = iter->second; auto inst = iter->second;
if (inst == nullptr) { continue; } if (inst == nullptr) { continue; }
auto item = inst->GetItem(); auto item = inst->GetItem();
if (item == nullptr) { continue; } if (item == nullptr) { continue; }
// 'Gloomingdeep lantern' is ItemTypeArmor in the database..there may be others instances and/or types that need to be handled
if (item->ItemType != ItemTypeMisc && item->ItemType != ItemTypeLight && item->ItemType != ItemTypeArmor) { continue; } switch (item->Light) {
if (item->Light & 0xF0) { continue; } case lightTypeCandle:
if (item->Light > light_value) { light_value = item->Light; } case lightTypeTorch:
case lightTypeSmallLantern:
case lightTypeLargeLantern:
continue;
default:
break;
}
if (LightProfile_Struct::IsLevelGreater(item->Light, brightest_light_type))
brightest_light_type = item->Light;
} }
return light_value; return brightest_light_type;
} }
void Inventory::dumpEntireInventory() { void Inventory::dumpEntireInventory() {
@ -2361,3 +2373,66 @@ bool Item_Struct::IsEquipable(uint16 Race, uint16 Class_) const
return (IsRace && IsClass); return (IsRace && IsClass);
} }
//
// struct LightProfile_Struct
//
uint8 LightProfile_Struct::TypeToLevel(uint8 lightType)
{
switch (lightType) {
case lightTypeGlobeOfStars:
return lightLevelBrilliant; // 10
case lightTypeFlamelessLantern:
case lightTypeGreaterLightstone:
return lightLevelLargeMagic; // 9
case lightTypeLargeLantern:
return lightLevelLargeLantern; // 8
case lightTypeSteinOfMoggok:
case lightTypeLightstone:
return lightLevelMagicLantern; // 7
case lightTypeSmallLantern:
return lightLevelSmallLantern; // 6
case lightTypeColdlight:
case lightTypeUnknown2:
return lightLevelBlueLight; // 5
case lightTypeFireBeetleEye:
case lightTypeUnknown1:
return lightLevelRedLight; // 4
case lightTypeTinyGlowingSkull:
case lightTypeLightGlobe:
return lightLevelSmallMagic; // 3
case lightTypeTorch:
return lightLevelTorch; // 2
case lightLevelCandle:
return lightLevelCandle; // 1
default:
return lightLevelUnlit; // 0
}
}
bool LightProfile_Struct::IsLevelGreater(uint8 leftType, uint8 rightType)
{
static const uint8 light_levels[LIGHT_TYPES_COUNT] = {
lightLevelUnlit, /* lightTypeNone */
lightLevelCandle, /* lightTypeCandle */
lightLevelTorch, /* lightTypeTorch */
lightLevelSmallMagic, /* lightTypeTinyGlowingSkull */
lightLevelSmallLantern, /* lightTypeSmallLantern */
lightLevelMagicLantern, /* lightTypeSteinOfMoggok */
lightLevelLargeLantern, /* lightTypeLargeLantern */
lightLevelLargeMagic, /* lightTypeFlamelessLantern */
lightLevelBrilliant, /* lightTypeGlobeOfStars */
lightLevelSmallMagic, /* lightTypeLightGlobe */
lightLevelMagicLantern, /* lightTypeLightstone */
lightLevelLargeMagic, /* lightTypeGreaterLightstone */
lightLevelRedLight, /* lightTypeFireBeetleEye */
lightLevelBlueLight, /* lightTypeColdlight */
lightLevelRedLight, /* lightTypeUnknown1 */
lightLevelBlueLight /* lightTypeUnknown2 */
};
if (leftType >= LIGHT_TYPES_COUNT) { leftType = lightTypeNone; }
if (rightType >= LIGHT_TYPES_COUNT) { rightType = lightTypeNone; }
return (light_levels[leftType] > light_levels[rightType]);
}

View File

@ -204,7 +204,7 @@ public:
int GetSlotByItemInst(ItemInst *inst); int GetSlotByItemInst(ItemInst *inst);
uint8 FindHighestLightValue(); uint8 FindBrightestLightType();
void dumpEntireInventory(); void dumpEntireInventory();
void dumpWornItems(); void dumpWornItems();
@ -472,4 +472,40 @@ public:
~EvolveInfo(); ~EvolveInfo();
}; };
struct LightProfile_Struct
{
/*
Current criteria (light types):
Equipment: { 0 .. 15 }
General: { 0 .. 15 } =/= { 1, 2, 4, 6 }
Notes:
- MainAmmo is not considered when determining light sources
- No 'Sub' or 'Aug' items are recognized as light sources
- Extinguishable light types { Candle, Torch, SmallLantern, LargeLantern } are not considered for general (carried) light sources
- Client calls '__debugbreak' for type values > 127
- If values > 0x0F are valid, then assignment limiters will need to be removed
- MainCursor 'appears' to be a valid light source update slot..but, have not experienced updates during debug sessions
*/
static uint8 TypeToLevel(uint8 lightType);
static bool IsLevelGreater(uint8 leftType, uint8 rightType);
// Light types (classifications)
struct {
uint8 Innate; // Defined by db field `npc_types`.`light` - where appropriate
uint8 Equipment; // Item_Struct::light value of worn/carried equipment
uint8 Spell; // Set value of any light-producing spell (can be modded to mimic equip_light behavior)
uint8 Active; // Highest value of all light sources
} Type;
// Light levels (intensities) - used to determine which light source should be active
struct {
uint8 Innate;
uint8 Equipment;
uint8 Spell;
uint8 Active;
} Level;
};
#endif // #define __ITEM_H #endif // #define __ITEM_H

View File

@ -97,7 +97,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm
strcpy(this->name, this->GetCleanName()); strcpy(this->name, this->GetCleanName());
active_light = spell_light = equip_light = innate_light = NOT_USED; memset(&m_Light, 0, sizeof(LightProfile_Struct));
} }
// This constructor is used when the bot is loaded out of the database // This constructor is used when the bot is loaded out of the database
@ -213,8 +213,6 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
if(cur_mana > max_mana) if(cur_mana > max_mana)
cur_mana = max_mana; cur_mana = max_mana;
cur_end = max_end; cur_end = max_end;
active_light = spell_light = equip_light = innate_light = NOT_USED;
} }
Bot::~Bot() { Bot::~Bot() {
@ -4121,8 +4119,8 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) {
// Level the bot to the same level as the bot owner // Level the bot to the same level as the bot owner
//this->SetLevel(botCharacterOwner->GetLevel()); //this->SetLevel(botCharacterOwner->GetLevel());
UpdateEquipLightValue(); UpdateEquipmentLight();
UpdateActiveLightValue(); UpdateActiveLight();
entity_list.AddBot(this, true, true); entity_list.AddBot(this, true, true);
@ -4187,7 +4185,7 @@ void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) {
*errorMessage = std::string(results.ErrorMessage()); *errorMessage = std::string(results.ErrorMessage());
m_inv.DeleteItem(slotID); m_inv.DeleteItem(slotID);
UpdateEquipLightValue(); UpdateEquipmentLight();
} }
// Retrieves all the inventory records from the database for this bot. // Retrieves all the inventory records from the database for this bot.
@ -4249,7 +4247,7 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) {
} }
UpdateEquipLightValue(); UpdateEquipmentLight();
} }
// Returns the inventory record for this bot from the database for the specified equipment slot. // Returns the inventory record for this bot from the database for the specified equipment slot.
@ -4375,8 +4373,8 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.size = 0; ns->spawn.size = 0;
ns->spawn.NPC = 0; // 0=player,1=npc,2=pc corpse,3=npc corpse ns->spawn.NPC = 0; // 0=player,1=npc,2=pc corpse,3=npc corpse
UpdateActiveLightValue(); UpdateActiveLight();
ns->spawn.light = active_light; ns->spawn.light = m_Light.Type.Active;
ns->spawn.helm = helmtexture; //0xFF; ns->spawn.helm = helmtexture; //0xFF;
ns->spawn.equip_chest2 = texture; //0xFF; ns->spawn.equip_chest2 = texture; //0xFF;
@ -5088,9 +5086,9 @@ void Bot::BotAddEquipItem(int slot, uint32 id) {
SendWearChange(materialFromSlot); SendWearChange(materialFromSlot);
} }
UpdateEquipLightValue(); UpdateEquipmentLight();
if (UpdateActiveLightValue()) if (UpdateActiveLight())
SendAppearancePacket(AT_Light, GetActiveLightValue()); SendAppearancePacket(AT_Light, GetActiveLightType());
} }
} }
@ -5106,9 +5104,9 @@ void Bot::BotRemoveEquipItem(int slot) {
SendWearChange(MaterialArms); SendWearChange(MaterialArms);
} }
UpdateEquipLightValue(); UpdateEquipmentLight();
if (UpdateActiveLightValue()) if (UpdateActiveLight())
SendAppearancePacket(AT_Light, GetActiveLightValue()); SendAppearancePacket(AT_Light, GetActiveLightType());
} }
} }
@ -8407,7 +8405,7 @@ void Bot::EquipBot(std::string* errorMessage) {
} }
} }
UpdateEquipLightValue(); UpdateEquipmentLight();
} }
//// This method is meant to be called by zone or client methods to clean up objects when a client camps, goes LD, zones out or something like that. //// This method is meant to be called by zone or client methods to clean up objects when a client camps, goes LD, zones out or something like that.

View File

@ -332,7 +332,7 @@ public:
void EquipBot(std::string* errorMessage); void EquipBot(std::string* errorMessage);
bool CheckLoreConflict(const Item_Struct* item); bool CheckLoreConflict(const Item_Struct* item);
uint32 GetEquipmentColor(uint8 material_slot) const; uint32 GetEquipmentColor(uint8 material_slot) const;
virtual void UpdateEquipLightValue() { equip_light = m_inv.FindHighestLightValue(); } virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); }
// Static Class Methods // Static Class Methods
static void SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* errorMessage); static void SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* errorMessage);

View File

@ -308,9 +308,6 @@ Client::Client(EQStreamInterface* ieqs)
interrogateinv_flag = false; interrogateinv_flag = false;
active_light = innate_light;
spell_light = equip_light = NOT_USED;
AI_Init(); AI_Init();
} }
@ -1869,9 +1866,9 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
ns->spawn.runspeed = (gmspeed == 0) ? runspeed : 3.125f; ns->spawn.runspeed = (gmspeed == 0) ? runspeed : 3.125f;
ns->spawn.showhelm = m_pp.showhelm ? 1 : 0; ns->spawn.showhelm = m_pp.showhelm ? 1 : 0;
UpdateEquipLightValue(); UpdateEquipmentLight();
UpdateActiveLightValue(); UpdateActiveLight();
ns->spawn.light = active_light; ns->spawn.light = m_Light.Type.Active;
} }
bool Client::GMHideMe(Client* client) { bool Client::GMHideMe(Client* client) {

View File

@ -731,7 +731,7 @@ public:
#endif #endif
uint32 GetEquipment(uint8 material_slot) const; // returns item id uint32 GetEquipment(uint8 material_slot) const; // returns item id
uint32 GetEquipmentColor(uint8 material_slot) const; uint32 GetEquipmentColor(uint8 material_slot) const;
virtual void UpdateEquipLightValue() { equip_light = m_inv.FindHighestLightValue(); } virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); }
inline bool AutoSplitEnabled() { return m_pp.autosplit != 0; } inline bool AutoSplitEnabled() { return m_pp.autosplit != 0; }

View File

@ -725,8 +725,8 @@ void Client::CompleteConnect()
SendWearChange(x); SendWearChange(x);
} }
// added due to wear change above // added due to wear change above
UpdateActiveLightValue(); UpdateActiveLight();
SendAppearancePacket(AT_Light, GetActiveLightValue()); SendAppearancePacket(AT_Light, GetActiveLightType());
Mob *pet = GetPet(); Mob *pet = GetPet();
if (pet != nullptr) { if (pet != nullptr) {
@ -734,8 +734,8 @@ void Client::CompleteConnect()
pet->SendWearChange(x); pet->SendWearChange(x);
} }
// added due to wear change above // added due to wear change above
pet->UpdateActiveLightValue(); pet->UpdateActiveLight();
pet->SendAppearancePacket(AT_Light, pet->GetActiveLightValue()); pet->SendAppearancePacket(AT_Light, pet->GetActiveLightType());
} }
entity_list.SendTraders(this); entity_list.SendTraders(this);

View File

@ -262,9 +262,10 @@ bool Client::Process() {
} }
if(light_update_timer.Check()) { if(light_update_timer.Check()) {
UpdateEquipLightValue();
if(UpdateActiveLightValue()) { UpdateEquipmentLight();
SendAppearancePacket(AT_Light, GetActiveLightValue()); if(UpdateActiveLight()) {
SendAppearancePacket(AT_Light, GetActiveLightType());
} }
} }

View File

@ -137,9 +137,9 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std:
pc->IsRezzed(rezzed); pc->IsRezzed(rezzed);
pc->become_npc = false; pc->become_npc = false;
pc->spell_light = pc->innate_light = NOT_USED; pc->m_Light.Level.Innate = pc->m_Light.Type.Innate = 0;
pc->UpdateEquipLightValue(); pc->UpdateEquipmentLight(); // itemlist populated above..need to determine actual values
//pc->UpdateActiveLightValue(); pc->m_Light.Level.Spell = pc->m_Light.Type.Spell = 0;
safe_delete_array(pcs); safe_delete_array(pcs);
@ -150,7 +150,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
// vesuvias - appearence fix // vesuvias - appearence fix
: Mob("Unnamed_Corpse","",0,0,in_npc->GetGender(),in_npc->GetRace(),in_npc->GetClass(),BT_Humanoid,//bodytype added : Mob("Unnamed_Corpse","",0,0,in_npc->GetGender(),in_npc->GetRace(),in_npc->GetClass(),BT_Humanoid,//bodytype added
in_npc->GetDeity(),in_npc->GetLevel(),in_npc->GetNPCTypeID(),in_npc->GetSize(),0, in_npc->GetDeity(),in_npc->GetLevel(),in_npc->GetNPCTypeID(),in_npc->GetSize(),0,
in_npc->GetPosition(), in_npc->GetInnateLightValue(), in_npc->GetTexture(),in_npc->GetHelmTexture(), in_npc->GetPosition(), in_npc->GetInnateLightType(), in_npc->GetTexture(),in_npc->GetHelmTexture(),
0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0), 0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0),
corpse_decay_timer(in_decaytime), corpse_decay_timer(in_decaytime),
@ -202,9 +202,8 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
} }
this->rez_experience = 0; this->rez_experience = 0;
UpdateEquipLightValue(); UpdateEquipmentLight();
spell_light = NOT_USED; UpdateActiveLight();
UpdateActiveLightValue();
} }
Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
@ -222,7 +221,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
client->GetSize(), // float in_size, client->GetSize(), // float in_size,
0, // float in_runspeed, 0, // float in_runspeed,
client->GetPosition(), client->GetPosition(),
0, // uint8 in_light, - verified for client innate_light value client->GetInnateLightType(), // uint8 in_light, - verified for client innate_light value
client->GetTexture(), // uint8 in_texture, client->GetTexture(), // uint8 in_texture,
client->GetHelmTexture(), // uint8 in_helmtexture, client->GetHelmTexture(), // uint8 in_helmtexture,
0, // uint16 in_ac, 0, // uint16 in_ac,
@ -373,16 +372,14 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
database.TransactionCommit(); database.TransactionCommit();
UpdateEquipLightValue(); UpdateEquipmentLight();
spell_light = NOT_USED; UpdateActiveLight();
UpdateActiveLightValue();
return; return;
} //end "not leaving naked corpses" } //end "not leaving naked corpses"
UpdateEquipLightValue(); UpdateEquipmentLight();
spell_light = NOT_USED; UpdateActiveLight();
UpdateActiveLightValue();
IsRezzed(false); IsRezzed(false);
Save(); Save();
@ -521,9 +518,9 @@ in_helmtexture,
} }
SetPlayerKillItemID(0); SetPlayerKillItemID(0);
UpdateEquipLightValue(); UpdateEquipmentLight();
spell_light = NOT_USED; m_Light.Level.Spell = m_Light.Type.Spell = 0;
UpdateActiveLightValue(); UpdateActiveLight();
} }
Corpse::~Corpse() { Corpse::~Corpse() {
@ -667,7 +664,7 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui
item->attuned=attuned; item->attuned=attuned;
itemlist.push_back(item); itemlist.push_back(item);
UpdateEquipLightValue(); UpdateEquipmentLight();
} }
ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data) { ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data) {
@ -742,9 +739,9 @@ void Corpse::RemoveItem(ServerLootItem_Struct* item_data)
if (material != _MaterialInvalid) if (material != _MaterialInvalid)
SendWearChange(material); SendWearChange(material);
UpdateEquipLightValue(); UpdateEquipmentLight();
if (UpdateActiveLightValue()) if (UpdateActiveLight())
SendAppearancePacket(AT_Light, GetActiveLightValue()); SendAppearancePacket(AT_Light, GetActiveLightType());
safe_delete(sitem); safe_delete(sitem);
return; return;
@ -1273,8 +1270,8 @@ void Corpse::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.max_hp = 120; ns->spawn.max_hp = 120;
ns->spawn.NPC = 2; ns->spawn.NPC = 2;
UpdateActiveLightValue(); UpdateActiveLight();
ns->spawn.light = active_light; ns->spawn.light = m_Light.Type.Active;
} }
void Corpse::QueryLoot(Client* to) { void Corpse::QueryLoot(Client* to) {
@ -1421,17 +1418,44 @@ uint32 Corpse::GetEquipmentColor(uint8 material_slot) const {
return 0; return 0;
} }
void Corpse::UpdateEquipLightValue() void Corpse::UpdateEquipmentLight()
{ {
equip_light = NOT_USED; m_Light.Type.Equipment = 0;
m_Light.Level.Equipment = 0;
for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) {
if (((*iter)->equip_slot < EmuConstants::EQUIPMENT_BEGIN || (*iter)->equip_slot > EmuConstants::GENERAL_END) && (*iter)->equip_slot != MainPowerSource) { continue; } if (((*iter)->equip_slot < EmuConstants::EQUIPMENT_BEGIN || (*iter)->equip_slot > EmuConstants::EQUIPMENT_END) && (*iter)->equip_slot != MainPowerSource) { continue; }
if ((*iter)->equip_slot == MainAmmo) { continue; }
auto item = database.GetItem((*iter)->item_id); auto item = database.GetItem((*iter)->item_id);
if (item == nullptr) { continue; } if (item == nullptr) { continue; }
if (item->ItemType != ItemTypeMisc && item->ItemType != ItemTypeLight) { continue; }
if (item->Light & 0xF0) { continue; } if (m_Light.IsLevelGreater(item->Light, m_Light.Type.Equipment)) {
if (item->Light > equip_light) { equip_light = item->Light; } m_Light.Type.Equipment = item->Light;
m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment);
}
}
for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) {
if ((*iter)->equip_slot < EmuConstants::GENERAL_BEGIN || (*iter)->equip_slot > EmuConstants::GENERAL_END) { continue; }
auto item = database.GetItem((*iter)->item_id);
if (item == nullptr) { continue; }
switch (item->Light) {
case lightTypeCandle:
case lightTypeTorch:
case lightTypeSmallLantern:
case lightTypeLargeLantern:
continue;
default:
break;
}
if (m_Light.IsLevelGreater(item->Light, m_Light.Type.Equipment)) {
m_Light.Type.Equipment = item->Light;
m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment);
}
} }
} }

View File

@ -125,7 +125,7 @@ class Corpse : public Mob {
uint32 GetEquipmentColor(uint8 material_slot) const; uint32 GetEquipmentColor(uint8 material_slot) const;
inline int GetRezExp() { return rez_experience; } inline int GetRezExp() { return rez_experience; }
virtual void UpdateEquipLightValue(); virtual void UpdateEquipmentLight();
protected: protected:
void MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, std::list<uint32> &removedList); void MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, std::list<uint32> &removedList);

View File

@ -184,7 +184,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
} }
} // We either ran out of items or reached our limit. } // We either ran out of items or reached our limit.
npc->UpdateEquipLightValue(); npc->UpdateEquipmentLight();
// no wearchange associated with this function..so, this should not be needed // no wearchange associated with this function..so, this should not be needed
//if (npc->UpdateActiveLightValue()) //if (npc->UpdateActiveLightValue())
// npc->SendAppearancePacket(AT_Light, npc->GetActiveLightValue()); // npc->SendAppearancePacket(AT_Light, npc->GetActiveLightValue());
@ -375,9 +375,9 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
safe_delete(outapp); safe_delete(outapp);
} }
UpdateEquipLightValue(); UpdateEquipmentLight();
if (UpdateActiveLightValue()) if (UpdateActiveLight())
SendAppearancePacket(AT_Light, GetActiveLightValue()); SendAppearancePacket(AT_Light, GetActiveLightType());
} }
void NPC::AddItem(const Item_Struct* item, uint16 charges, bool equipitem) { void NPC::AddItem(const Item_Struct* item, uint16 charges, bool equipitem) {

View File

@ -1201,8 +1201,8 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.NPC = 1; // 0=player,1=npc,2=pc corpse,3=npc corpse ns->spawn.NPC = 1; // 0=player,1=npc,2=pc corpse,3=npc corpse
ns->spawn.IsMercenary = 1; ns->spawn.IsMercenary = 1;
UpdateActiveLightValue(); UpdateActiveLight();
ns->spawn.light = active_light; ns->spawn.light = m_Light.Type.Active;
/* /*
// Wear Slots are not setup for Mercs yet // Wear Slots are not setup for Mercs yet
@ -5028,34 +5028,51 @@ void Merc::UpdateMercAppearance() {
} }
} }
if (UpdateActiveLightValue()) if (UpdateActiveLight())
SendAppearancePacket(AT_Light, GetActiveLightValue()); SendAppearancePacket(AT_Light, GetActiveLightType());
} }
void Merc::UpdateEquipLightValue() void Merc::UpdateEquipmentLight()
{ {
equip_light = NOT_USED; m_Light.Type.Equipment = 0;
m_Light.Level.Equipment = 0;
for (int index = MAIN_BEGIN; index < EmuConstants::EQUIPMENT_SIZE; ++index) { for (int index = MAIN_BEGIN; index < EmuConstants::EQUIPMENT_SIZE; ++index) {
if (equipment[index] == NOT_USED) { continue; } if (index == MainAmmo) { continue; }
auto item = database.GetItem(equipment[index]); auto item = database.GetItem(equipment[index]);
if (item == nullptr) { continue; } if (item == nullptr) { continue; }
if (item->Light & 0xF0) { continue; }
if (item->Light > equip_light) { equip_light = item->Light; } if (m_Light.IsLevelGreater(item->Light, m_Light.Type.Equipment)) {
m_Light.Type.Equipment = item->Light;
m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment);
}
} }
for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) {
auto item = database.GetItem((*iter)->item_id); auto item = database.GetItem((*iter)->item_id);
if (item == nullptr) { continue; } if (item == nullptr) { continue; }
if (item->ItemType != ItemTypeMisc && item->ItemType != ItemTypeLight) { continue; }
if (item->Light & 0xF0) { continue; } switch (item->Light) {
if (item->Light > equip_light) { equip_light = item->Light; } case lightTypeCandle:
case lightTypeTorch:
case lightTypeSmallLantern:
case lightTypeLargeLantern:
continue;
default:
break;
}
if (m_Light.IsLevelGreater(item->Light, m_Light.Type.Equipment)) {
m_Light.Type.Equipment = item->Light;
m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment);
}
} }
} }
void Merc::AddItem(uint8 slot, uint32 item_id) { void Merc::AddItem(uint8 slot, uint32 item_id) {
equipment[slot] = item_id; equipment[slot] = item_id;
UpdateEquipLightValue(); UpdateEquipmentLight();
} }
bool Merc::Spawn(Client *owner) { bool Merc::Spawn(Client *owner) {

View File

@ -139,7 +139,7 @@ public:
void UpdateMercInfo(Client *c); void UpdateMercInfo(Client *c);
void UpdateMercStats(Client *c, bool setmax = false); void UpdateMercStats(Client *c, bool setmax = false);
void UpdateMercAppearance(); void UpdateMercAppearance();
virtual void UpdateEquipLightValue(); virtual void UpdateEquipmentLight();
void AddItem(uint8 slot, uint32 item_id); void AddItem(uint8 slot, uint32 item_id);
static const char *GetRandomName(); static const char *GetRandomName();
bool Spawn(Client *owner); bool Spawn(Client *owner);

View File

@ -149,9 +149,13 @@ Mob::Mob(const char* in_name,
if (runspeed < 0 || runspeed > 20) if (runspeed < 0 || runspeed > 20)
runspeed = 1.25f; runspeed = 1.25f;
active_light = innate_light = in_light; m_Light.Type.Innate = in_light;
spell_light = equip_light = NOT_USED; m_Light.Level.Innate = m_Light.TypeToLevel(m_Light.Type.Innate);
m_Light.Level.Equipment = m_Light.Type.Equipment = 0;
m_Light.Level.Spell = m_Light.Type.Spell = 0;
m_Light.Type.Active = m_Light.Type.Innate;
m_Light.Level.Active = m_Light.Level.Innate;
texture = in_texture; texture = in_texture;
helmtexture = in_helmtexture; helmtexture = in_helmtexture;
haircolor = in_haircolor; haircolor = in_haircolor;
@ -903,8 +907,8 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
ns->spawn.animation = 0; ns->spawn.animation = 0;
ns->spawn.findable = findable?1:0; ns->spawn.findable = findable?1:0;
UpdateActiveLightValue(); UpdateActiveLight();
ns->spawn.light = active_light; ns->spawn.light = m_Light.Type.Active;
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0; ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0;
@ -2032,37 +2036,20 @@ void Mob::SetAppearance(EmuAppearance app, bool iIgnoreSelf) {
} }
} }
bool Mob::UpdateActiveLightValue() bool Mob::UpdateActiveLight()
{ {
/* This is old information... uint8 old_light_level = m_Light.Level.Active;
0 - "None"
1 - "Candle"
2 - "Torch"
3 - "Tiny Glowing Skull"
4 - "Small Lantern"
5 - "Stein of Moggok"
6 - "Large Lantern"
7 - "Flameless Lantern"
8 - "Globe of Stars"
9 - "Light Globe"
10 - "Lightstone"
11 - "Greater Lightstone"
12 - "Fire Beatle Eye"
13 - "Coldlight"
14 - "Unknown"
15 - "Unknown"
*/
uint8 old_light = (active_light & 0x0F);
active_light = (innate_light & 0x0F);
if (equip_light > active_light) { active_light = equip_light; } // limiter in property handler m_Light.Type.Active = 0;
if (spell_light > active_light) { active_light = spell_light; } // limiter in property handler m_Light.Level.Active = 0;
if (active_light != old_light) if (m_Light.IsLevelGreater((m_Light.Type.Innate & 0x0F), m_Light.Type.Active)) { m_Light.Type.Active = m_Light.Type.Innate; }
return true; if (m_Light.Level.Equipment > m_Light.Level.Active) { m_Light.Type.Active = m_Light.Type.Equipment; } // limiter in property handler
if (m_Light.Level.Spell > m_Light.Level.Active) { m_Light.Type.Active = m_Light.Type.Spell; } // limiter in property handler
return false; m_Light.Level.Active = m_Light.TypeToLevel(m_Light.Type.Active);
return (m_Light.Level.Active != old_light_level);
} }
void Mob::ChangeSize(float in_size = 0, bool bNoRestriction) { void Mob::ChangeSize(float in_size = 0, bool bNoRestriction) {
@ -5387,4 +5374,3 @@ bool Mob::CanClassEquipItem(uint32 item_id)
else else
return true; return true;
} }

View File

@ -655,14 +655,17 @@ public:
bool IsDestructibleObject() { return destructibleobject; } bool IsDestructibleObject() { return destructibleobject; }
void SetDestructibleObject(bool in) { destructibleobject = in; } void SetDestructibleObject(bool in) { destructibleobject = in; }
inline uint8 GetInnateLightValue() { return innate_light; } inline uint8 GetInnateLightType() { return m_Light.Type.Innate; }
inline uint8 GetEquipLightValue() { return equip_light; } inline uint8 GetEquipmentLightType() { return m_Light.Type.Equipment; }
inline uint8 GetSpellLightValue() { return spell_light; } inline uint8 GetSpellLightType() { return m_Light.Type.Spell; }
virtual void UpdateEquipLightValue() { equip_light = NOT_USED; }
inline void SetSpellLightValue(uint8 light_value) { spell_light = (light_value & 0x0F); }
inline uint8 GetActiveLightValue() { return active_light; } virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = 0; m_Light.Level.Equipment = 0; }
bool UpdateActiveLightValue(); // returns true if change, false if no change inline void SetSpellLightType(uint8 lightType) { m_Light.Type.Spell = (lightType & 0x0F); m_Light.Level.Spell = m_Light.TypeToLevel(m_Light.Type.Spell); }
inline uint8 GetActiveLightType() { return m_Light.Type.Active; }
bool UpdateActiveLight(); // returns true if change, false if no change
LightProfile_Struct* GetLightProfile() { return &m_Light; }
Mob* GetPet(); Mob* GetPet();
void SetPet(Mob* newpet); void SetPet(Mob* newpet);
@ -1074,10 +1077,7 @@ protected:
glm::vec4 m_Delta; glm::vec4 m_Delta;
uint8 innate_light; // defined by db field `npc_types`.`light` - where appropriate LightProfile_Struct m_Light;
uint8 equip_light; // highest value of equipped/carried light-producing items
uint8 spell_light; // set value of any light-producing spell (can be modded to mimic equip_light behavior)
uint8 active_light; // highest value of all light sources
float fixedZ; float fixedZ;
EmuAppearance _appearance; EmuAppearance _appearance;

View File

@ -352,9 +352,6 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if
InitializeBuffSlots(); InitializeBuffSlots();
CalcBonuses(); CalcBonuses();
raid_target = d->raid_target; raid_target = d->raid_target;
active_light = d->light;
spell_light = equip_light = NOT_USED;
} }
NPC::~NPC() NPC::~NPC()
@ -439,15 +436,15 @@ void NPC::RemoveItem(uint32 item_id, uint16 quantity, uint16 slot) {
ServerLootItem_Struct* item = *cur; ServerLootItem_Struct* item = *cur;
if (item->item_id == item_id && slot <= 0 && quantity <= 0) { if (item->item_id == item_id && slot <= 0 && quantity <= 0) {
itemlist.erase(cur); itemlist.erase(cur);
UpdateEquipLightValue(); UpdateEquipmentLight();
if (UpdateActiveLightValue()) { SendAppearancePacket(AT_Light, GetActiveLightValue()); } if (UpdateActiveLight()) { SendAppearancePacket(AT_Light, GetActiveLightType()); }
return; return;
} }
else if (item->item_id == item_id && item->equip_slot == slot && quantity >= 1) { else if (item->item_id == item_id && item->equip_slot == slot && quantity >= 1) {
if (item->charges <= quantity) { if (item->charges <= quantity) {
itemlist.erase(cur); itemlist.erase(cur);
UpdateEquipLightValue(); UpdateEquipmentLight();
if (UpdateActiveLightValue()) { SendAppearancePacket(AT_Light, GetActiveLightValue()); } if (UpdateActiveLight()) { SendAppearancePacket(AT_Light, GetActiveLightType()); }
} }
else { else {
item->charges -= quantity; item->charges -= quantity;
@ -483,9 +480,9 @@ void NPC::CheckMinMaxLevel(Mob *them)
++cur; ++cur;
} }
UpdateEquipLightValue(); UpdateEquipmentLight();
if (UpdateActiveLightValue()) if (UpdateActiveLight())
SendAppearancePacket(AT_Light, GetActiveLightValue()); SendAppearancePacket(AT_Light, GetActiveLightType());
} }
void NPC::ClearItemList() { void NPC::ClearItemList() {
@ -498,9 +495,9 @@ void NPC::ClearItemList() {
} }
itemlist.clear(); itemlist.clear();
UpdateEquipLightValue(); UpdateEquipmentLight();
if (UpdateActiveLightValue()) if (UpdateActiveLight())
SendAppearancePacket(AT_Light, GetActiveLightValue()); SendAppearancePacket(AT_Light, GetActiveLightType());
} }
void NPC::QueryLoot(Client* to) void NPC::QueryLoot(Client* to)
@ -718,24 +715,41 @@ uint32 NPC::CountLoot() {
return(itemlist.size()); return(itemlist.size());
} }
void NPC::UpdateEquipLightValue() void NPC::UpdateEquipmentLight()
{ {
equip_light = NOT_USED; m_Light.Type.Equipment = 0;
m_Light.Level.Equipment = 0;
for (int index = MAIN_BEGIN; index < EmuConstants::EQUIPMENT_SIZE; ++index) { for (int index = MAIN_BEGIN; index < EmuConstants::EQUIPMENT_SIZE; ++index) {
if (equipment[index] == NOT_USED) { continue; } if (index == MainAmmo) { continue; }
auto item = database.GetItem(equipment[index]); auto item = database.GetItem(equipment[index]);
if (item == nullptr) { continue; } if (item == nullptr) { continue; }
if (item->Light & 0xF0) { continue; }
if (item->Light > equip_light) { equip_light = item->Light; } if (m_Light.IsLevelGreater(item->Light, m_Light.Type.Equipment)) {
m_Light.Type.Equipment = item->Light;
m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment);
}
} }
for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) {
auto item = database.GetItem((*iter)->item_id); auto item = database.GetItem((*iter)->item_id);
if (item == nullptr) { continue; } if (item == nullptr) { continue; }
if (item->ItemType != ItemTypeMisc && item->ItemType != ItemTypeLight) { continue; }
if (item->Light & 0xF0) { continue; } switch (item->Light) {
if (item->Light > equip_light) { equip_light = item->Light; } case lightTypeCandle:
case lightTypeTorch:
case lightTypeSmallLantern:
case lightTypeLargeLantern:
continue;
default:
break;
}
if (m_Light.IsLevelGreater(item->Light, m_Light.Type.Equipment)) {
m_Light.Type.Equipment = item->Light;
m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment);
}
} }
} }
@ -1810,8 +1824,8 @@ void NPC::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
Mob::FillSpawnStruct(ns, ForWho); Mob::FillSpawnStruct(ns, ForWho);
PetOnSpawn(ns); PetOnSpawn(ns);
ns->spawn.is_npc = 1; ns->spawn.is_npc = 1;
UpdateActiveLightValue(); UpdateActiveLight();
ns->spawn.light = GetActiveLightValue(); ns->spawn.light = GetActiveLightType();
} }
void NPC::PetOnSpawn(NewSpawn_Struct* ns) void NPC::PetOnSpawn(NewSpawn_Struct* ns)

View File

@ -187,7 +187,7 @@ public:
void QueryLoot(Client* to); void QueryLoot(Client* to);
uint32 CountLoot(); uint32 CountLoot();
inline uint32 GetLoottableID() const { return loottable_id; } inline uint32 GetLoottableID() const { return loottable_id; }
virtual void UpdateEquipLightValue(); virtual void UpdateEquipmentLight();
inline uint32 GetCopper() const { return copper; } inline uint32 GetCopper() const { return copper; }
inline uint32 GetSilver() const { return silver; } inline uint32 GetSilver() const { return silver; }

View File

@ -417,7 +417,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
} }
} }
npc->UpdateEquipLightValue(); npc->UpdateEquipmentLight();
// finally, override size if one was provided // finally, override size if one was provided
if (in_size > 0.0f) if (in_size > 0.0f)