Lacertae Update #4
Fix #376 - resolved spells with duration until cancel blinking after zoning Fix #375 - 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:
parent
c867304727
commit
b93cabc72e
6 changed files with 42 additions and 14 deletions
EQ2/source/WorldServer
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue