Lacertae Update

Fix  - resolved spells with duration until cancel blinking after zoning
Fix  - hard coded activity status to solid/transport flags on lifts/boats resolves falling through lifts when moving on them

Additional crash fixes:
- stats clearing when calculating bonuses on entity
- Player equipment mutex lock protection
This commit is contained in:
Image 2021-08-22 14:57:35 -04:00
parent c867304727
commit b93cabc72e
6 changed files with 42 additions and 14 deletions

View file

@ -793,9 +793,6 @@ void Entity::DoRegenUpdate(){
SetHP(GetTotalHP());
else
SetHP(hp + temp);
LogWrite(MISC__TODO, 1, "TODO", "Fix this later for mobs\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);
}
if(GetPower() < GetTotalPower()){
sint16 temp = GetInfoStruct()->get_power_regen();
@ -804,8 +801,6 @@ void Entity::DoRegenUpdate(){
SetPower(GetTotalPower());
else
SetPower(power + temp);
LogWrite(MISC__TODO, 1, "TODO", "Fix this later for mobs\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);
}
}
@ -1129,8 +1124,6 @@ void Entity::CalculateBonuses(){
info->set_cur_mitigation(info->get_mitigation_base());
info->set_base_avoidance_pct(info->get_avoidance_base());
LogWrite(MISC__TODO, 1, "TODO", "Calculate via current spells\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);
info->set_disease(info->get_disease_base());
info->set_divine(info->get_divine_base());
info->set_heat(info->get_heat_base());
@ -1174,7 +1167,10 @@ void Entity::CalculateBonuses(){
info->set_offensivespeed(0);
MStats.lock();
stats.clear();
MStats.unlock();
ItemStatsValues* values = equipment_list.CalculateEquipmentBonuses(this);
CalculateSpellBonuses(values);
info->add_sta((float)values->sta);

View file

@ -1101,6 +1101,7 @@ public:
EquipmentItemList(const EquipmentItemList& list);
~EquipmentItemList();
Item* items[NUM_SLOTS];
Mutex MEquipmentItems;
vector<Item*>* GetAllEquippedItems();
@ -1127,7 +1128,6 @@ public:
void SetAppearanceType(int8 type) { AppearanceType = type; }
int8 GetAppearanceType() { return AppearanceType; }
private:
Mutex MEquipmentItems;
int8 AppearanceType; // 0 for normal equip, 1 for appearance
};

View file

@ -1712,6 +1712,7 @@ bool Player::DamageEquippedItems(int8 amount, Client* client) {
bool ret = false;
int8 item_type;
Item* item = 0;
equipment_list.MEquipmentItems.readlock(__FUNCTION__, __LINE__);
for(int8 i=0;i<NUM_SLOTS;i++){
item = equipment_list.items[i];
if(item) {
@ -1729,6 +1730,8 @@ bool Player::DamageEquippedItems(int8 amount, Client* client) {
}
}
}
equipment_list.MEquipmentItems.releasereadlock(__FUNCTION__, __LINE__);
return ret;
}
@ -1783,8 +1786,10 @@ vector<EQ2Packet*> Player::UnequipItem(int16 index, sint32 bag_id, int8 slot, in
LogWrite(PLAYER__ERROR, 0, "Player", "%u index is out of range for equip items, bag_id: %i, slot: %u, version: %u, appearance: %u", index, bag_id, slot, version, appearance_type);
return packets;
}
equipList->MEquipmentItems.readlock(__FUNCTION__, __LINE__);
Item* item = equipList->items[index];
equipList->MEquipmentItems.releasereadlock(__FUNCTION__, __LINE__);
if (item && bag_id == -999) {
int8 old_slot = item->details.slot_id;
if (item_list.AssignItemToFreeSlot(item)) {
@ -1836,9 +1841,17 @@ vector<EQ2Packet*> Player::UnequipItem(int16 index, sint32 bag_id, int8 slot, in
bag_id = 0;
}
item_list.MPlayerItems.readlock(__FUNCTION__, __LINE__);
if (item_list.items.count(bag_id) > 0 && item_list.items[bag_id][BASE_EQUIPMENT].count(slot) > 0)
to_item = item_list.items[bag_id][BASE_EQUIPMENT][slot];
bool canEquipToSlot = false;
if (to_item && equipList->CanItemBeEquippedInSlot(to_item, ConvertSlotFromClient(item->details.slot_id, version))) {
canEquipToSlot = true;
}
item_list.MPlayerItems.releasereadlock(__FUNCTION__, __LINE__);
if (canEquipToSlot) {
equipList->RemoveItem(index);
if(item->details.appearance_type)
database.DeleteItem(GetCharacterID(), item, "APPEARANCE");
@ -1877,7 +1890,10 @@ vector<EQ2Packet*> Player::UnequipItem(int16 index, sint32 bag_id, int8 slot, in
else if (to_item && to_item->IsBag() && to_item->details.num_slots > 0) {
bool free_slot = false;
for (int8 i = 0; i < to_item->details.num_slots; i++) {
if (item_list.items[to_item->details.bag_id][appearance_type].count(i) == 0) {
item_list.MPlayerItems.readlock(__FUNCTION__, __LINE__);
int32 count = item_list.items[to_item->details.bag_id][appearance_type].count(i);
item_list.MPlayerItems.releasereadlock(__FUNCTION__, __LINE__);
if (count == 0) {
SetEquipment(0, item->details.slot_id);
if(item->details.appearance_type)
@ -2029,14 +2045,19 @@ EQ2Packet* Player::SwapEquippedItems(int8 slot1, int8 slot2, int16 version, int1
if(equip_type == 3)
equipList = &appearance_equipment_list;
equipList->MEquipmentItems.readlock(__FUNCTION__, __LINE__);
Item* item_from = equipList->items[slot1];
Item* item_to = equipList->items[slot2];
equipList->MEquipmentItems.releasereadlock(__FUNCTION__, __LINE__);
if(item_from && equipList->CanItemBeEquippedInSlot(item_from, slot2)){
if(item_to){
if(!equipList->CanItemBeEquippedInSlot(item_to, slot1))
return 0;
}
equipList->MEquipmentItems.writelock(__FUNCTION__, __LINE__);
equipList->items[slot1] = nullptr;
equipList->MEquipmentItems.releasewritelock(__FUNCTION__, __LINE__);
equipList->SetItem(slot2, item_from);
if(item_to)
{

View file

@ -2563,6 +2563,9 @@ void Spawn::InitializeInfoPacketData(Player* spawn, PacketStruct* packet) {
// doesn't work for DoF client version 546
if (appearance.icon == 28 || appearance.icon == 12 || IsTransportSpawn())
{
// there is some other flags that setting with a transport breaks their solidity/ability to properly transport
// thus we just consider the following flags for now as all necessary
temp_activity_status = ACTIVITY_STATUS_SOLID_1188;
temp_activity_status += ACTIVITY_STATUS_ISTRANSPORT_1188;
}
}

View file

@ -1679,8 +1679,11 @@ void World::AddBonuses(Item* item, ItemStatsValues* values, int16 type, sint32 v
break;
}*/
default: {
if (entity)
if (entity) {
entity->MStats.lock();
entity->stats[type] += value;
entity->MStats.unlock();
}
break;
}
}

View file

@ -7651,8 +7651,10 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int
safe_delete(lua_spell);
continue;
}
info->spell_effects[effect_slot].expire_timestamp = Timer::GetCurrentTime2() + expire_timestamp;
if(spell->GetSpellData()->duration_until_cancel)
info->spell_effects[effect_slot].expire_timestamp = 0xFFFFFFFF;
else
info->spell_effects[effect_slot].expire_timestamp = Timer::GetCurrentTime2() + expire_timestamp;
info->spell_effects[effect_slot].icon = icon;
info->spell_effects[effect_slot].icon_backdrop = icon_backdrop;
info->spell_effects[effect_slot].spell_id = spell_id;
@ -7771,7 +7773,10 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int
info->maintained_effects[effect_slot].slot_pos = slot_pos;
info->maintained_effects[effect_slot].target = targetID;
info->maintained_effects[effect_slot].target_type = target_type;
info->maintained_effects[effect_slot].expire_timestamp = Timer::GetCurrentTime2() + expire_timestamp;
if(spell->GetSpellData()->duration_until_cancel)
info->maintained_effects[effect_slot].expire_timestamp = 0xFFFFFFFF;
else
info->maintained_effects[effect_slot].expire_timestamp = Timer::GetCurrentTime2() + expire_timestamp;
info->maintained_effects[effect_slot].icon = icon;
info->maintained_effects[effect_slot].icon_backdrop = icon_backdrop;
info->maintained_effects[effect_slot].spell_id = spell_id;