SergiuAndreiM

acce.cpp

Jul 10th, 2017
267
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 28.78 KB | None | 0 0
  1. #define _acce_cpp_
  2. #include "stdafx.h"
  3. #include "config.h"
  4. #include "constants.h"
  5. #include "utils.h"
  6. #include "log.h"
  7. #include "char.h"
  8. #include "dev_log.h"
  9. #include "locale_service.h"
  10. #include "item.h"
  11. #include "item_manager.h"
  12. #include <stdlib.h>
  13. #include <sstream>
  14. #define RETURN_IF_ACCE_IS_NOT_OPENED(ch) if (!(ch)->IsAcceOpen()) return
  15.  
  16. extern int test_server;
  17. static std::vector<ACCE_DATA*>  s_acce_proto;
  18. static bool s_isInitializedAcceMaterialInformation = false;
  19.  
  20. enum EAcceResultCategory
  21. {
  22.     ACCE_CATEGORY_POTION,
  23.     ACCE_CATEGORY_WEAPON,
  24.     ACCE_CATEGORY_ARMOR,
  25.     ACCE_CATEGORY_ACCESSORY,
  26.     ACCE_CATEGORY_ETC,
  27. };
  28.  
  29. typedef std::vector<ACCE_VALUE> TAcceValueVector;
  30.  
  31. struct SAcceMaterialInfo
  32. {
  33.     SAcceMaterialInfo()
  34.     {
  35.         bHaveComplicateMaterial = false;
  36.     };
  37.    
  38.     ACCE_VALUE          reward;
  39.     TAcceValueVector    material;
  40.     DWORD               gold;
  41.     TAcceValueVector    complicateMaterial;
  42.    
  43.     std::string         infoText;
  44.     bool                bHaveComplicateMaterial;
  45. };
  46.  
  47. struct SItemNameAndLevel
  48. {
  49.     SItemNameAndLevel() { level = 0; }
  50.    
  51.     std::string     name;
  52.     int             level;
  53. };
  54.  
  55. typedef std::vector<SAcceMaterialInfo>                              TAcceResultList;
  56. typedef boost::unordered_map<DWORD, TAcceResultList>                TAcceMapByNPC;
  57. typedef boost::unordered_map<DWORD, std::string>                    TAcceResultInfoTextByNPC;
  58.  
  59. TAcceMapByNPC acce_info_map;
  60. TAcceResultInfoTextByNPC acce_result_info_map_by_npc;
  61.  
  62. class CAcceMaterialInfoHelper
  63. {
  64. public:
  65. public:
  66. };
  67.  
  68. static bool FN_check_item_count(LPITEM *items, DWORD item_vnum, int need_count)
  69. {
  70.     int count = 0;
  71.     for (int i=0; i<ACCE_MAX_NUM; ++i)
  72.     {
  73.         if (NULL == items[i])
  74.             continue;
  75.        
  76.         if (item_vnum==items[i]->GetVnum())
  77.         {
  78.             count += items[i]->GetCount();
  79.         }
  80.     }
  81.    
  82.     return (count>=need_count);
  83. }
  84.  
  85. static void FN_remove_material(LPITEM *items, DWORD item_vnum, int need_count, int result)
  86. {
  87.     int     count = 0;
  88.     (void)count;
  89.     LPITEM  item = NULL;
  90.    
  91.     item = items[1];
  92.     if (item != NULL)
  93.     {
  94.         item->SetCount(0);
  95.         items[1] = NULL;
  96.     }
  97.    
  98.     if (result == 1)
  99.     {
  100.         item = items[0];
  101.         if (item != NULL)
  102.         {
  103.             item->SetCount(0);
  104.             items[0] = NULL;
  105.         }
  106.     }
  107. }
  108.  
  109. static ACCE_DATA* FN_find_acce(LPITEM *items, WORD npc_vnum)
  110. {
  111.     DWORD   i, end_index;
  112.    
  113.     if (npc_vnum == 0)
  114.         return NULL;
  115.    
  116.     end_index = s_acce_proto.size();
  117.     for (i = 0; i < end_index; ++i)
  118.     {
  119.         if (s_acce_proto[i]->can_make_item(items, npc_vnum))
  120.             return s_acce_proto[i];
  121.     }
  122.    
  123.     return NULL;
  124. }
  125.  
  126. static bool FN_check_valid_npc(WORD vnum)
  127. {
  128.     for (std::vector<ACCE_DATA*>::iterator iter = s_acce_proto.begin(); iter != s_acce_proto.end(); iter++)
  129.     {
  130.         if (std::find((*iter)->npc_vnum.begin(), (*iter)->npc_vnum.end(), vnum) != (*iter)->npc_vnum.end())
  131.             return true;
  132.     }
  133.    
  134.     return false;
  135. }
  136.  
  137. static bool FN_check_acce_data(ACCE_DATA *acce_data)
  138. {
  139.     DWORD   i = 0;
  140.     DWORD   end_index = 0;
  141.    
  142.     end_index = acce_data->npc_vnum.size();
  143.     for (i=0; i<end_index; ++i)
  144.     {
  145.         if ( acce_data->npc_vnum[i] == 0 )
  146.             return false;
  147.     }
  148.    
  149.     end_index = acce_data->item.size();
  150.     for (i=0; i<end_index; ++i)
  151.     {
  152.         if ( acce_data->item[i].vnum == 0 )
  153.             return false;
  154.        
  155.         if ( acce_data->item[i].count == 0 )
  156.             return false;
  157.     }
  158.    
  159.     end_index = acce_data->reward.size();
  160.     for (i=0; i<end_index; ++i)
  161.     {
  162.         if (acce_data->reward[i].vnum == 0)
  163.             return false;
  164.        
  165.         if (acce_data->reward[i].count == 0)
  166.             return false;
  167.     }
  168.    
  169.     return true;
  170. }
  171.  
  172. ACCE_DATA::ACCE_DATA()
  173. {
  174.     this->percent = 0;
  175.     this->gold = 0;
  176.     this->abs_chance_min = 0;
  177.     this->abs_chance_max = 0;
  178. }
  179.  
  180. bool ACCE_DATA::can_make_item(LPITEM *items, WORD npc_vnum)
  181. {
  182.     DWORD   i, end_index;
  183.     DWORD   need_vnum;
  184.     int     need_count;
  185.     int     found_npc = false;
  186.    
  187.     end_index = this->npc_vnum.size();
  188.     for (i=0; i<end_index; ++i)
  189.     {
  190.         if (npc_vnum == this->npc_vnum[i])
  191.             found_npc = true;
  192.     }
  193.    
  194.     if (false == found_npc)
  195.         return false;
  196.    
  197.     end_index = this->item.size();
  198.     for (i=0; i<end_index; ++i)
  199.     {
  200.         need_vnum = this->item[i].vnum;
  201.         need_count = this->item[i].count;
  202.        
  203.         if (false == FN_check_item_count(items, need_vnum, need_count))
  204.             return false;
  205.     }
  206.    
  207.     return true;
  208. }
  209.  
  210. ACCE_VALUE* ACCE_DATA::reward_value()
  211. {
  212.     int     end_index = 0;
  213.     DWORD   reward_index = 0;
  214.    
  215.     end_index = this->reward.size();
  216.     reward_index = number(0, end_index);
  217.     reward_index = number(0, end_index-1);
  218.     return &this->reward[reward_index];
  219. }
  220.  
  221. void ACCE_DATA::remove_material(LPCHARACTER ch, int result)
  222. {
  223.     DWORD   i, end_index;
  224.     DWORD   need_vnum;
  225.     int     need_count;
  226.     LPITEM  *items = ch->GetAcceItem();
  227.    
  228.     end_index = this->item.size();
  229.     for (i = 0; i < ACCE_MAX_NUM; ++i)
  230.     {
  231.         need_vnum = this->item[i].vnum;
  232.         need_count = this->item[i].count;
  233.        
  234.         FN_remove_material(items, need_vnum, need_count, result);
  235.     }
  236. }
  237.  
  238. void Acce_clean_item(LPCHARACTER ch)
  239. {
  240.     LPITEM  *acce_item;
  241.    
  242.     acce_item = ch->GetAcceItem();
  243.     for (int i=0; i<ACCE_MAX_NUM; ++i)
  244.     {
  245.         if (acce_item[i] == NULL)
  246.             continue;
  247.        
  248.         if (acce_item[i]->GetType() == ITEM_COSTUME && acce_item[i]->GetSubType() == COSTUME_ACCE && acce_item[i]->GetType() != ITEM_WEAPON && acce_item[i]->GetType() != ITEM_ARMOR)
  249.             acce_item[i]->SetSocket(0, 0);
  250.        
  251.         acce_item[i] = NULL;
  252.     }
  253. }
  254.  
  255. void Acce_open(LPCHARACTER ch)
  256. {
  257.     if (false == s_isInitializedAcceMaterialInformation)
  258.     {
  259.         Acce_InformationInitialize();
  260.     }
  261.    
  262.     if (NULL == ch)
  263.         return;
  264.    
  265.     LPCHARACTER npc;
  266.     npc = ch->GetQuestNPC();
  267.     if (NULL == npc)
  268.     {
  269.         if (test_server)
  270.             dev_log(LOG_DEB0, "acce_npc is NULL");
  271.        
  272.         return;
  273.     }
  274.    
  275.     if (FN_check_valid_npc(npc->GetRaceNum()) == false)
  276.     {
  277.         if ( test_server == true )
  278.         {
  279.             dev_log(LOG_DEB0, "Acce not valid NPC");
  280.         }
  281.        
  282.         return;
  283.     }
  284.    
  285.     if (ch->IsAcceOpen())
  286.     {
  287.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Fereastra de creare a esarfelor este deja deschisa."));
  288.         return;
  289.     }
  290.    
  291.     if ( ch->GetExchange() || ch->GetMyShop() || ch->GetShopOwner() || ch->IsOpenSafebox() || ch->IsAcceOpen() )
  292.     {
  293.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("다른 거래중(창고,교환,상점)에는 사용할 수 없습니다."));
  294.         return;
  295.     }
  296.    
  297.     long distance = DISTANCE_APPROX(ch->GetX() - npc->GetX(), ch->GetY() - npc->GetY());
  298.     if (distance >= ACCE_MAX_DISTANCE)
  299.     {
  300.         sys_log(1, "Acce: TOO_FAR: %s distance %d", ch->GetName(), distance);
  301.         return;
  302.     }
  303.    
  304.     Acce_clean_item(ch);
  305.     ch->SetAcceNpc(npc);
  306.     ch->ChatPacket(CHAT_TYPE_COMMAND, "Acce open %d", npc->GetRaceNum());
  307. }
  308.  
  309. void Acce_absorption_open(LPCHARACTER ch)
  310. {
  311.     if (false == s_isInitializedAcceMaterialInformation)
  312.     {
  313.         Acce_InformationInitialize();
  314.     }
  315.    
  316.     if (NULL == ch)
  317.         return;
  318.    
  319.     LPCHARACTER npc;
  320.     npc = ch->GetQuestNPC();
  321.     if (NULL == npc)
  322.     {
  323.         if (test_server)
  324.             dev_log(LOG_DEB0, "acce_npc is NULL");
  325.        
  326.         return;
  327.     }
  328.    
  329.     if (FN_check_valid_npc(npc->GetRaceNum()) == false)
  330.     {
  331.         if ( test_server == true )
  332.         {
  333.             dev_log(LOG_DEB0, "Acce not valid NPC");
  334.         }
  335.        
  336.         return;
  337.     }
  338.    
  339.     if (ch->IsAcceOpen())
  340.     {
  341.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Fereastra de creare a esarfelor este deja deschisa."));
  342.         return;
  343.     }
  344.    
  345.     if ( ch->GetExchange() || ch->GetMyShop() || ch->GetShopOwner() || ch->IsOpenSafebox() || ch->IsAcceOpen() )
  346.     {
  347.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("다른 거래중(창고,교환,상점)에는 사용할 수 없습니다."));
  348.         return;
  349.     }
  350.    
  351.     long distance = DISTANCE_APPROX(ch->GetX() - npc->GetX(), ch->GetY() - npc->GetY());
  352.     if (distance >= ACCE_MAX_DISTANCE)
  353.     {
  354.         sys_log(1, "Acce: TOO_FAR: %s distance %d", ch->GetName(), distance);
  355.         return;
  356.     }
  357.    
  358.     Acce_clean_item(ch);
  359.     ch->SetAcceNpc(npc);
  360.     ch->ChatPacket(CHAT_TYPE_COMMAND, "Acce open_absorption %d", npc->GetRaceNum());
  361. }
  362.  
  363. void Acce_close(LPCHARACTER ch)
  364. {
  365.     RETURN_IF_ACCE_IS_NOT_OPENED(ch);
  366.     Acce_clean_item(ch);
  367.     ch->SetAcceNpc(NULL);
  368.     ch->ChatPacket(CHAT_TYPE_COMMAND, "Acce close");
  369.     dev_log(LOG_DEB0, "<Acce> close (%s)", ch->GetName());
  370. }
  371.  
  372. void Acce_init()
  373. {
  374.     ACCE_DATA * p_acce = NULL;
  375.     std::vector<ACCE_DATA*>::iterator iter;
  376.     char file_name[256+1];
  377.    
  378.     snprintf(file_name, sizeof(file_name), "%s/acce.txt", LocaleService_GetBasePath().c_str());
  379.     sys_log(0, "Acce_Init %s", file_name);
  380.     for (iter = s_acce_proto.begin(); iter!=s_acce_proto.end(); iter++)
  381.     {
  382.         p_acce = *iter;
  383.         M2_DELETE(p_acce);
  384.     }
  385.    
  386.     s_acce_proto.clear();
  387.     if (false == Acce_load(file_name))
  388.         sys_err("Acce_Init failed");
  389. }
  390.  
  391. bool Acce_load(const char *file)
  392. {
  393.     FILE    *fp;
  394.     char    one_line[256];
  395.     int     value1, value2;
  396.     const char  *delim = " \t\r\n";
  397.     char    *v, *token_string;
  398.     ACCE_DATA   *acce_data = NULL;
  399.     ACCE_VALUE  acce_value = {0, 0};
  400.    
  401.     if (0 == file || 0 == file[0])
  402.         return false;
  403.    
  404.     if ((fp = fopen(file, "r")) == 0)
  405.         return false;
  406.    
  407.     while (fgets(one_line, 256, fp))
  408.     {
  409.         value1 = value2 = 0;
  410.         if (one_line[0] == '#')
  411.             continue;
  412.        
  413.         token_string = strtok(one_line, delim);
  414.         if (NULL == token_string)
  415.             continue;
  416.        
  417.         if ((v = strtok(NULL, delim)))
  418.             str_to_number(value1, v);
  419.        
  420.         if ((v = strtok(NULL, delim)))
  421.             str_to_number(value2, v);
  422.        
  423.         TOKEN("section")
  424.         {
  425.             acce_data = M2_NEW ACCE_DATA;
  426.         }
  427.         else TOKEN("npc")
  428.         {
  429.             acce_data->npc_vnum.push_back((WORD)value1);
  430.         }
  431.         else TOKEN("item")
  432.         {
  433.             acce_value.vnum = value1;
  434.             acce_value.count = value2;
  435.             acce_data->item.push_back(acce_value);
  436.         }
  437.         else TOKEN("reward")
  438.         {
  439.             acce_value.vnum = value1;
  440.             acce_value.count = value2;
  441.             acce_data->reward.push_back(acce_value);
  442.         }
  443.         else TOKEN("abs_chance_min")
  444.         {
  445.             acce_data->abs_chance_min = value1;
  446.         }
  447.         else TOKEN("abs_chance_max")
  448.         {
  449.             acce_data->abs_chance_max = value1;
  450.         }
  451.         else TOKEN("percent")
  452.         {
  453.             acce_data->percent = value1;
  454.         }
  455.         else TOKEN("gold")
  456.         {
  457.             acce_data->gold = value1;
  458.         }
  459.         else TOKEN("end")
  460.         {
  461.             if (false == FN_check_acce_data(acce_data))
  462.             {
  463.                 dev_log(LOG_DEB0, "something wrong");
  464.                 M2_DELETE(acce_data);
  465.                 continue;
  466.             }
  467.            
  468.             s_acce_proto.push_back(acce_data);
  469.         }
  470.     }
  471.    
  472.     fclose(fp);
  473.     return true;
  474. }
  475.  
  476. static void FN_acce_print(ACCE_DATA *data, DWORD index)
  477. {
  478.     DWORD   i;
  479.     dev_log(LOG_DEB0, "--------------------------------");
  480.     dev_log(LOG_DEB0, "ACCE_DATA[%d]", index);
  481.     for (i = 0; i < data->npc_vnum.size(); ++i)
  482.     {
  483.         dev_log(LOG_DEB0, "\tNPC_VNUM[%d] = %d", i, data->npc_vnum[i]);
  484.     }
  485.     for (i = 0; i < data->item.size(); ++i)
  486.     {
  487.         dev_log(LOG_DEB0, "\tITEM[%d]   = (%d, %d)", i, data->item[i].vnum, data->item[i].count);
  488.     }
  489.     for (i = 0; i < data->reward.size(); ++i)
  490.     {
  491.         dev_log(LOG_DEB0, "\tREWARD[%d] = (%d, %d)", i, data->reward[i].vnum, data->reward[i].count);
  492.     }
  493.    
  494.     dev_log(LOG_DEB0, "\tPERCENT = %d", data->percent);
  495.     dev_log(LOG_DEB0, "--------------------------------");
  496. }
  497.  
  498. void Acce_print ()
  499. {
  500.     for (DWORD i=0; i<s_acce_proto.size(); ++i)
  501.     {
  502.         FN_acce_print(s_acce_proto[i], i);
  503.     }
  504. }
  505.  
  506. static bool FN_update_acce_status(LPCHARACTER ch)
  507. {
  508.     if (NULL == ch)
  509.         return false;
  510.    
  511.     if (!ch->IsAcceOpen())
  512.         return false;
  513.    
  514.     LPCHARACTER npc = ch->GetQuestNPC();
  515.     if (NULL == npc)
  516.         return false;
  517.    
  518.     ACCE_DATA* Acce = FN_find_acce(ch->GetAcceItem(), npc->GetRaceNum());
  519.     if (NULL == Acce)
  520.     {
  521.         ch->ChatPacket(CHAT_TYPE_COMMAND, "Acce info 0 0 0 0 0");
  522.         return false;
  523.     }
  524.    
  525.     ch->ChatPacket(CHAT_TYPE_COMMAND, "Acce info %d %d %d %d %d", Acce->gold, 0, 0, Acce->reward[0], Acce->reward[1]);
  526.     return true;
  527. }
  528.  
  529. bool Acce_make(LPCHARACTER ch)
  530. {
  531.     LPCHARACTER npc;
  532.     int         percent_number = 0;
  533.     ACCE_DATA   *acce_proto;
  534.     LPITEM  *items;
  535.     LPITEM  new_item;
  536.     int reward_vnum = 0;
  537.    
  538.     if (!(ch)->IsAcceOpen())
  539.     {
  540.         (ch)->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Fereastra de creare a esarfelor este deja deschisa."));
  541.         return false;
  542.     }
  543.    
  544.     npc = ch->GetQuestNPC();
  545.     if (NULL == npc)
  546.     {
  547.         return false;
  548.     }
  549.    
  550.     items = ch->GetAcceItem();
  551.     if (items[0] == NULL || items[1] == NULL || items[0]->GetValue(0) != items[1]->GetValue(0))
  552.     {
  553.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Pune itemele in fereastra."));
  554.         return false;
  555.     }
  556.    
  557.     acce_proto = FN_find_acce(items, npc->GetRaceNum());
  558.     if (NULL == acce_proto)
  559.     {
  560.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("제조 재료가 부족합니다"));
  561.         return false;
  562.     }
  563.    
  564.     if (ch->GetGold() < acce_proto->gold)
  565.     {
  566.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("돈이 부족하거나 아이템이 제자리에 없습니다."));
  567.         return false;
  568.     }
  569.    
  570.     reward_vnum = items[0]->GetValue(1);
  571.     if (reward_vnum == 0)
  572.     {
  573.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Pune itemele in fereastra."));
  574.         return false;
  575.     }
  576.        
  577.     ACCE_VALUE  *reward_value = acce_proto->reward_value();
  578.     if (0 < acce_proto->gold)
  579.         ch->PointChange(POINT_GOLD, -(acce_proto->gold), false);
  580.    
  581.     percent_number = number(1, 100);
  582.     if (percent_number <= acce_proto->percent)
  583.     {
  584.         acce_proto->remove_material(ch, 1);
  585.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Success!"));
  586.         ch->ChatPacket(CHAT_TYPE_COMMAND, "acce success %d %d", reward_vnum, reward_value->count);
  587.         ch->EffectPacket(SE_ACCE_SUCCEDED_1);
  588.         int abs_chance = 0;
  589.         if (acce_proto->abs_chance_min < 1 || acce_proto->abs_chance_max < 1)
  590.         {
  591.             abs_chance = 1;
  592.         }
  593.         else if (acce_proto->abs_chance_min > acce_proto->abs_chance_max)
  594.         {
  595.             abs_chance = 1;
  596.         }
  597.         else if (acce_proto->abs_chance_min == acce_proto->abs_chance_max)
  598.         {
  599.             abs_chance = acce_proto->abs_chance_min;
  600.         }
  601.         else
  602.         {
  603.             abs_chance = number(acce_proto->abs_chance_min, acce_proto->abs_chance_max);
  604.         }
  605.        
  606.         new_item = ch->AutoGiveAcce(reward_vnum, reward_value->count, abs_chance);
  607.         LogManager::instance().AcceLog(ch->GetPlayerID(), ch->GetX(), ch->GetY(), reward_vnum, new_item->GetID(), reward_value->count, abs_chance, 1);
  608.         return true;
  609.     }
  610.     else
  611.     {
  612.         acce_proto->remove_material(ch, 0);
  613.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Failed!"));
  614.         ch->ChatPacket(CHAT_TYPE_COMMAND, "Acce fail");
  615.         LogManager::instance().AcceLog(ch->GetPlayerID(), ch->GetX(), ch->GetY(), reward_vnum, 0, 0, 0, 0);
  616.         return false;
  617.     }
  618.    
  619.     return false;
  620. }
  621.  
  622. bool Acce_absorption_make(LPCHARACTER ch)
  623. {
  624.     LPCHARACTER npc;
  625.     LPITEM  *items;
  626.     int absorption_chance = 0;
  627.     BYTE    type1 = 0, type2 = 0, type3 = 0, type4 = 0, type5 = 0, type6 = 0, type7 = 0, type8 = 0, type9 = 0, type10 = 0, type11 = 0, type12 = 0, type13 = 0, type14 = 0, type15 = 0;
  628.     float   value1 = 0, value2 = 0, value3 = 0, value4 = 0, value5 = 0, value6 = 0, value7 = 0, value8 = 0, value9 = 0, value10 = 0, value11 = 0, value12 = 0, value13 = 0, value14 = 0, value15 = 0;
  629.    
  630.     if (!(ch)->IsAcceOpen())
  631.     {
  632.         (ch)->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Fereastra de creare a esarfelor nu este deschisa."));
  633.         return false;
  634.     }
  635.    
  636.     npc = ch->GetQuestNPC();
  637.     if (NULL == npc)
  638.     {
  639.         return false;
  640.     }
  641.    
  642.     items = ch->GetAcceItem();
  643.     if (items[0] == NULL || items[1] == NULL)
  644.     {
  645.         (ch)->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Pune itemele in fereastra."));
  646.         return false;
  647.     }
  648.     else if (items[1]->GetType() != ITEM_WEAPON && items[1]->GetType() != ITEM_ARMOR)
  649.     {
  650.         (ch)->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Poti absorbi bonusurile doar de pe arme si armuri."));
  651.         return false;
  652.     }
  653.     else if (items[0]->GetAcceAttributeCount() > 0)
  654.     {
  655.         (ch)->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You must remove the bonus from sash before continue."));
  656.         return false;
  657.     }  
  658.    
  659.     absorption_chance = items[0]->GetSocket(1);
  660.     type1 = items[1]->GetAttributeType(0);
  661.     value1 = items[1]->GetAttributeValue(0) * absorption_chance / 100;
  662.     type2 = items[1]->GetAttributeType(1);
  663.     value2 = items[1]->GetAttributeValue(1) * absorption_chance / 100;
  664.     type3 = items[1]->GetAttributeType(2);
  665.     value3 = items[1]->GetAttributeValue(2) * absorption_chance / 100;
  666.     type4 = items[1]->GetAttributeType(3);
  667.     value4 = items[1]->GetAttributeValue(3) * absorption_chance / 100;
  668.     type5 = items[1]->GetAttributeType(4);
  669.     value5 = items[1]->GetAttributeValue(4) * absorption_chance / 100;
  670.     type6 = items[1]->GetAttributeType(5);
  671.     value6 = items[1]->GetAttributeValue(5) * absorption_chance / 100;
  672.     type7 = items[1]->GetAttributeType(6);
  673.     value7 = items[1]->GetAttributeValue(6) * absorption_chance / 100;
  674.    
  675.     if (items[1]->GetType() == ITEM_ARMOR)
  676.     {
  677.         type8 = 54;
  678.         value8 = (items[1]->GetValue(1) + items[1]->GetValue(5)) * absorption_chance / 100;
  679.     }
  680.     else
  681.     {
  682.         type8 = 0;
  683.         value8 = 0;
  684.     }
  685.    
  686.     if (items[1]->GetType() == ITEM_WEAPON)
  687.     {
  688.         type9 = 53;
  689.         value9 = (items[1]->GetValue(3) + items[1]->GetValue(5)) * absorption_chance / 100;
  690.         type10 = 53;
  691.         value10 = (items[1]->GetValue(4) + items[1]->GetValue(5)) * absorption_chance / 100;
  692.         value11 = (items[1]->GetValue(1) + items[1]->GetValue(5)) * absorption_chance / 100;
  693.         value12 = (items[1]->GetValue(2) + items[1]->GetValue(5)) * absorption_chance / 100;
  694.         if (items[1]->GetValue(1) <= 0)
  695.         {
  696.             type11 = 0;
  697.             value11 = 0;
  698.         }
  699.         else
  700.         {
  701.             type11 = 55;
  702.         }
  703.        
  704.         if (items[1]->GetValue(2) <= 0)
  705.         {
  706.             type12 = 0;
  707.             value12 = 0;
  708.         }
  709.         else
  710.         {
  711.             type12 = 55;
  712.         }
  713.     }
  714.     else
  715.     {
  716.         type9 = 0;
  717.         value9 = 0;
  718.         type10 = 0;
  719.         value10 = 0;
  720.         type11 = 0;
  721.         value11 = 0;
  722.         type12 = 0;
  723.         value12 = 0;
  724.     }
  725.    
  726.     type13 = items[1]->GetNewAttributeType(0);
  727.     value13 = items[1]->GetNewAttributeValue(0) * absorption_chance / 100;
  728.     type14 = items[1]->GetNewAttributeType(1);
  729.     value14 = items[1]->GetNewAttributeValue(1) * absorption_chance / 100;
  730.     type15 = items[1]->GetNewAttributeType(2);
  731.     value15 = items[1]->GetNewAttributeValue(2) * absorption_chance / 100;
  732.    
  733.     int value1_final = (value1 <= 0) ? (int)(1) : (int)(value1);
  734.     int value2_final = (value2 <= 0) ? (int)(1) : (int)(value2);
  735.     int value3_final = (value3 <= 0) ? (int)(1) : (int)(value3);
  736.     int value4_final = (value4 <= 0) ? (int)(1) : (int)(value4);
  737.     int value5_final = (value5 <= 0) ? (int)(1) : (int)(value5);
  738.     int value6_final = (value6 <= 0) ? (int)(1) : (int)(value6);
  739.     int value7_final = (value7 <= 0) ? (int)(1) : (int)(value7);
  740.     int value8_final = (value8 <= 0) ? (int)(1) : (int)(value8);
  741.     int value9_final = (value10 - value9 <= 0) ? (int)(1) : (int)(value10 - value9);
  742.     int value10_final = (value10 <= 0) ? (int)(1) : (int)(value10);
  743.     int value11_final = (value11 - value11 <= 0) ? (int)(1) : (int)(value12 - value11);
  744.     int value12_final = (value12 <= 0) ? (int)(1) : (int)(value12);
  745.     int value13_final = (value13 <= 0) ? (int)(1) : (int)(value13);
  746.     int value14_final = (value14 <= 0) ? (int)(1) : (int)(value14);
  747.     int value15_final = (value15 <= 0) ? (int)(1) : (int)(value15);
  748.    
  749.     items[0]->SetForceAttribute(0, type1, value1_final);
  750.     items[0]->SetForceAttribute(1, type2, value2_final);
  751.     items[0]->SetForceAttribute(2, type3, value3_final);
  752.     items[0]->SetForceAttribute(3, type4, value4_final);
  753.     items[0]->SetForceAttribute(4, type5, value5_final);
  754.     items[0]->SetForceAttribute(5, type6, value6_final);
  755.     items[0]->SetForceAttribute(6, type7, value7_final);
  756.     items[0]->SetForceAttribute(7, type8, value8_final);
  757.     items[0]->SetForceAttribute(8, type9, value9_final);
  758.     items[0]->SetForceAttribute(9, type10, value10_final);
  759.     items[0]->SetForceAttribute(10, type11, value11_final);
  760.     items[0]->SetForceAttribute(11, type12, value12_final);
  761.     items[0]->SetForceAttribute(12, type13, value13_final);
  762.     items[0]->SetForceAttribute(13, type14, value14_final);
  763.     items[0]->SetForceAttribute(14, type15, value15_final);
  764.    
  765.     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Absorbtia a avut succes."));
  766.     ch->ChatPacket(CHAT_TYPE_COMMAND, "acce success_absorption");
  767.    
  768.     items[1]->SetCount(0);
  769.     items[1] = NULL;
  770.     return true;
  771. }
  772.  
  773. void Acce_show_list(LPCHARACTER ch)
  774. {
  775.     LPITEM  *acce_item;
  776.     LPITEM  item;
  777.    
  778.     RETURN_IF_ACCE_IS_NOT_OPENED(ch);
  779.    
  780.     acce_item = ch->GetAcceItem();
  781.     for (int i=0; i<ACCE_MAX_NUM; ++i)
  782.     {
  783.         item = acce_item[i];
  784.         if (item == NULL)
  785.             continue;
  786.        
  787.         ch->ChatPacket(CHAT_TYPE_INFO, "Acce[%d]: inventory[%d]: %s", i, item->GetCell(), item->GetName());
  788.     }
  789. }
  790.  
  791. void Acce_add_item(LPCHARACTER ch, int acce_index, int inven_index)
  792. {
  793.     LPITEM  item;
  794.     LPITEM  *acce_item;
  795.    
  796.     RETURN_IF_ACCE_IS_NOT_OPENED(ch);
  797.    
  798.     if (inven_index < 0 || INVENTORY_MAX_NUM <= inven_index)
  799.         return;
  800.    
  801.     if (acce_index<0 || ACCE_MAX_NUM <= acce_index)
  802.         return;
  803.    
  804.     item = ch->GetInventoryItem(inven_index);
  805.     if (item == NULL)
  806.         return;
  807.    
  808.     if (item->GetType() == ITEM_COSTUME && item->GetSubType() == COSTUME_ACCE && item->GetType() != ITEM_WEAPON && item->GetType() != ITEM_ARMOR)
  809.         item->SetSocket(0, 1);
  810.    
  811.     acce_item = ch->GetAcceItem();
  812.     for (int i=0; i<ACCE_MAX_NUM; ++i)
  813.     {
  814.         if (item==acce_item[i])
  815.         {
  816.             acce_item[i] = NULL;
  817.             break;
  818.         }
  819.     }
  820.    
  821.     acce_item[acce_index] = item;
  822.     if (acce_index == 1)
  823.     {
  824.         if (item->GetType() == ITEM_WEAPON || item->GetType() == ITEM_ARMOR)
  825.         {
  826.             ch->ChatPacket(CHAT_TYPE_COMMAND, "AcceAbsMessage");
  827.         }
  828.         else
  829.         {
  830.             ch->ChatPacket(CHAT_TYPE_COMMAND, "AcceMessage");
  831.         }
  832.     }
  833.    
  834.     if (test_server)
  835.         ch->ChatPacket(CHAT_TYPE_INFO, "Acce[%d]: inventory[%d]: %s added", acce_index, inven_index, item->GetName());
  836.    
  837.     if (acce_index == 0)
  838.     {
  839.         FN_update_acce_status(ch);
  840.     }
  841.     return;
  842. }
  843.  
  844. void Acce_delete_item(LPCHARACTER ch, int acce_index)
  845. {
  846.     LPITEM  item;
  847.     LPITEM  *acce_item;
  848.    
  849.     RETURN_IF_ACCE_IS_NOT_OPENED(ch);
  850.     if (acce_index < 0 || ACCE_MAX_NUM <= acce_index)
  851.         return;
  852.    
  853.     acce_item = ch->GetAcceItem();
  854.     if (acce_item[acce_index] == NULL)
  855.         return;
  856.    
  857.     item = acce_item[acce_index];
  858.     if (item->GetType() == ITEM_COSTUME && item->GetSubType() == COSTUME_ACCE && item->GetType() != ITEM_WEAPON && item->GetType() != ITEM_ARMOR)
  859.         item->SetSocket(0, 0);
  860.    
  861.     acce_item[acce_index] = NULL;
  862.     if (test_server)
  863.         ch->ChatPacket(CHAT_TYPE_INFO, "Acce[%d]: Acce[%d]: %s deleted", acce_index, item->GetCell(), item->GetName());
  864.    
  865.     FN_update_acce_status(ch);
  866.     return;
  867. }
  868.  
  869. SItemNameAndLevel SplitItemNameAndLevelFromHName(const std::string& name)
  870. {
  871.     int level = 0;
  872.     SItemNameAndLevel info;
  873.     info.name = name;
  874.    
  875.     size_t pos = name.find("+");
  876.     if (std::string::npos != pos)
  877.     {
  878.         const std::string levelStr = name.substr(pos + 1, name.size() - pos - 1);
  879.         str_to_number(level, levelStr.c_str());
  880.  
  881.         info.name = name.substr(0, pos);
  882.     }
  883.    
  884.     info.level = level;
  885.     return info;
  886. };
  887.  
  888. bool FIsEqualAcceValue(const ACCE_VALUE& a, const ACCE_VALUE& b)
  889. {
  890.     return (a.vnum == b.vnum) && (a.count == b.count);
  891. }
  892.  
  893. bool FIsLessAcceValue(const ACCE_VALUE& a, const ACCE_VALUE& b)
  894. {
  895.     return a.vnum < b.vnum;
  896. }
  897.  
  898. void Acce_MakeAcceInformationText()
  899. {
  900.     for (TAcceMapByNPC::iterator iter = acce_info_map.begin(); acce_info_map.end() != iter; ++iter)
  901.     {
  902.         TAcceResultList& resultList = iter->second;
  903.         for (TAcceResultList::iterator resultIter = resultList.begin(); resultList.end() != resultIter; ++resultIter)
  904.         {
  905.             SAcceMaterialInfo& materialInfo = *resultIter;
  906.             std::string& infoText = materialInfo.infoText;
  907.             if (0 < materialInfo.complicateMaterial.size())
  908.             {
  909.                 std::sort(materialInfo.complicateMaterial.begin(), materialInfo.complicateMaterial.end(), FIsLessAcceValue);
  910.                 std::sort(materialInfo.material.begin(), materialInfo.material.end(), FIsLessAcceValue);
  911.                 for (TAcceValueVector::iterator iter = materialInfo.complicateMaterial.begin(); materialInfo.complicateMaterial.end() != iter; ++iter)
  912.                 {
  913.                     for (TAcceValueVector::iterator targetIter = materialInfo.material.begin(); materialInfo.material.end() != targetIter; ++targetIter)
  914.                     {
  915.                         if (*targetIter == *iter)
  916.                         {
  917.                             targetIter = materialInfo.material.erase(targetIter);
  918.                         }
  919.                     }
  920.                 }
  921.                
  922.                 for (TAcceValueVector::iterator iter = materialInfo.complicateMaterial.begin(); materialInfo.complicateMaterial.end() != iter; ++iter)
  923.                 {
  924.                     char tempBuffer[128];
  925.                     sprintf(tempBuffer, "%d,%d|", iter->vnum, iter->count);
  926.                    
  927.                     infoText += std::string(tempBuffer);
  928.                 }
  929.                
  930.                 infoText.erase(infoText.size() - 1);
  931.                 if (0 < materialInfo.material.size())
  932.                     infoText.push_back('&');
  933.             }
  934.            
  935.             for (TAcceValueVector::iterator iter = materialInfo.material.begin(); materialInfo.material.end() != iter; ++iter)
  936.             {
  937.                 char tempBuffer[128];
  938.                 sprintf(tempBuffer, "%d,%d&", iter->vnum, iter->count);
  939.                 infoText += std::string(tempBuffer);
  940.             }
  941.            
  942.             infoText.erase(infoText.size() - 1);
  943.             if (0 < materialInfo.gold)
  944.             {
  945.                 char temp[128];
  946.                 sprintf(temp, "%d", materialInfo.gold);
  947.                 infoText += std::string("/") + temp;
  948.             }
  949.         }
  950.     }
  951. }
  952.  
  953. bool Acce_InformationInitialize()
  954. {
  955.     for (int i = 0; i < (unsigned)s_acce_proto.size(); ++i)
  956.     {
  957.         ACCE_DATA* acceData = s_acce_proto[i];
  958.         const std::vector<ACCE_VALUE>& rewards = acceData->reward;
  959.         if (rewards.size() != 1)
  960.         {
  961.             sys_err("[AcceInfo] WARNING! Does not support multiple rewards (count: %d)", rewards.size());          
  962.             continue;
  963.         }
  964.        
  965.         const ACCE_VALUE& reward = rewards.at(0);
  966.         const WORD& npcVNUM = acceData->npc_vnum.at(0);
  967.         bool bComplicate = false;
  968.        
  969.         TAcceMapByNPC& acceMap = acce_info_map;
  970.         TAcceResultList& resultList = acceMap[npcVNUM];
  971.         SAcceMaterialInfo materialInfo;
  972.        
  973.         materialInfo.reward = reward;
  974.         materialInfo.gold = acceData->gold;
  975.         materialInfo.material = acceData->item;
  976.        
  977.         for (TAcceResultList::iterator iter = resultList.begin(); resultList.end() != iter; ++iter)
  978.         {
  979.             SAcceMaterialInfo& existInfo = *iter;
  980.             if (reward.vnum == existInfo.reward.vnum)
  981.             {
  982.                 for (TAcceValueVector::iterator existMaterialIter = existInfo.material.begin(); existInfo.material.end() != existMaterialIter; ++existMaterialIter)
  983.                 {
  984.                     TItemTable* existMaterialProto = ITEM_MANAGER::Instance().GetTable(existMaterialIter->vnum);
  985.                     if (NULL == existMaterialProto)
  986.                     {
  987.                         sys_err("There is no item(%u)", existMaterialIter->vnum);
  988.                         return false;
  989.                     }
  990.                    
  991.                     SItemNameAndLevel existItemInfo = SplitItemNameAndLevelFromHName(existMaterialProto->szName);
  992.                     if (0 < existItemInfo.level)
  993.                     {
  994.                         for (TAcceValueVector::iterator currentMaterialIter = materialInfo.material.begin(); materialInfo.material.end() != currentMaterialIter; ++currentMaterialIter)
  995.                         {
  996.                             TItemTable* currentMaterialProto = ITEM_MANAGER::Instance().GetTable(currentMaterialIter->vnum);
  997.                             SItemNameAndLevel currentItemInfo = SplitItemNameAndLevelFromHName(currentMaterialProto->szName);
  998.                             if (currentItemInfo.name == existItemInfo.name)
  999.                             {
  1000.                                 bComplicate = true;
  1001.                                 existInfo.complicateMaterial.push_back(*currentMaterialIter);
  1002.                                 if (std::find(existInfo.complicateMaterial.begin(), existInfo.complicateMaterial.end(), *existMaterialIter) == existInfo.complicateMaterial.end())
  1003.                                     existInfo.complicateMaterial.push_back(*existMaterialIter);
  1004.                                
  1005.                                 break;
  1006.                             }
  1007.                         }
  1008.                     }
  1009.                 }
  1010.             }
  1011.         }
  1012.        
  1013.         if (false == bComplicate)
  1014.             resultList.push_back(materialInfo);
  1015.     }
  1016.    
  1017.     Acce_MakeAcceInformationText();
  1018.     s_isInitializedAcceMaterialInformation = true;
  1019.     return true;
  1020. }
  1021.  
  1022. void Acce_request_result_list(LPCHARACTER ch)
  1023. {
  1024.     RETURN_IF_ACCE_IS_NOT_OPENED(ch);
  1025.     LPCHARACTER npc = ch->GetQuestNPC();
  1026.     if (NULL == npc)
  1027.         return;
  1028.    
  1029.     DWORD npcVNUM = npc->GetRaceNum();
  1030.     size_t resultCount = 0;
  1031.     std::string& resultText = acce_result_info_map_by_npc[npcVNUM];
  1032.     if (resultText.length() == 0)
  1033.     {
  1034.         resultText.clear();
  1035.         const TAcceResultList& resultList = acce_info_map[npcVNUM];
  1036.         for (TAcceResultList::const_iterator iter = resultList.begin(); resultList.end() != iter; ++iter)
  1037.         {
  1038.             const SAcceMaterialInfo& materialInfo = *iter;
  1039.             char temp[128];
  1040.             sprintf(temp, "%d,%d", materialInfo.reward.vnum, materialInfo.reward.count);
  1041.            
  1042.             resultText += std::string(temp) + "/";
  1043.         }
  1044.        
  1045.         resultCount = resultList.size();
  1046.         resultText.erase(resultText.size() - 1);
  1047.         if (resultCount == 0)
  1048.         {
  1049.             return;
  1050.         }
  1051.        
  1052.         if (resultText.size() - 20 >= CHAT_MAX_LEN)
  1053.         {
  1054.             sys_err("[AcceInfo] Too long Acce result list text. (NPC: %d, length: %d)", npcVNUM, resultText.size());
  1055.             resultText.clear();
  1056.             resultCount = 0;
  1057.         }
  1058.     }
  1059.    
  1060.     ch->ChatPacket(CHAT_TYPE_COMMAND, "Acce r_list %d %d %s", npcVNUM, resultCount, resultText.c_str());
  1061. }
  1062.  
  1063. void Acce_request_material_info(LPCHARACTER ch, int requestStartIndex, int requestCount)
  1064. {
  1065.     RETURN_IF_ACCE_IS_NOT_OPENED(ch);
  1066.     LPCHARACTER npc = ch->GetQuestNPC();
  1067.     if (NULL == npc)
  1068.         return;
  1069.    
  1070.     DWORD npcVNUM = npc->GetRaceNum();
  1071.     std::string materialInfoText = "";
  1072.    
  1073.     int index = 0;
  1074.     bool bCatchInfo = false;
  1075.     const TAcceResultList& resultList = acce_info_map[npcVNUM];
  1076.    
  1077.     for (TAcceResultList::const_iterator iter = resultList.begin(); resultList.end() != iter; ++iter)
  1078.     {
  1079.         const SAcceMaterialInfo& materialInfo = *iter;
  1080.         if (index++ == requestStartIndex)
  1081.         {
  1082.             bCatchInfo = true;
  1083.         }
  1084.        
  1085.         if (bCatchInfo)
  1086.         {
  1087.             materialInfoText += materialInfo.infoText + "@";
  1088.         }
  1089.        
  1090.         if (index >= requestStartIndex + requestCount)
  1091.             break;
  1092.     }
  1093.    
  1094.     if (false == bCatchInfo)
  1095.     {
  1096.         sys_err("[AcceInfo] Can't find matched material info (NPC: %d, index: %d, request count: %d)", npcVNUM, requestStartIndex, requestCount);
  1097.         return;
  1098.     }
  1099.    
  1100.     materialInfoText.erase(materialInfoText.size() - 1);
  1101.     if (materialInfoText.size() - 20 >= CHAT_MAX_LEN)
  1102.     {
  1103.         sys_err("[AcceInfo] Too long material info. (NPC: %d, requestStart: %d, requestCount: %d, length: %d)", npcVNUM, requestStartIndex, requestCount, materialInfoText.size());
  1104.     }
  1105.    
  1106.     ch->ChatPacket(CHAT_TYPE_COMMAND, "Acce m_info %d %d %s", requestStartIndex, requestCount, materialInfoText.c_str());
  1107. }
Advertisement
Add Comment
Please, Sign In to add comment