123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590 |
- /*
- EQ2Emulator: Everquest II Server Emulator
- Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
- This file is part of EQ2Emulator.
- EQ2Emulator is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- EQ2Emulator is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "Skills.h"
- #include "Spawn.h"
- #include "LuaInterface.h"
- #include "../common/Log.h"
- extern ConfigReader configReader;
- extern LuaInterface* lua_interface;
- MasterSkillList::MasterSkillList(){
- }
- MasterSkillList::~MasterSkillList(){
- map<int32, Skill*>::iterator itr;
- for(itr = skills.begin(); itr != skills.end(); itr++){
- safe_delete(itr->second);
- }
- map<int16, EQ2Packet*>::iterator itr2;
- for(itr2 = populate_packets.begin(); itr2 != populate_packets.end(); itr2++){
- safe_delete(itr2->second);
- }
- }
- Skill::Skill(){
- skill_id = 0;
- current_val = 0;
- previous_val = 0;
- max_val = 0;
- skill_type = 0;
- display = 0;
- save_needed = false;
- active_skill = true;
- }
- Skill::Skill(Skill* skill){
- skill_id = skill->skill_id;
- current_val = skill->current_val;
- previous_val = skill->current_val;
- max_val = skill->max_val;
- skill_type = skill->skill_type;
- display = skill->display;
- short_name = skill->short_name;
- name = skill->name;
- description = skill->description;
- save_needed = false;
- active_skill = true;
- }
- map<int32, Skill*>* MasterSkillList::GetAllSkills(){
- return &skills;
- }
- Skill* MasterSkillList::GetSkill(int32 skill_id){
- if(skills.count(skill_id) > 0)
- return skills[skill_id];
- else
- return 0;
- }
- Skill* MasterSkillList::GetSkillByName(const char* skill_name) {
- Skill* skill = 0;
- map<int32, Skill*>::iterator itr;
- for (itr = skills.begin(); itr != skills.end(); itr++) {
- Skill* current_skill = itr->second;
- if (::ToLower(string(current_skill->name.data.c_str())) == ::ToLower(string(skill_name))) {
- skill = current_skill;
- break;
- }
- }
- return skill;
- }
- int16 MasterSkillList::GetSkillCount(){
- return skills.size();
- }
- void MasterSkillList::AddSkill(Skill* skill){
- if(skill)
- skills[skill->skill_id] = skill;
- }
- EQ2Packet* MasterSkillList::GetPopulateSkillsPacket(int16 version){
- EQ2Packet* ret = 0;
- int16 packet_version = configReader.GetStructVersion("WS_SkillMap", version);
- if(populate_packets.count(packet_version) > 0)
- ret = populate_packets[packet_version];
- else{
- PacketStruct* packet = configReader.getStruct("WS_SkillMap", packet_version);
- int32 count = skills.size();
- Skill* skill = 0;
- int32 i = 0;
- packet->setArrayLengthByName("skill_count", count);
- map<int32, Skill*>::iterator itr;
- for(itr = skills.begin(); itr != skills.end(); itr++, i++){
- skill = itr->second;
- packet->setArrayDataByName("skill_id", skill->skill_id, i);
- packet->setArrayDataByName("short_name", &skill->short_name, i);
- packet->setArrayDataByName("name", &skill->name, i);
- packet->setArrayDataByName("description", &skill->description, i);
- }
- populate_packets[packet_version] = packet->serialize();
- safe_delete(packet);
- ret = populate_packets[packet_version];
- }
- if(ret)
- return ret->Copy(); //need to return a copy as the packet is deleted after the client confirms it and we want to keep the packet to prevent constant generation of the same data
- else
- return ret;
- }
- PlayerSkillList::PlayerSkillList(){
- xor_packet = 0;
- orig_packet = 0;
- packet_count = 0;
- has_updates = false;
- MSkillUpdates.SetName("PlayerSkillList::MSkillUpdates");
- }
- PlayerSkillList::~PlayerSkillList(){
- map<int32, Skill*>::iterator itr;
- for(itr = skills.begin(); itr != skills.end(); itr++){
- safe_delete(itr->second);
- }
- MutexMap<int32, SkillBonus*>::iterator sb_itr = skill_bonus_list.begin();
- while (sb_itr.Next())
- RemoveSkillBonus(sb_itr.first);
- safe_delete_array(xor_packet);
- safe_delete_array(orig_packet);
- }
- void PlayerSkillList::AddSkill(Skill* new_skill){
- std::unique_lock lock(MPlayerSkills);
- Skill* tmpSkill = nullptr;
- if(skills.count(new_skill->skill_id)) {
- tmpSkill = skills[new_skill->skill_id];
- }
- skills[new_skill->skill_id] = new_skill;
- if(tmpSkill) {
- lua_interface->SetLuaUserDataStale(tmpSkill);
- safe_delete(tmpSkill);
- }
- name_skill_map.clear();
- }
- void PlayerSkillList::RemoveSkill(Skill* skill) {
- std::unique_lock lock(MPlayerSkills);
- if (skill) {
- lua_interface->SetLuaUserDataStale(skill);
- skill->active_skill = false;
- name_skill_map.clear();
- }
- }
- map<int32, Skill*>* PlayerSkillList::GetAllSkills(){
- return &skills;
- }
- void PlayerSkillList::SetSkillValuesByType(int8 type, int16 value, bool send_update) {
- map<int32, Skill*>::iterator itr;
- for (itr = skills.begin(); itr != skills.end(); itr++) {
- if (itr->second && itr->second->skill_type == type)
- SetSkill(itr->second, value, send_update);
- }
- }
- void PlayerSkillList::SetSkillCapsByType(int8 type, int16 value){
- map<int32, Skill*>::iterator itr;
- for(itr = skills.begin(); itr != skills.end(); itr++){
- if(itr->second && itr->second->skill_type == type)
- SetSkillCap(itr->second, value);
- }
- }
- void PlayerSkillList::IncreaseSkillCapsByType(int8 type, int16 value){
- map<int32, Skill*>::iterator itr;
- for(itr = skills.begin(); itr != skills.end(); itr++){
- if(itr->second && itr->second->skill_type == type)
- IncreaseSkillCap(itr->second, value);
- }
- }
- void PlayerSkillList::IncreaseAllSkillCaps(int16 value){
- map<int32, Skill*>::iterator itr;
- for(itr = skills.begin(); itr != skills.end(); itr++){
- IncreaseSkillCap(itr->second, value);
- }
- }
- bool PlayerSkillList::HasSkill(int32 skill_id){
- std::shared_lock lock(MPlayerSkills);
- return (skills.count(skill_id) > 0 && skills[skill_id]->active_skill);
- }
- Skill* PlayerSkillList::GetSkill(int32 skill_id){
- std::shared_lock lock(MPlayerSkills);
- if(skills.count(skill_id) > 0 && skills[skill_id]->active_skill)
- return skills[skill_id];
- else
- return 0;
- }
- void PlayerSkillList::IncreaseSkill(Skill* skill, int16 amount){
- if(skill){
- skill->previous_val = skill->current_val;
- skill->current_val += amount;
- if(skill->current_val > skill->max_val)
- skill->max_val = skill->current_val;
- AddSkillUpdateNeeded(skill);
- skill->save_needed = true;
- }
- }
- void PlayerSkillList::IncreaseSkill(int32 skill_id, int16 amount){
- IncreaseSkill(GetSkill(skill_id), amount);
- }
- void PlayerSkillList::DecreaseSkill(Skill* skill, int16 amount){
- if(skill){
- skill->previous_val = skill->current_val;
- if((skill->current_val - amount) < 0)
- skill->current_val = 0;
- else
- skill->current_val -= amount;
- skill->save_needed = true;
- AddSkillUpdateNeeded(skill);
- }
- }
- void PlayerSkillList::DecreaseSkill(int32 skill_id, int16 amount){
- DecreaseSkill(GetSkill(skill_id), amount);
- }
- void PlayerSkillList::SetSkill(Skill* skill, int16 value, bool send_update){
- if(skill){
- skill->previous_val = skill->current_val;
- skill->current_val = value;
- if(skill->current_val > skill->max_val)
- skill->max_val = skill->current_val;
- skill->save_needed = true;
- if(send_update)
- AddSkillUpdateNeeded(skill);
- }
- }
- void PlayerSkillList::SetSkill(int32 skill_id, int16 value, bool send_update){
- SetSkill(GetSkill(skill_id), value, send_update);
- }
- void PlayerSkillList::IncreaseSkillCap(Skill* skill, int16 amount){
- if(skill){
- skill->max_val += amount;
- skill->save_needed = true;
- }
- }
- void PlayerSkillList::IncreaseSkillCap(int32 skill_id, int16 amount){
- IncreaseSkillCap(GetSkill(skill_id), amount);
- }
- void PlayerSkillList::DecreaseSkillCap(Skill* skill, int16 amount){
- if(skill){
- if((skill->max_val - amount) < 0)
- skill->max_val = 0;
- else
- skill->max_val -= amount;
- if(skill->current_val > skill->max_val){
- skill->previous_val = skill->current_val;
- skill->current_val = skill->max_val;
- }
- AddSkillUpdateNeeded(skill);
- skill->save_needed = true;
- }
- }
- void PlayerSkillList::DecreaseSkillCap(int32 skill_id, int16 amount){
- DecreaseSkillCap(GetSkill(skill_id), amount);
- }
- void PlayerSkillList::SetSkillCap(Skill* skill, int16 value){
- if(skill){
- skill->max_val = value;
- if(skill->current_val > skill->max_val){
- skill->previous_val = skill->current_val;
- skill->current_val = skill->max_val;
- }
- AddSkillUpdateNeeded(skill);
- skill->save_needed = true;
- }
- }
- void PlayerSkillList::SetSkillCap(int32 skill_id, int16 value){
- SetSkillCap(GetSkill(skill_id), value);
- }
- int16 PlayerSkillList::CalculateSkillValue(int32 skill_id, int16 current_val){
- if (current_val > 5) {
- int16 new_val = current_val;
- MutexMap<int32, SkillBonus*>::iterator itr = skill_bonus_list.begin();
- while (itr.Next()) {
- SkillBonus* sb = itr.second;
- map<int32, SkillBonusValue*>::iterator sbv_itr;
- for (sbv_itr = sb->skills.begin(); sbv_itr != sb->skills.end(); sbv_itr++) {
- SkillBonusValue* sbv = sbv_itr->second;
- if (sbv->skill_id == skill_id)
- new_val += (int16)sbv->value;
- }
- }
- return new_val;
- }
- return current_val;
- }
- int16 PlayerSkillList::CalculateSkillMaxValue(int32 skill_id, int16 max_val) {
- int16 new_val = max_val;
- MutexMap<int32, SkillBonus*>::iterator itr = skill_bonus_list.begin();
- while (itr.Next()) {
- SkillBonus* sb = itr->second;
- map<int32, SkillBonusValue*>::iterator sbv_itr;
- for (sbv_itr = sb->skills.begin(); sbv_itr != sb->skills.end(); sbv_itr++) {
- SkillBonusValue* sbv = sbv_itr->second;
- if (sbv->skill_id == skill_id)
- new_val += (int16)sbv->value;
- }
- }
- return new_val;
- }
- EQ2Packet* PlayerSkillList::GetSkillPacket(int16 version){
- std::shared_lock lock(MPlayerSkills);
- PacketStruct* packet = configReader.getStruct("WS_UpdateSkillBook", version);
- if(packet){
- int16 skill_count = 0;
- map<int32, Skill*>::iterator itr;
- for (itr = skills.begin(); itr != skills.end(); itr++) {
- if (itr->second && itr->second->active_skill)
- skill_count++;
- }
- int16 size = 0;
- if (version > 561) {
- size = 21 * skill_count + 8;
- }
- else if (version < 373) {
- size = 12 * skill_count + 6;
- }
- else if (version <= 373) {
- size = 15 * skill_count + 6;
- }
- else if (version <= 561) {
- size = 21 * skill_count + 7;
- }
-
- if (skill_count > packet_count) {
- uchar* tmp = 0;
- if (orig_packet) {
- tmp = new uchar[size];
- memset(tmp, 0, size);
- memcpy(tmp, orig_packet, orig_packet_size);
- safe_delete_array(orig_packet);
- safe_delete_array(xor_packet);
- orig_packet = tmp;
- }
- else {
- orig_packet = new uchar[size];
- memset(orig_packet, 0, size);
- }
- xor_packet = new uchar[size];
- memset(xor_packet, 0, size);
- }
- packet_count = skill_count;
- orig_packet_size = size;
- packet->setArrayLengthByName("skill_count", skill_count);
- Skill* skill = 0;
- int32 i=0;
- for(itr = skills.begin(); itr != skills.end(); itr++){
- skill = itr->second;
- if(skill && skill->active_skill){
- int16 skill_max_with_bonuses = CalculateSkillMaxValue(skill->skill_id, skill->max_val);
- int16 skill_with_bonuses = int(CalculateSkillValue(skill->skill_id, skill->current_val));
- packet->setArrayDataByName("skill_id", skill->skill_id, i);
- if (version <= 561 && skill->skill_type >= SKILL_TYPE_GENERAL) { //covert it to DOF types
- packet->setArrayDataByName("type", skill->skill_type-2, i);
- }
- else if(version >= 60085 && skill->skill_type >= 12) {
- packet->setArrayDataByName("type", skill->skill_type-1, i);
- }
- else {
- packet->setArrayDataByName("type", skill->skill_type, i);
- }
-
- int16 current_val = skill->current_val;
-
- if(skill->skill_type == SKILL_TYPE_LANGUAGE) { // 13 is language in the DB?? 14 is the skill type though
- packet->setArrayDataByName("language_unknown", skill->skill_id, i);
- packet->setArrayDataByName("display_maxval", 1, i);
- packet->setArrayDataByName("max_val", 1, i);
- }
- else {
- packet->setArrayDataByName("max_val", skill->max_val, i);
- packet->setArrayDataByName("display_minval", skill->display, i);
- packet->setArrayDataByName("display_maxval", skill->display, i);
- packet->setArrayDataByName("skill_delta", 0, i);// skill_with_bonuses- skill->current_val
- packet->setArrayDataByName("skill_delta2", skill_max_with_bonuses - skill->max_val, i);// skill_max_with_bonuses - skill->max_val, i);
- }
-
- packet->setArrayDataByName("current_val", current_val, i);
- packet->setArrayDataByName("base_val", current_val, i);
- i++;
- }
- }
- int8 offset = 1;
- if (version <= 373)
- offset = 0;
- EQ2Packet* ret = packet->serializeCountPacket(version, offset, orig_packet, xor_packet);
- //packet->PrintPacket();
- //DumpPacket(orig_packet, orig_packet_size);
- //DumpPacket(ret);
- safe_delete(packet);
- return ret;
- }
- return 0;
- }
- bool PlayerSkillList::CheckSkillIncrease(Skill* skill){
- if(!skill || skill->current_val >= skill->max_val)
- return false;
- // Assuming that skills will be used more at higher levels, increase chances are:
- // skill val of 1 ~ 20% chance, value of 100 ~ 10%, value of 400 ~ 4%
- int8 percent = (int8)(((float)((float)100/(float)(50 + skill->current_val)))*10);
- if(rand()%100 < percent){ // skill increase
- IncreaseSkill(skill, 1);
- return true;
- }
- else
- return false;
- }
- Skill* PlayerSkillList::GetSkillByName(const char* name){
- std::shared_lock lock(MPlayerSkills);
- if(name_skill_map.size() == 0){
- map<int32, Skill*>::iterator itr;
- Skill* skill = 0;
- for(itr = skills.begin(); itr != skills.end(); itr++){
- skill = itr->second;
- name_skill_map[skill->name.data] = skill;
- }
- }
- if(name_skill_map.count(name) > 0)
- return name_skill_map[name];
- else
- return 0;
- }
- vector<Skill*>* PlayerSkillList::GetSaveNeededSkills(){
- std::shared_lock lock(MPlayerSkills);
- vector<Skill*>* ret = new vector<Skill*>;
- map<int32, Skill*>::iterator itr;
- for(itr = skills.begin(); itr != skills.end(); itr++){
- if(itr->second->save_needed){
- ret->push_back(itr->second);
- itr->second->save_needed = false;
- }
- }
- return ret;
- }
- void PlayerSkillList::AddSkillUpdateNeeded(Skill* skill){
- MSkillUpdates.writelock(__FUNCTION__, __LINE__);
- skill_updates.push_back(skill);
- has_updates = true;
- MSkillUpdates.releasewritelock(__FUNCTION__, __LINE__);
- }
- vector<Skill*>* PlayerSkillList::GetSkillUpdates(){
- vector<Skill*>* ret = 0;
- vector<Skill*>::iterator itr;
- MSkillUpdates.writelock(__FUNCTION__, __LINE__);
- if(skill_updates.size() > 0){
- ret = new vector<Skill*>();
- ret->insert(ret->begin(), skill_updates.begin(), skill_updates.end());
- skill_updates.clear();
- }
- has_updates = false;
- MSkillUpdates.releasewritelock(__FUNCTION__, __LINE__);
- return ret;
- }
- bool PlayerSkillList::HasSkillUpdates(){
- return has_updates;
- }
- void PlayerSkillList::AddSkillBonus(int32 spell_id, int32 skill_id, float value) {
- if (value != 0) {
- SkillBonus* sb;
- if (skill_bonus_list.count(spell_id) == 0) {
- sb = new SkillBonus;
- sb->spell_id = spell_id;
- skill_bonus_list.Put(spell_id, sb);
- }
- else
- sb = skill_bonus_list.Get(spell_id);
-
- if (sb->skills[skill_id] == nullptr) {
- SkillBonusValue* sbv = new SkillBonusValue;
- sbv->skill_id = skill_id;
- sbv->value = value;
- sb->skills[skill_id] = sbv;
- }
- }
- }
- void PlayerSkillList::ResetPackets() {
- safe_delete_array(orig_packet);
- safe_delete_array(xor_packet);
- orig_packet_size = 0;
- orig_packet = 0;
- xor_packet = 0;
- packet_count = 0;
- }
- SkillBonus* PlayerSkillList::GetSkillBonus(int32 spell_id) {
- SkillBonus *ret = 0;
-
- if (skill_bonus_list.count(spell_id) > 0)
- ret = skill_bonus_list.Get(spell_id);
- return ret;
- }
- void PlayerSkillList::RemoveSkillBonus(int32 spell_id) {
- if (skill_bonus_list.count(spell_id) > 0) {
- SkillBonus* sb = skill_bonus_list.Get(spell_id);
- skill_bonus_list.erase(spell_id);
- map<int32, SkillBonusValue*>::iterator itr;
- for (itr = sb->skills.begin(); itr != sb->skills.end(); itr++)
- safe_delete(itr->second);
- safe_delete(sb);
- }
- }
- int Skill::CheckDisarmSkill(int16 targetLevel, int8 chest_difficulty)
- {
- if (chest_difficulty < 2) // no triggers on this chest type
- return 1;
- if (targetLevel < 1)
- targetLevel = 1;
- int chest_diff_result = targetLevel * chest_difficulty;
- float base_difficulty = 15.0f;
- float fail_threshold = 10.0f;
- float chance = ((100.0f - base_difficulty) * ((float)current_val / (float)chest_diff_result));
- if (chance > (100.0f - base_difficulty))
- {
- chance = 100.0f - base_difficulty;
- }
- float d100 = (float)MakeRandomFloat(0, 100);
- if (d100 <= chance)
- return 1;
- else
- {
- if (d100 > (chance + fail_threshold))
- return -1;
- }
- return 0;
- }
|