Skills.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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 "../common/Log.h"
  19. extern ConfigReader configReader;
  20. MasterSkillList::MasterSkillList(){
  21. }
  22. MasterSkillList::~MasterSkillList(){
  23. map<int32, Skill*>::iterator itr;
  24. for(itr = skills.begin(); itr != skills.end(); itr++){
  25. safe_delete(itr->second);
  26. }
  27. map<int16, EQ2Packet*>::iterator itr2;
  28. for(itr2 = populate_packets.begin(); itr2 != populate_packets.end(); itr2++){
  29. safe_delete(itr2->second);
  30. }
  31. }
  32. Skill::Skill(){
  33. skill_id = 0;
  34. current_val = 0;
  35. previous_val = 0;
  36. max_val = 0;
  37. skill_type = 0;
  38. display = 0;
  39. save_needed = false;
  40. }
  41. Skill::Skill(Skill* skill){
  42. skill_id = skill->skill_id;
  43. current_val = skill->current_val;
  44. previous_val = skill->current_val;
  45. max_val = skill->max_val;
  46. skill_type = skill->skill_type;
  47. display = skill->display;
  48. short_name = skill->short_name;
  49. name = skill->name;
  50. description = skill->description;
  51. save_needed = false;
  52. }
  53. map<int32, Skill*>* MasterSkillList::GetAllSkills(){
  54. return &skills;
  55. }
  56. Skill* MasterSkillList::GetSkill(int32 skill_id){
  57. if(skills.count(skill_id) > 0)
  58. return skills[skill_id];
  59. else
  60. return 0;
  61. }
  62. Skill* MasterSkillList::GetSkillByName(const char* skill_name) {
  63. Skill* skill = 0;
  64. map<int32, Skill*>::iterator itr;
  65. for (itr = skills.begin(); itr != skills.end(); itr++) {
  66. Skill* current_skill = itr->second;
  67. if (::ToLower(string(current_skill->name.data.c_str())) == ::ToLower(string(skill_name))) {
  68. skill = current_skill;
  69. break;
  70. }
  71. }
  72. return skill;
  73. }
  74. int16 MasterSkillList::GetSkillCount(){
  75. return skills.size();
  76. }
  77. void MasterSkillList::AddSkill(Skill* skill){
  78. if(skill)
  79. skills[skill->skill_id] = skill;
  80. }
  81. EQ2Packet* MasterSkillList::GetPopulateSkillsPacket(int16 version){
  82. EQ2Packet* ret = 0;
  83. int16 packet_version = configReader.GetStructVersion("WS_SkillMap", version);
  84. if(populate_packets.count(packet_version) > 0)
  85. ret = populate_packets[packet_version];
  86. else{
  87. PacketStruct* packet = configReader.getStruct("WS_SkillMap", packet_version);
  88. int32 count = skills.size();
  89. Skill* skill = 0;
  90. int32 i = 0;
  91. packet->setArrayLengthByName("skill_count", count);
  92. map<int32, Skill*>::iterator itr;
  93. for(itr = skills.begin(); itr != skills.end(); itr++, i++){
  94. skill = itr->second;
  95. packet->setArrayDataByName("skill_id", skill->skill_id, i);
  96. packet->setArrayDataByName("short_name", &skill->short_name, i);
  97. packet->setArrayDataByName("name", &skill->name, i);
  98. packet->setArrayDataByName("description", &skill->description, i);
  99. }
  100. populate_packets[packet_version] = packet->serialize();
  101. safe_delete(packet);
  102. ret = populate_packets[packet_version];
  103. }
  104. if(ret)
  105. 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
  106. else
  107. return ret;
  108. }
  109. PlayerSkillList::PlayerSkillList(){
  110. xor_packet = 0;
  111. orig_packet = 0;
  112. packet_count = 0;
  113. has_updates = false;
  114. MSkillUpdates.SetName("PlayerSkillList::MSkillUpdates");
  115. }
  116. PlayerSkillList::~PlayerSkillList(){
  117. map<int32, Skill*>::iterator itr;
  118. for(itr = skills.begin(); itr != skills.end(); itr++){
  119. safe_delete(itr->second);
  120. }
  121. MutexMap<int32, SkillBonus*>::iterator sb_itr = skill_bonus_list.begin();
  122. while (sb_itr.Next())
  123. RemoveSkillBonus(sb_itr.first);
  124. safe_delete_array(xor_packet);
  125. safe_delete_array(orig_packet);
  126. }
  127. void PlayerSkillList::AddSkill(Skill* new_skill){
  128. skills[new_skill->skill_id] = new_skill;
  129. }
  130. void PlayerSkillList::RemoveSkill(Skill* skill) {
  131. if (skill)
  132. skills.erase(skill->skill_id);
  133. }
  134. map<int32, Skill*>* PlayerSkillList::GetAllSkills(){
  135. return &skills;
  136. }
  137. void PlayerSkillList::SetSkillCapsByType(int8 type, int16 value){
  138. map<int32, Skill*>::iterator itr;
  139. for(itr = skills.begin(); itr != skills.end(); itr++){
  140. if(itr->second && itr->second->skill_type == type)
  141. SetSkillCap(itr->second, value);
  142. }
  143. }
  144. void PlayerSkillList::IncreaseSkillCapsByType(int8 type, int16 value){
  145. map<int32, Skill*>::iterator itr;
  146. for(itr = skills.begin(); itr != skills.end(); itr++){
  147. if(itr->second && itr->second->skill_type == type)
  148. IncreaseSkillCap(itr->second, value);
  149. }
  150. }
  151. void PlayerSkillList::IncreaseAllSkillCaps(int16 value){
  152. map<int32, Skill*>::iterator itr;
  153. for(itr = skills.begin(); itr != skills.end(); itr++){
  154. IncreaseSkillCap(itr->second, value);
  155. }
  156. }
  157. bool PlayerSkillList::HasSkill(int32 skill_id){
  158. return (skills.count(skill_id) > 0);
  159. }
  160. Skill* PlayerSkillList::GetSkill(int32 skill_id){
  161. if(skills.count(skill_id) > 0)
  162. return skills[skill_id];
  163. else
  164. return 0;
  165. }
  166. void PlayerSkillList::IncreaseSkill(Skill* skill, int16 amount){
  167. if(skill){
  168. skill->previous_val = skill->current_val;
  169. skill->current_val += amount;
  170. if(skill->current_val > skill->max_val)
  171. skill->max_val = skill->current_val;
  172. AddSkillUpdateNeeded(skill);
  173. skill->save_needed = true;
  174. }
  175. }
  176. void PlayerSkillList::IncreaseSkill(int32 skill_id, int16 amount){
  177. IncreaseSkill(GetSkill(skill_id), amount);
  178. }
  179. void PlayerSkillList::DecreaseSkill(Skill* skill, int16 amount){
  180. if(skill){
  181. skill->previous_val = skill->current_val;
  182. if((skill->current_val - amount) < 0)
  183. skill->current_val = 0;
  184. else
  185. skill->current_val -= amount;
  186. skill->save_needed = true;
  187. AddSkillUpdateNeeded(skill);
  188. }
  189. }
  190. void PlayerSkillList::DecreaseSkill(int32 skill_id, int16 amount){
  191. DecreaseSkill(GetSkill(skill_id), amount);
  192. }
  193. void PlayerSkillList::SetSkill(Skill* skill, int16 value){
  194. if(skill){
  195. skill->previous_val = skill->current_val;
  196. skill->current_val = value;
  197. if(skill->current_val > skill->max_val)
  198. skill->max_val = skill->current_val;
  199. skill->save_needed = true;
  200. AddSkillUpdateNeeded(skill);
  201. }
  202. }
  203. void PlayerSkillList::SetSkill(int32 skill_id, int16 value){
  204. SetSkill(GetSkill(skill_id), value);
  205. }
  206. void PlayerSkillList::IncreaseSkillCap(Skill* skill, int16 amount){
  207. if(skill){
  208. skill->max_val += amount;
  209. skill->save_needed = true;
  210. }
  211. }
  212. void PlayerSkillList::IncreaseSkillCap(int32 skill_id, int16 amount){
  213. IncreaseSkillCap(GetSkill(skill_id), amount);
  214. }
  215. void PlayerSkillList::DecreaseSkillCap(Skill* skill, int16 amount){
  216. if(skill){
  217. if((skill->max_val - amount) < 0)
  218. skill->max_val = 0;
  219. else
  220. skill->max_val -= amount;
  221. if(skill->current_val > skill->max_val){
  222. skill->previous_val = skill->current_val;
  223. skill->current_val = skill->max_val;
  224. }
  225. AddSkillUpdateNeeded(skill);
  226. skill->save_needed = true;
  227. }
  228. }
  229. void PlayerSkillList::DecreaseSkillCap(int32 skill_id, int16 amount){
  230. DecreaseSkillCap(GetSkill(skill_id), amount);
  231. }
  232. void PlayerSkillList::SetSkillCap(Skill* skill, int16 value){
  233. if(skill){
  234. skill->max_val = value;
  235. if(skill->current_val > skill->max_val){
  236. skill->previous_val = skill->current_val;
  237. skill->current_val = skill->max_val;
  238. }
  239. AddSkillUpdateNeeded(skill);
  240. skill->save_needed = true;
  241. }
  242. }
  243. void PlayerSkillList::SetSkillCap(int32 skill_id, int16 value){
  244. SetSkillCap(GetSkill(skill_id), value);
  245. }
  246. int16 PlayerSkillList::CalculateSkillValue(int32 skill_id, int16 current_val){
  247. if (current_val > 5) {
  248. int16 new_val = current_val;
  249. MutexMap<int32, SkillBonus*>::iterator itr = skill_bonus_list.begin();
  250. while (itr.Next()) {
  251. SkillBonus* sb = itr.second;
  252. map<int32, SkillBonusValue*>::iterator sbv_itr;
  253. for (sbv_itr = sb->skills.begin(); sbv_itr != sb->skills.end(); sbv_itr++) {
  254. SkillBonusValue* sbv = sbv_itr->second;
  255. if (sbv->skill_id == skill_id)
  256. new_val += (int16)sbv->value;
  257. }
  258. }
  259. return new_val;
  260. }
  261. return current_val;
  262. }
  263. int16 PlayerSkillList::CalculateSkillMaxValue(int32 skill_id, int16 max_val) {
  264. int16 new_val = max_val;
  265. MutexMap<int32, SkillBonus*>::iterator itr = skill_bonus_list.begin();
  266. while (itr.Next()) {
  267. SkillBonus* sb = itr->second;
  268. map<int32, SkillBonusValue*>::iterator sbv_itr;
  269. for (sbv_itr = sb->skills.begin(); sbv_itr != sb->skills.end(); sbv_itr++) {
  270. SkillBonusValue* sbv = sbv_itr->second;
  271. if (sbv->skill_id == skill_id)
  272. new_val += (int16)sbv->value;
  273. }
  274. }
  275. return new_val;
  276. }
  277. EQ2Packet* PlayerSkillList::GetSkillPacket(int16 version){
  278. PacketStruct* packet = configReader.getStruct("WS_UpdateSkillBook", version);
  279. if(packet){
  280. if(packet_count < skills.size()){
  281. if(!orig_packet){
  282. int16 size = 21*skills.size()+8;
  283. xor_packet = new uchar[size];
  284. orig_packet = new uchar[size];
  285. memset(xor_packet, 0, size);
  286. memset(orig_packet, 0, size);
  287. }
  288. else{
  289. int16 size = 21*skills.size()+8;
  290. uchar* tmp = new uchar[size];
  291. memset(tmp, 0, size);
  292. memcpy(tmp, orig_packet, 21*packet_count+8);
  293. safe_delete_array(orig_packet);
  294. orig_packet = tmp;
  295. safe_delete_array(xor_packet);
  296. xor_packet = new uchar[size];
  297. }
  298. packet_count = skills.size();
  299. }
  300. packet->setArrayLengthByName("skill_count", skills.size());
  301. map<int32, Skill*>::iterator itr;
  302. Skill* skill = 0;
  303. int32 i=0;
  304. for(itr = skills.begin(); itr != skills.end(); itr++){
  305. skill = itr->second;
  306. if(skill){
  307. int16 skill_max_with_bonuses = CalculateSkillMaxValue(skill->skill_id, skill->max_val);
  308. int16 skill_with_bonuses = int(CalculateSkillValue(skill->skill_id, skill->current_val));
  309. if (skill->skill_id == 613995491) {
  310. int x_current = skill->current_val;
  311. int x_previous = skill->previous_val;
  312. int x_max = skill->max_val;
  313. int x_delta2 = skill_max_with_bonuses - skill->max_val;
  314. int xxx = 1;
  315. }
  316. packet->setArrayDataByName("skill_id", skill->skill_id, i);
  317. packet->setArrayDataByName("type", skill->skill_type, i);
  318. packet->setArrayDataByName("current_val", skill->current_val, i);
  319. packet->setArrayDataByName("base_val", skill->current_val, i);// skill->
  320. packet->setArrayDataByName("skill_delta", 0, i);// skill_with_bonuses- skill->current_val
  321. packet->setArrayDataByName("skill_delta2", skill_max_with_bonuses - skill->max_val, i);// skill_max_with_bonuses - skill->max_val, i);
  322. packet->setArrayDataByName("max_val", skill->max_val, i);
  323. packet->setArrayDataByName("display_minval", skill->display, i);
  324. packet->setArrayDataByName("display_maxval", skill->display, i);
  325. i++;
  326. }
  327. }
  328. EQ2Packet* ret = packet->serializeCountPacket(version, 1, orig_packet, xor_packet);
  329. //packet->PrintPacket();
  330. //DumpPacket(ret);
  331. safe_delete(packet);
  332. return ret;
  333. }
  334. return 0;
  335. }
  336. bool PlayerSkillList::CheckSkillIncrease(Skill* skill){
  337. if(!skill || skill->current_val >= skill->max_val)
  338. return false;
  339. // Assuming that skills will be used more at higher levels, increase chances are:
  340. // skill val of 1 ~ 20% chance, value of 100 ~ 10%, value of 400 ~ 4%
  341. int8 percent = (int8)(((float)((float)100/(float)(50 + skill->current_val)))*10);
  342. if(rand()%100 < percent){ // skill increase
  343. IncreaseSkill(skill, 1);
  344. return true;
  345. }
  346. else
  347. return false;
  348. }
  349. Skill* PlayerSkillList::GetSkillByName(const char* name){
  350. if(name_skill_map.size() == 0){
  351. map<int32, Skill*>::iterator itr;
  352. Skill* skill = 0;
  353. for(itr = skills.begin(); itr != skills.end(); itr++){
  354. skill = itr->second;
  355. name_skill_map[skill->name.data] = skill;
  356. }
  357. }
  358. if(name_skill_map.count(name) > 0)
  359. return name_skill_map[name];
  360. else
  361. return 0;
  362. }
  363. vector<Skill*>* PlayerSkillList::GetSaveNeededSkills(){
  364. vector<Skill*>* ret = new vector<Skill*>;
  365. map<int32, Skill*>::iterator itr;
  366. for(itr = skills.begin(); itr != skills.end(); itr++){
  367. if(itr->second->save_needed){
  368. ret->push_back(itr->second);
  369. itr->second->save_needed = false;
  370. }
  371. }
  372. return ret;
  373. }
  374. void PlayerSkillList::AddSkillUpdateNeeded(Skill* skill){
  375. MSkillUpdates.writelock(__FUNCTION__, __LINE__);
  376. skill_updates.push_back(skill);
  377. has_updates = true;
  378. MSkillUpdates.releasewritelock(__FUNCTION__, __LINE__);
  379. }
  380. vector<Skill*>* PlayerSkillList::GetSkillUpdates(){
  381. vector<Skill*>* ret = 0;
  382. vector<Skill*>::iterator itr;
  383. MSkillUpdates.writelock(__FUNCTION__, __LINE__);
  384. if(skill_updates.size() > 0){
  385. ret = new vector<Skill*>();
  386. ret->insert(ret->begin(), skill_updates.begin(), skill_updates.end());
  387. skill_updates.clear();
  388. }
  389. has_updates = false;
  390. MSkillUpdates.releasewritelock(__FUNCTION__, __LINE__);
  391. return ret;
  392. }
  393. bool PlayerSkillList::HasSkillUpdates(){
  394. return has_updates;
  395. }
  396. void PlayerSkillList::AddSkillBonus(int32 spell_id, int32 skill_id, float value) {
  397. if (value != 0) {
  398. SkillBonus* sb;
  399. if (skill_bonus_list.count(spell_id) == 0) {
  400. sb = new SkillBonus;
  401. sb->spell_id = spell_id;
  402. skill_bonus_list.Put(spell_id, sb);
  403. }
  404. else
  405. sb = skill_bonus_list.Get(spell_id);
  406. if (sb->skills[skill_id] == 0) {
  407. SkillBonusValue* sbv = new SkillBonusValue;
  408. sbv->skill_id = skill_id;
  409. sbv->value = value;
  410. sb->skills[skill_id] = sbv;
  411. }
  412. }
  413. }
  414. SkillBonus* PlayerSkillList::GetSkillBonus(int32 spell_id) {
  415. SkillBonus *ret = 0;
  416. if (skill_bonus_list.count(spell_id) > 0)
  417. ret = skill_bonus_list.Get(spell_id);
  418. return ret;
  419. }
  420. void PlayerSkillList::RemoveSkillBonus(int32 spell_id) {
  421. if (skill_bonus_list.count(spell_id) > 0) {
  422. SkillBonus* sb = skill_bonus_list.Get(spell_id);
  423. skill_bonus_list.erase(spell_id);
  424. map<int32, SkillBonusValue*>::iterator itr;
  425. for (itr = sb->skills.begin(); itr != sb->skills.end(); itr++)
  426. safe_delete(itr->second);
  427. safe_delete(sb);
  428. }
  429. }
  430. int Skill::CheckDisarmSkill(int16 targetLevel, int8 chest_difficulty)
  431. {
  432. if (chest_difficulty < 2) // no triggers on this chest type
  433. return 1;
  434. if (targetLevel < 1)
  435. targetLevel = 1;
  436. int chest_diff_result = targetLevel * chest_difficulty;
  437. float base_difficulty = 15.0f;
  438. float fail_threshold = 10.0f;
  439. float chance = ((100.0f - base_difficulty) * ((float)current_val / (float)chest_diff_result));
  440. if (chance > (100.0f - base_difficulty))
  441. {
  442. chance = 100.0f - base_difficulty;
  443. }
  444. float d100 = (float)MakeRandomFloat(0, 100);
  445. if (d100 <= chance)
  446. return 1;
  447. else
  448. {
  449. if (d100 > (chance + fail_threshold))
  450. return -1;
  451. }
  452. return 0;
  453. }