Skills.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. EQ2Emulator is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. EQ2Emulator is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "Skills.h"
  17. #include "Spawn.h"
  18. #include "LuaInterface.h"
  19. #include "../common/Log.h"
  20. extern ConfigReader configReader;
  21. extern LuaInterface* lua_interface;
  22. MasterSkillList::MasterSkillList(){
  23. }
  24. MasterSkillList::~MasterSkillList(){
  25. map<int32, Skill*>::iterator itr;
  26. for(itr = skills.begin(); itr != skills.end(); itr++){
  27. safe_delete(itr->second);
  28. }
  29. map<int16, EQ2Packet*>::iterator itr2;
  30. for(itr2 = populate_packets.begin(); itr2 != populate_packets.end(); itr2++){
  31. safe_delete(itr2->second);
  32. }
  33. }
  34. Skill::Skill(){
  35. skill_id = 0;
  36. current_val = 0;
  37. previous_val = 0;
  38. max_val = 0;
  39. skill_type = 0;
  40. display = 0;
  41. save_needed = false;
  42. active_skill = true;
  43. }
  44. Skill::Skill(Skill* skill){
  45. skill_id = skill->skill_id;
  46. current_val = skill->current_val;
  47. previous_val = skill->current_val;
  48. max_val = skill->max_val;
  49. skill_type = skill->skill_type;
  50. display = skill->display;
  51. short_name = skill->short_name;
  52. name = skill->name;
  53. description = skill->description;
  54. save_needed = false;
  55. active_skill = true;
  56. }
  57. map<int32, Skill*>* MasterSkillList::GetAllSkills(){
  58. return &skills;
  59. }
  60. Skill* MasterSkillList::GetSkill(int32 skill_id){
  61. if(skills.count(skill_id) > 0)
  62. return skills[skill_id];
  63. else
  64. return 0;
  65. }
  66. Skill* MasterSkillList::GetSkillByName(const char* skill_name) {
  67. Skill* skill = 0;
  68. map<int32, Skill*>::iterator itr;
  69. for (itr = skills.begin(); itr != skills.end(); itr++) {
  70. Skill* current_skill = itr->second;
  71. if (::ToLower(string(current_skill->name.data.c_str())) == ::ToLower(string(skill_name))) {
  72. skill = current_skill;
  73. break;
  74. }
  75. }
  76. return skill;
  77. }
  78. int16 MasterSkillList::GetSkillCount(){
  79. return skills.size();
  80. }
  81. void MasterSkillList::AddSkill(Skill* skill){
  82. if(skill)
  83. skills[skill->skill_id] = skill;
  84. }
  85. EQ2Packet* MasterSkillList::GetPopulateSkillsPacket(int16 version){
  86. EQ2Packet* ret = 0;
  87. int16 packet_version = configReader.GetStructVersion("WS_SkillMap", version);
  88. if(populate_packets.count(packet_version) > 0)
  89. ret = populate_packets[packet_version];
  90. else{
  91. PacketStruct* packet = configReader.getStruct("WS_SkillMap", packet_version);
  92. int32 count = skills.size();
  93. Skill* skill = 0;
  94. int32 i = 0;
  95. packet->setArrayLengthByName("skill_count", count);
  96. map<int32, Skill*>::iterator itr;
  97. for(itr = skills.begin(); itr != skills.end(); itr++, i++){
  98. skill = itr->second;
  99. packet->setArrayDataByName("skill_id", skill->skill_id, i);
  100. packet->setArrayDataByName("short_name", &skill->short_name, i);
  101. packet->setArrayDataByName("name", &skill->name, i);
  102. packet->setArrayDataByName("description", &skill->description, i);
  103. }
  104. populate_packets[packet_version] = packet->serialize();
  105. safe_delete(packet);
  106. ret = populate_packets[packet_version];
  107. }
  108. if(ret)
  109. 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
  110. else
  111. return ret;
  112. }
  113. PlayerSkillList::PlayerSkillList(){
  114. xor_packet = 0;
  115. orig_packet = 0;
  116. packet_count = 0;
  117. has_updates = false;
  118. MSkillUpdates.SetName("PlayerSkillList::MSkillUpdates");
  119. }
  120. PlayerSkillList::~PlayerSkillList(){
  121. map<int32, Skill*>::iterator itr;
  122. for(itr = skills.begin(); itr != skills.end(); itr++){
  123. safe_delete(itr->second);
  124. }
  125. MutexMap<int32, SkillBonus*>::iterator sb_itr = skill_bonus_list.begin();
  126. while (sb_itr.Next())
  127. RemoveSkillBonus(sb_itr.first);
  128. safe_delete_array(xor_packet);
  129. safe_delete_array(orig_packet);
  130. }
  131. void PlayerSkillList::AddSkill(Skill* new_skill){
  132. std::unique_lock lock(MPlayerSkills);
  133. Skill* tmpSkill = nullptr;
  134. if(skills.count(new_skill->skill_id)) {
  135. tmpSkill = skills[new_skill->skill_id];
  136. }
  137. skills[new_skill->skill_id] = new_skill;
  138. if(tmpSkill) {
  139. lua_interface->SetLuaUserDataStale(tmpSkill);
  140. safe_delete(tmpSkill);
  141. }
  142. name_skill_map.clear();
  143. }
  144. void PlayerSkillList::RemoveSkill(Skill* skill) {
  145. std::unique_lock lock(MPlayerSkills);
  146. if (skill) {
  147. lua_interface->SetLuaUserDataStale(skill);
  148. skill->active_skill = false;
  149. name_skill_map.clear();
  150. }
  151. }
  152. map<int32, Skill*>* PlayerSkillList::GetAllSkills(){
  153. return &skills;
  154. }
  155. void PlayerSkillList::SetSkillValuesByType(int8 type, int16 value, bool send_update) {
  156. map<int32, Skill*>::iterator itr;
  157. for (itr = skills.begin(); itr != skills.end(); itr++) {
  158. if (itr->second && itr->second->skill_type == type)
  159. SetSkill(itr->second, value, send_update);
  160. }
  161. }
  162. void PlayerSkillList::SetSkillCapsByType(int8 type, int16 value){
  163. map<int32, Skill*>::iterator itr;
  164. for(itr = skills.begin(); itr != skills.end(); itr++){
  165. if(itr->second && itr->second->skill_type == type)
  166. SetSkillCap(itr->second, value);
  167. }
  168. }
  169. void PlayerSkillList::IncreaseSkillCapsByType(int8 type, int16 value){
  170. map<int32, Skill*>::iterator itr;
  171. for(itr = skills.begin(); itr != skills.end(); itr++){
  172. if(itr->second && itr->second->skill_type == type)
  173. IncreaseSkillCap(itr->second, value);
  174. }
  175. }
  176. void PlayerSkillList::IncreaseAllSkillCaps(int16 value){
  177. map<int32, Skill*>::iterator itr;
  178. for(itr = skills.begin(); itr != skills.end(); itr++){
  179. IncreaseSkillCap(itr->second, value);
  180. }
  181. }
  182. bool PlayerSkillList::HasSkill(int32 skill_id){
  183. std::shared_lock lock(MPlayerSkills);
  184. return (skills.count(skill_id) > 0 && skills[skill_id]->active_skill);
  185. }
  186. Skill* PlayerSkillList::GetSkill(int32 skill_id){
  187. std::shared_lock lock(MPlayerSkills);
  188. if(skills.count(skill_id) > 0 && skills[skill_id]->active_skill)
  189. return skills[skill_id];
  190. else
  191. return 0;
  192. }
  193. void PlayerSkillList::IncreaseSkill(Skill* skill, int16 amount){
  194. if(skill){
  195. skill->previous_val = skill->current_val;
  196. skill->current_val += amount;
  197. if(skill->current_val > skill->max_val)
  198. skill->max_val = skill->current_val;
  199. AddSkillUpdateNeeded(skill);
  200. skill->save_needed = true;
  201. }
  202. }
  203. void PlayerSkillList::IncreaseSkill(int32 skill_id, int16 amount){
  204. IncreaseSkill(GetSkill(skill_id), amount);
  205. }
  206. void PlayerSkillList::DecreaseSkill(Skill* skill, int16 amount){
  207. if(skill){
  208. skill->previous_val = skill->current_val;
  209. if((skill->current_val - amount) < 0)
  210. skill->current_val = 0;
  211. else
  212. skill->current_val -= amount;
  213. skill->save_needed = true;
  214. AddSkillUpdateNeeded(skill);
  215. }
  216. }
  217. void PlayerSkillList::DecreaseSkill(int32 skill_id, int16 amount){
  218. DecreaseSkill(GetSkill(skill_id), amount);
  219. }
  220. void PlayerSkillList::SetSkill(Skill* skill, int16 value, bool send_update){
  221. if(skill){
  222. skill->previous_val = skill->current_val;
  223. skill->current_val = value;
  224. if(skill->current_val > skill->max_val)
  225. skill->max_val = skill->current_val;
  226. skill->save_needed = true;
  227. if(send_update)
  228. AddSkillUpdateNeeded(skill);
  229. }
  230. }
  231. void PlayerSkillList::SetSkill(int32 skill_id, int16 value, bool send_update){
  232. SetSkill(GetSkill(skill_id), value, send_update);
  233. }
  234. void PlayerSkillList::IncreaseSkillCap(Skill* skill, int16 amount){
  235. if(skill){
  236. skill->max_val += amount;
  237. skill->save_needed = true;
  238. }
  239. }
  240. void PlayerSkillList::IncreaseSkillCap(int32 skill_id, int16 amount){
  241. IncreaseSkillCap(GetSkill(skill_id), amount);
  242. }
  243. void PlayerSkillList::DecreaseSkillCap(Skill* skill, int16 amount){
  244. if(skill){
  245. if((skill->max_val - amount) < 0)
  246. skill->max_val = 0;
  247. else
  248. skill->max_val -= amount;
  249. if(skill->current_val > skill->max_val){
  250. skill->previous_val = skill->current_val;
  251. skill->current_val = skill->max_val;
  252. }
  253. AddSkillUpdateNeeded(skill);
  254. skill->save_needed = true;
  255. }
  256. }
  257. void PlayerSkillList::DecreaseSkillCap(int32 skill_id, int16 amount){
  258. DecreaseSkillCap(GetSkill(skill_id), amount);
  259. }
  260. void PlayerSkillList::SetSkillCap(Skill* skill, int16 value){
  261. if(skill){
  262. skill->max_val = value;
  263. if(skill->current_val > skill->max_val){
  264. skill->previous_val = skill->current_val;
  265. skill->current_val = skill->max_val;
  266. }
  267. AddSkillUpdateNeeded(skill);
  268. skill->save_needed = true;
  269. }
  270. }
  271. void PlayerSkillList::SetSkillCap(int32 skill_id, int16 value){
  272. SetSkillCap(GetSkill(skill_id), value);
  273. }
  274. int16 PlayerSkillList::CalculateSkillValue(int32 skill_id, int16 current_val){
  275. if (current_val > 5) {
  276. int16 new_val = current_val;
  277. MutexMap<int32, SkillBonus*>::iterator itr = skill_bonus_list.begin();
  278. while (itr.Next()) {
  279. SkillBonus* sb = itr.second;
  280. map<int32, SkillBonusValue*>::iterator sbv_itr;
  281. for (sbv_itr = sb->skills.begin(); sbv_itr != sb->skills.end(); sbv_itr++) {
  282. SkillBonusValue* sbv = sbv_itr->second;
  283. if (sbv->skill_id == skill_id)
  284. new_val += (int16)sbv->value;
  285. }
  286. }
  287. return new_val;
  288. }
  289. return current_val;
  290. }
  291. int16 PlayerSkillList::CalculateSkillMaxValue(int32 skill_id, int16 max_val) {
  292. int16 new_val = max_val;
  293. MutexMap<int32, SkillBonus*>::iterator itr = skill_bonus_list.begin();
  294. while (itr.Next()) {
  295. SkillBonus* sb = itr->second;
  296. map<int32, SkillBonusValue*>::iterator sbv_itr;
  297. for (sbv_itr = sb->skills.begin(); sbv_itr != sb->skills.end(); sbv_itr++) {
  298. SkillBonusValue* sbv = sbv_itr->second;
  299. if (sbv->skill_id == skill_id)
  300. new_val += (int16)sbv->value;
  301. }
  302. }
  303. return new_val;
  304. }
  305. EQ2Packet* PlayerSkillList::GetSkillPacket(int16 version){
  306. std::shared_lock lock(MPlayerSkills);
  307. PacketStruct* packet = configReader.getStruct("WS_UpdateSkillBook", version);
  308. if(packet){
  309. int16 skill_count = 0;
  310. map<int32, Skill*>::iterator itr;
  311. for (itr = skills.begin(); itr != skills.end(); itr++) {
  312. if (itr->second && itr->second->active_skill)
  313. skill_count++;
  314. }
  315. int16 size = 0;
  316. if (version > 546) {
  317. size = 21 * skill_count + 8;
  318. }
  319. else if (version <= 283) {
  320. size = 12 * skill_count + 6;
  321. }
  322. else if (version <= 546) {
  323. size = 21 * skill_count + 7;
  324. }
  325. if (skill_count > packet_count) {
  326. uchar* tmp = 0;
  327. if (orig_packet) {
  328. tmp = new uchar[size];
  329. memset(tmp, 0, size);
  330. memcpy(tmp, orig_packet, orig_packet_size);
  331. safe_delete_array(orig_packet);
  332. safe_delete_array(xor_packet);
  333. orig_packet = tmp;
  334. }
  335. else {
  336. orig_packet = new uchar[size];
  337. memset(orig_packet, 0, size);
  338. }
  339. xor_packet = new uchar[size];
  340. memset(xor_packet, 0, size);
  341. }
  342. packet_count = skill_count;
  343. orig_packet_size = size;
  344. packet->setArrayLengthByName("skill_count", skill_count);
  345. Skill* skill = 0;
  346. int32 i=0;
  347. for(itr = skills.begin(); itr != skills.end(); itr++){
  348. skill = itr->second;
  349. if(skill && skill->active_skill){
  350. int16 skill_max_with_bonuses = CalculateSkillMaxValue(skill->skill_id, skill->max_val);
  351. int16 skill_with_bonuses = int(CalculateSkillValue(skill->skill_id, skill->current_val));
  352. packet->setArrayDataByName("skill_id", skill->skill_id, i);
  353. if (version <= 546 && skill->skill_type >= SKILL_TYPE_GENERAL) { //covert it to DOF types
  354. packet->setArrayDataByName("type", skill->skill_type-2, i);
  355. }
  356. else if(version >= 60085 && skill->skill_type >= 12) {
  357. packet->setArrayDataByName("type", skill->skill_type-1, i);
  358. }
  359. else {
  360. packet->setArrayDataByName("type", skill->skill_type, i);
  361. }
  362. int16 current_val = skill->current_val;
  363. if(skill->skill_type == SKILL_TYPE_LANGUAGE) { // 13 is language in the DB?? 14 is the skill type though
  364. packet->setArrayDataByName("language_unknown", skill->skill_id, i);
  365. packet->setArrayDataByName("display_maxval", 1, i);
  366. packet->setArrayDataByName("max_val", 1, i);
  367. }
  368. else {
  369. packet->setArrayDataByName("max_val", skill->max_val, i);
  370. packet->setArrayDataByName("display_minval", skill->display, i);
  371. packet->setArrayDataByName("display_maxval", skill->display, i);
  372. packet->setArrayDataByName("skill_delta", 0, i);// skill_with_bonuses- skill->current_val
  373. packet->setArrayDataByName("skill_delta2", skill_max_with_bonuses - skill->max_val, i);// skill_max_with_bonuses - skill->max_val, i);
  374. }
  375. packet->setArrayDataByName("current_val", current_val, i);
  376. packet->setArrayDataByName("base_val", current_val, i);
  377. i++;
  378. }
  379. }
  380. int8 offset = 1;
  381. if (version <= 283)
  382. offset = 0;
  383. EQ2Packet* ret = packet->serializeCountPacket(version, offset, orig_packet, xor_packet);
  384. //packet->PrintPacket();
  385. //DumpPacket(orig_packet, orig_packet_size);
  386. //DumpPacket(ret);
  387. safe_delete(packet);
  388. return ret;
  389. }
  390. return 0;
  391. }
  392. bool PlayerSkillList::CheckSkillIncrease(Skill* skill){
  393. if(!skill || skill->current_val >= skill->max_val)
  394. return false;
  395. // Assuming that skills will be used more at higher levels, increase chances are:
  396. // skill val of 1 ~ 20% chance, value of 100 ~ 10%, value of 400 ~ 4%
  397. int8 percent = (int8)(((float)((float)100/(float)(50 + skill->current_val)))*10);
  398. if(rand()%100 < percent){ // skill increase
  399. IncreaseSkill(skill, 1);
  400. return true;
  401. }
  402. else
  403. return false;
  404. }
  405. Skill* PlayerSkillList::GetSkillByName(const char* name){
  406. std::shared_lock lock(MPlayerSkills);
  407. if(name_skill_map.size() == 0){
  408. map<int32, Skill*>::iterator itr;
  409. Skill* skill = 0;
  410. for(itr = skills.begin(); itr != skills.end(); itr++){
  411. skill = itr->second;
  412. name_skill_map[skill->name.data] = skill;
  413. }
  414. }
  415. if(name_skill_map.count(name) > 0)
  416. return name_skill_map[name];
  417. else
  418. return 0;
  419. }
  420. vector<Skill*>* PlayerSkillList::GetSaveNeededSkills(){
  421. std::shared_lock lock(MPlayerSkills);
  422. vector<Skill*>* ret = new vector<Skill*>;
  423. map<int32, Skill*>::iterator itr;
  424. for(itr = skills.begin(); itr != skills.end(); itr++){
  425. if(itr->second->save_needed){
  426. ret->push_back(itr->second);
  427. itr->second->save_needed = false;
  428. }
  429. }
  430. return ret;
  431. }
  432. void PlayerSkillList::AddSkillUpdateNeeded(Skill* skill){
  433. MSkillUpdates.writelock(__FUNCTION__, __LINE__);
  434. skill_updates.push_back(skill);
  435. has_updates = true;
  436. MSkillUpdates.releasewritelock(__FUNCTION__, __LINE__);
  437. }
  438. vector<Skill*>* PlayerSkillList::GetSkillUpdates(){
  439. vector<Skill*>* ret = 0;
  440. vector<Skill*>::iterator itr;
  441. MSkillUpdates.writelock(__FUNCTION__, __LINE__);
  442. if(skill_updates.size() > 0){
  443. ret = new vector<Skill*>();
  444. ret->insert(ret->begin(), skill_updates.begin(), skill_updates.end());
  445. skill_updates.clear();
  446. }
  447. has_updates = false;
  448. MSkillUpdates.releasewritelock(__FUNCTION__, __LINE__);
  449. return ret;
  450. }
  451. bool PlayerSkillList::HasSkillUpdates(){
  452. return has_updates;
  453. }
  454. void PlayerSkillList::AddSkillBonus(int32 spell_id, int32 skill_id, float value) {
  455. if (value != 0) {
  456. SkillBonus* sb;
  457. if (skill_bonus_list.count(spell_id) == 0) {
  458. sb = new SkillBonus;
  459. sb->spell_id = spell_id;
  460. skill_bonus_list.Put(spell_id, sb);
  461. }
  462. else
  463. sb = skill_bonus_list.Get(spell_id);
  464. if (sb->skills[skill_id] == nullptr) {
  465. SkillBonusValue* sbv = new SkillBonusValue;
  466. sbv->skill_id = skill_id;
  467. sbv->value = value;
  468. sb->skills[skill_id] = sbv;
  469. }
  470. }
  471. }
  472. void PlayerSkillList::ResetPackets() {
  473. safe_delete_array(orig_packet);
  474. safe_delete_array(xor_packet);
  475. orig_packet_size = 0;
  476. orig_packet = 0;
  477. xor_packet = 0;
  478. packet_count = 0;
  479. }
  480. SkillBonus* PlayerSkillList::GetSkillBonus(int32 spell_id) {
  481. SkillBonus *ret = 0;
  482. if (skill_bonus_list.count(spell_id) > 0)
  483. ret = skill_bonus_list.Get(spell_id);
  484. return ret;
  485. }
  486. void PlayerSkillList::RemoveSkillBonus(int32 spell_id) {
  487. if (skill_bonus_list.count(spell_id) > 0) {
  488. SkillBonus* sb = skill_bonus_list.Get(spell_id);
  489. skill_bonus_list.erase(spell_id);
  490. map<int32, SkillBonusValue*>::iterator itr;
  491. for (itr = sb->skills.begin(); itr != sb->skills.end(); itr++)
  492. safe_delete(itr->second);
  493. safe_delete(sb);
  494. }
  495. }
  496. int Skill::CheckDisarmSkill(int16 targetLevel, int8 chest_difficulty)
  497. {
  498. if (chest_difficulty < 2) // no triggers on this chest type
  499. return 1;
  500. if (targetLevel < 1)
  501. targetLevel = 1;
  502. int chest_diff_result = targetLevel * chest_difficulty;
  503. float base_difficulty = 15.0f;
  504. float fail_threshold = 10.0f;
  505. float chance = ((100.0f - base_difficulty) * ((float)current_val / (float)chest_diff_result));
  506. if (chance > (100.0f - base_difficulty))
  507. {
  508. chance = 100.0f - base_difficulty;
  509. }
  510. float d100 = (float)MakeRandomFloat(0, 100);
  511. if (d100 <= chance)
  512. return 1;
  513. else
  514. {
  515. if (d100 > (chance + fail_threshold))
  516. return -1;
  517. }
  518. return 0;
  519. }