Advertisement
victorbh

Untitled

Aug 16th, 2015
191
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 40.70 KB | None | 0 0
  1. // Copyright (c) Hercules Dev Team, licensed under GNU GPL.
  2. // See the LICENSE file
  3. // CostumeItem Hercules Plugin
  4. // Special Thanks for Mr. [Hercules/Ind]
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9.  
  10. #include "common/hercules.h" /* Should always be the first Hercules file included! (if you don't make it first, you won't be able to use interfaces) */
  11. #include "common/malloc.h"
  12. #include "common/timer.h"
  13. #include "common/HPMi.h"
  14. #include "common/mmo.h"
  15. #include "map/itemdb.h"
  16. #include "map/battle.h"
  17. #include "map/script.h"
  18. #include "map/status.h"
  19. #include "map/clif.h"
  20. #include "map/pet.h"
  21. #include "map/map.h"
  22. #include "map/mob.h"
  23. #include "map/pc.h"
  24. #include "common/strlib.h"
  25. #include "config/const.h"
  26.  
  27. #include "common/HPMDataCheck.h"
  28.  
  29. #define cap_value(a, min, max) (((a) >= (max)) ? (max) : ((a) <= (min)) ? (min) : (a))
  30.  
  31.  
  32. /*
  33. 1.0 Initial Release [Mhalicot]
  34. 1.0a Fixed Typo (usage: @ci <item name/ID>) changed to (usage: @costumeitem <item name/ID>) thx to DP
  35. 2.0 Converted Costume Items will now removed normal stats and Bonuses. [Mhalicot]
  36. 3.0 Item Combos will now Ignore Converted Costume Items. [Mhalicot]
  37. 3.1 Fixed HP/SP becomes 1/1 [Mhalicot]
  38. 3.2 Fixed Sinx Can't Equipt dagger/sword on both arms(L/R), Special Thanks to Haru for Help [Mhalicot]
  39. 3.3 Fixed Error when compiling.
  40. 3.4 Fixed Error when compiling.
  41. 3.4a Updated According to new hercules.[Dastgir]
  42. */
  43.  
  44. HPExport struct hplugin_info pinfo = {
  45.     "costumeitem",      // Plugin name
  46.     SERVER_TYPE_CHAR|SERVER_TYPE_LOGIN|SERVER_TYPE_MAP, // Which server types this plugin works with?
  47.     "1.0",              // Plugin version
  48.     HPM_VERSION,        // HPM Version (don't change, macro is automatically updated)
  49. };
  50.  
  51. static inline void status_cpy(struct status_data* a, const struct status_data* b)
  52. {
  53.     memcpy((void*)&a->max_hp, (const void*)&b->max_hp, sizeof(struct status_data)-(sizeof(a->hp)+sizeof(a->sp)));
  54. }
  55.  
  56. // Costume System
  57. int reserved_costume_id = 999998;
  58. void parse_my_setting(const char *val) {
  59.     reserved_costume_id = atoi(val);
  60. }
  61.  
  62. uint16 GetWord(uint32 val, int idx) {
  63.     switch( idx ) {
  64.     case 0: return (uint16)( (val & 0x0000FFFF)         );
  65.     case 1: return (uint16)( (val & 0xFFFF0000) >> 0x10 );
  66.     default:
  67. #if defined(DEBUG)
  68. #endif
  69.         ShowDebug("GetWord: invalid index (idx=%d)\n", idx);
  70.         return 0;
  71.     }
  72. }
  73.  
  74. uint32 MakeDWord(uint16 word0, uint16 word1) {
  75.     return
  76.         ( (uint32)(word0        ) )|
  77.         ( (uint32)(word1 << 0x10) );
  78. }
  79.  
  80. int status_calc_mine(struct map_session_data* sd, enum e_status_calc_opt opt) {
  81.     static int calculating = 0; //Check for recursive call preemption. [Skotlex]
  82.     struct status_data *bstatus; // pointer to the player's base status
  83.     const struct status_change *sc = &sd->sc;
  84.     struct s_skill b_skill[MAX_SKILL]; // previous skill tree
  85.     int b_weight, b_max_weight, b_cart_weight_max, // previous weight
  86.         i, k, index, skill_lv,refinedef=0;
  87.     int64 i64;
  88.  
  89.     if (++calculating > 10) //Too many recursive calls!
  90.         return -1;
  91.  
  92.     // remember player-specific values that are currently being shown to the client (for refresh purposes)
  93.     memcpy(b_skill, &sd->status.skill, sizeof(b_skill));
  94.     b_weight = sd->weight;
  95.     b_max_weight = sd->max_weight;
  96.     b_cart_weight_max = sd->cart_weight_max;
  97.  
  98.     pc->calc_skilltree(sd); // SkillTree calculation
  99.  
  100.     sd->max_weight = status->max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300;
  101.  
  102.     if(opt&SCO_FIRST) {
  103.         //Load Hp/SP from char-received data.
  104.         sd->battle_status.hp = sd->status.hp;
  105.         sd->battle_status.sp = sd->status.sp;
  106.         sd->regen.sregen = &sd->sregen;
  107.         sd->regen.ssregen = &sd->ssregen;
  108.         sd->weight=0;
  109.         for(i=0;i<MAX_INVENTORY;i++){
  110.             if(sd->status.inventory[i].nameid==0 || sd->inventory_data[i] == NULL)
  111.                 continue;
  112.             sd->weight += sd->inventory_data[i]->weight*sd->status.inventory[i].amount;
  113.         }
  114.         sd->cart_weight=0;
  115.         sd->cart_num=0;
  116.         for(i=0;i<MAX_CART;i++){
  117.             if(sd->status.cart[i].nameid==0)
  118.                 continue;
  119.             sd->cart_weight+=itemdb_weight(sd->status.cart[i].nameid)*sd->status.cart[i].amount;
  120.             sd->cart_num++;
  121.         }
  122.     }
  123.  
  124.     bstatus = &sd->base_status;
  125.     // these are not zeroed. [zzo]
  126.     sd->hprate=100;
  127.     sd->sprate=100;
  128.     sd->castrate=100;
  129.     sd->delayrate=100;
  130.     sd->dsprate=100;
  131.     sd->hprecov_rate = 100;
  132.     sd->sprecov_rate = 100;
  133.     sd->matk_rate = 100;
  134.     sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100;
  135.     sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100;
  136.     sd->regen.state.block = 0;
  137.  
  138.     // zeroed arrays, order follows the order in pc.h.
  139.     // add new arrays to the end of zeroed area in pc.h (see comments) and size here. [zzo]
  140.     memset (sd->param_bonus, 0, sizeof(sd->param_bonus)
  141.         + sizeof(sd->param_equip)
  142.         + sizeof(sd->subele)
  143.         + sizeof(sd->subrace)
  144.         + sizeof(sd->subrace2)
  145.         + sizeof(sd->subsize)
  146.         + sizeof(sd->reseff)
  147.         + sizeof(sd->weapon_coma_ele)
  148.         + sizeof(sd->weapon_coma_race)
  149.         + sizeof(sd->weapon_atk)
  150.         + sizeof(sd->weapon_atk_rate)
  151.         + sizeof(sd->arrow_addele)
  152.         + sizeof(sd->arrow_addrace)
  153.         + sizeof(sd->arrow_addsize)
  154.         + sizeof(sd->magic_addele)
  155.         + sizeof(sd->magic_addrace)
  156.         + sizeof(sd->magic_addsize)
  157.         + sizeof(sd->magic_atk_ele)
  158.         + sizeof(sd->critaddrace)
  159.         + sizeof(sd->expaddrace)
  160.         + sizeof(sd->ignore_mdef)
  161.         + sizeof(sd->ignore_def)
  162.         + sizeof(sd->sp_gain_race)
  163.         + sizeof(sd->sp_gain_race_attack)
  164.         + sizeof(sd->hp_gain_race_attack)
  165.         );
  166.  
  167.     memset (&sd->right_weapon.overrefine, 0, sizeof(sd->right_weapon) - sizeof(sd->right_weapon.atkmods));
  168.     memset (&sd->left_weapon.overrefine, 0, sizeof(sd->left_weapon) - sizeof(sd->left_weapon.atkmods));
  169.  
  170.     if (sd->special_state.intravision && !sd->sc.data[SC_CLAIRVOYANCE]) //Clear intravision as long as nothing else is using it
  171.         clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_CLAIRVOYANCE);
  172.  
  173.     memset(&sd->special_state,0,sizeof(sd->special_state));
  174.    
  175.     if (!sd->state.permanent_speed) {
  176.         memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp)));
  177.         bstatus->speed = DEFAULT_WALK_SPEED;
  178.     } else {
  179.         int pSpeed = bstatus->speed;
  180.         memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp)));
  181.         bstatus->speed = pSpeed;
  182.     }
  183.    
  184.     //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex]
  185.     //Give them all modes except these (useful for clones)
  186.     bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
  187.  
  188.     bstatus->size = (sd->class_&JOBL_BABY)?SZ_MEDIUM:SZ_SMALL;
  189.     if (battle->bc->character_size && (pc_isridingpeco(sd) || pc_isridingdragon(sd)) ) { //[Lupus]
  190.         if (sd->class_&JOBL_BABY) {
  191.             if (battle->bc->character_size&SZ_BIG)
  192.                 bstatus->size++;
  193.         } else
  194.             if(battle->bc->character_size&SZ_SMALL)
  195.                 bstatus->size++;
  196.     }
  197.     bstatus->aspd_rate = 1000;
  198.     bstatus->ele_lv = 1;
  199.     bstatus->race = RC_DEMIHUMAN;
  200.  
  201.     //zero up structures...
  202.     memset(&sd->autospell,0,sizeof(sd->autospell)
  203.         + sizeof(sd->autospell2)
  204.         + sizeof(sd->autospell3)
  205.         + sizeof(sd->addeff)
  206.         + sizeof(sd->addeff2)
  207.         + sizeof(sd->addeff3)
  208.         + sizeof(sd->skillatk)
  209.         + sizeof(sd->skillusesprate)
  210.         + sizeof(sd->skillusesp)
  211.         + sizeof(sd->skillheal)
  212.         + sizeof(sd->skillheal2)
  213.         + sizeof(sd->hp_loss)
  214.         + sizeof(sd->sp_loss)
  215.         + sizeof(sd->hp_regen)
  216.         + sizeof(sd->sp_regen)
  217.         + sizeof(sd->skillblown)
  218.         + sizeof(sd->skillcast)
  219.         + sizeof(sd->add_def)
  220.         + sizeof(sd->add_mdef)
  221.         + sizeof(sd->add_mdmg)
  222.         + sizeof(sd->add_drop)
  223.         + sizeof(sd->itemhealrate)
  224.         + sizeof(sd->subele2)
  225.         + sizeof(sd->skillcooldown)
  226.         + sizeof(sd->skillfixcast)
  227.         + sizeof(sd->skillvarcast)
  228.         + sizeof(sd->skillfixcastrate)
  229.         );
  230.  
  231.     memset (&sd->bonus, 0,sizeof(sd->bonus));
  232.  
  233.     // Autobonus
  234.     pc->delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true);
  235.     pc->delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus2),true);
  236.     pc->delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),true);
  237.  
  238.     // Parse equipment.
  239.     for(i=0;i<EQI_MAX;i++) {
  240.         status->current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to status->current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
  241.         if(index < 0)
  242.             continue;
  243.         if(i == EQI_AMMO) continue;/* ammo has special handler down there */
  244.         if(i == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index)
  245.             continue;
  246.         if(i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index)
  247.             continue;
  248.         if(i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index))
  249.             continue;
  250.         if(i == EQI_COSTUME_MID && sd->equip_index[EQI_COSTUME_LOW] == index)
  251.             continue;
  252.         if(i == EQI_COSTUME_TOP && (sd->equip_index[EQI_COSTUME_MID] == index || sd->equip_index[EQI_COSTUME_LOW] == index))
  253.             continue;
  254.         if( (int)MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) == reserved_costume_id )
  255.             continue;
  256.         if(!sd->inventory_data[index])
  257.             continue;
  258.  
  259.         for(k = 0; k < map->list[sd->bl.m].zone->disabled_items_count; k++) {
  260.             if( map->list[sd->bl.m].zone->disabled_items[k] == sd->inventory_data[index]->nameid ) {
  261.                 break;
  262.             }
  263.         }
  264.  
  265.         if( k < map->list[sd->bl.m].zone->disabled_items_count )
  266.             continue;
  267.  
  268.         bstatus->def += sd->inventory_data[index]->def;
  269.  
  270.         if(opt&SCO_FIRST && sd->inventory_data[index]->equip_script)
  271.         {   //Execute equip-script on login
  272.             script->run(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
  273.             if (!calculating)
  274.                 return 1;
  275.         }
  276.  
  277.         // sanitize the refine level in case someone decreased the value inbetween
  278.         if (sd->status.inventory[index].refine > MAX_REFINE)
  279.             sd->status.inventory[index].refine = MAX_REFINE;
  280.  
  281.         if(sd->inventory_data[index]->type == IT_WEAPON) {
  282.             int r,wlv = sd->inventory_data[index]->wlv;
  283.             struct weapon_data *wd;
  284.             struct weapon_atk *wa;
  285.             if (wlv >= REFINE_TYPE_MAX)
  286.                 wlv = REFINE_TYPE_MAX - 1;
  287.             if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) {
  288.                 wd = &sd->left_weapon; // Left-hand weapon
  289.                 wa = &bstatus->lhw;
  290.             } else {
  291.                 wd = &sd->right_weapon;
  292.                 wa = &bstatus->rhw;
  293.             }
  294.             wa->atk += sd->inventory_data[index]->atk;
  295.             if ( (r = sd->status.inventory[index].refine) )
  296.                 wa->atk2 = status->refine_info[wlv].bonus[r-1] / 100;
  297.  
  298. #ifdef RENEWAL
  299.             wa->matk += sd->inventory_data[index]->matk;
  300.             wa->wlv = wlv;
  301.             if( r && sd->weapontype1 != W_BOW ) // renewal magic attack refine bonus
  302.                 wa->matk += status->refine_info[wlv].bonus[r-1] / 100;
  303. #endif
  304.  
  305.             //Overrefine bonus.
  306.             if (r)
  307.                 wd->overrefine = status->refine_info[wlv].randombonus_max[r-1] / 100;
  308.  
  309.             wa->range += sd->inventory_data[index]->range;
  310.             if(sd->inventory_data[index]->script) {
  311.                 if (wd == &sd->left_weapon) {
  312.                     sd->state.lr_flag = 1;
  313.                     script->run(sd->inventory_data[index]->script,0,sd->bl.id,0);
  314.                     sd->state.lr_flag = 0;
  315.                 } else
  316.                     script->run(sd->inventory_data[index]->script,0,sd->bl.id,0);
  317.                 if (!calculating) //Abort, script->run retriggered this. [Skotlex]
  318.                     return 1;
  319.             }
  320.  
  321.             if(sd->status.inventory[index].card[0]==CARD0_FORGE)
  322.             {   // Forged weapon
  323.                 wd->star += (sd->status.inventory[index].card[1]>>8);
  324.                 if(wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg
  325.                 if(pc->famerank(MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH))
  326.                     wd->star += 10;
  327.  
  328.                 if (!wa->ele) //Do not overwrite element from previous bonuses.
  329.                     wa->ele = (sd->status.inventory[index].card[1]&0x0f);
  330.             }
  331.         }
  332.         else if(sd->inventory_data[index]->type == IT_ARMOR) {
  333.             int r;
  334.             if ( (r = sd->status.inventory[index].refine) )
  335.                 refinedef += status->refine_info[REFINE_TYPE_ARMOR].bonus[r-1];
  336.             if(sd->inventory_data[index]->script) {
  337.                 if( i == EQI_HAND_L ) //Shield
  338.                     sd->state.lr_flag = 3;
  339.                 script->run(sd->inventory_data[index]->script,0,sd->bl.id,0);
  340.                 if( i == EQI_HAND_L ) //Shield
  341.                     sd->state.lr_flag = 0;
  342.                 if (!calculating) //Abort, script->run retriggered this. [Skotlex]
  343.                     return 1;
  344.             }
  345.         }
  346.     }
  347.  
  348.     if(sd->equip_index[EQI_AMMO] >= 0){
  349.         index = sd->equip_index[EQI_AMMO];
  350.         if(sd->inventory_data[index]){      // Arrows
  351.             sd->bonus.arrow_atk += sd->inventory_data[index]->atk;
  352.             sd->state.lr_flag = 2;
  353.             if( !itemdb_is_GNthrowable(sd->inventory_data[index]->nameid) ) //don't run scripts on throwable items
  354.                 script->run(sd->inventory_data[index]->script,0,sd->bl.id,0);
  355.             sd->state.lr_flag = 0;
  356.             if (!calculating) //Abort, script->run retriggered status_calc_pc. [Skotlex]
  357.                 return 1;
  358.         }
  359.     }
  360.  
  361.     /* we've got combos to process */
  362.     for( i = 0; i < sd->combo_count; i++ ) {
  363.         struct item_combo *combo = itemdb->id2combo(sd->combos[i].id);
  364.         unsigned char j;
  365.        
  366.         /**
  367.          * ensure combo usage is allowed at this location
  368.          **/
  369.         for(j = 0; j < combo->count; j++) {
  370.             for(k = 0; k < map->list[sd->bl.m].zone->disabled_items_count; k++) {
  371.                 if( map->list[sd->bl.m].zone->disabled_items[k] == combo->nameid[j] ) {
  372.                     break;
  373.                 }
  374.             }
  375.             if( k != map->list[sd->bl.m].zone->disabled_items_count )
  376.                 break;
  377.         }
  378.        
  379.         if( j != combo->count )
  380.             continue;
  381.        
  382.         script->run(sd->combos[i].bonus,0,sd->bl.id,0);
  383.         if (!calculating) //Abort, script->run retriggered this.
  384.             return 1;
  385.     }
  386.  
  387.     //Store equipment script bonuses
  388.     memcpy(sd->param_equip,sd->param_bonus,sizeof(sd->param_equip));
  389.     memset(sd->param_bonus, 0, sizeof(sd->param_bonus));
  390.  
  391.     bstatus->def += (refinedef+50)/100;
  392.  
  393.     //Parse Cards
  394.     for(i=0;i<EQI_MAX;i++) {
  395.         status->current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to status->current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
  396.         if(index < 0)
  397.             continue;
  398.         if(i == EQI_AMMO) continue;/* ammo doesn't have cards */
  399.         if(i == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index)
  400.             continue;
  401.         if(i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index)
  402.             continue;
  403.         if(i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index))
  404.             continue;
  405.  
  406.         if(sd->inventory_data[index]) {
  407.             int j,c;
  408.             struct item_data *data;
  409.  
  410.             //Card script execution.
  411.             if(itemdb_isspecial(sd->status.inventory[index].card[0]))
  412.                 continue;
  413.             for(j=0;j<MAX_SLOTS;j++) {
  414.                 // Uses MAX_SLOTS to support Soul Bound system [Inkfish]
  415.                 status->current_equip_card_id= c= sd->status.inventory[index].card[j];
  416.                 if(!c)
  417.                     continue;
  418.                 data = itemdb->exists(c);
  419.                 if(!data)
  420.                     continue;
  421.  
  422.                 for(k = 0; k < map->list[sd->bl.m].zone->disabled_items_count; k++) {
  423.                     if( map->list[sd->bl.m].zone->disabled_items[k] == data->nameid ) {
  424.                         break;
  425.                     }
  426.                 }
  427.  
  428.                 if( k < map->list[sd->bl.m].zone->disabled_items_count )
  429.                     continue;
  430.  
  431.                 if(opt&SCO_FIRST && data->equip_script) {//Execute equip-script on login
  432.                     script->run(data->equip_script,0,sd->bl.id,0);
  433.                     if (!calculating)
  434.                         return 1;
  435.                 }
  436.  
  437.                 if(!data->script)
  438.                     continue;
  439.  
  440.                 if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) { //Left hand status.
  441.                     sd->state.lr_flag = 1;
  442.                     script->run(data->script,0,sd->bl.id,0);
  443.                     sd->state.lr_flag = 0;
  444.                 } else
  445.                     script->run(data->script,0,sd->bl.id,0);
  446.                 if (!calculating) //Abort, script->run his function. [Skotlex]
  447.                     return 1;
  448.             }
  449.         }
  450.     }
  451.  
  452.     if( sc->count && sc->data[SC_ITEMSCRIPT] ) {
  453.         struct item_data *data = itemdb->exists(sc->data[SC_ITEMSCRIPT]->val1);
  454.         if( data && data->script )
  455.             script->run(data->script,0,sd->bl.id,0);
  456.     }
  457.  
  458.     if( sd->pd ) { // Pet Bonus
  459.         struct pet_data *pd = sd->pd;
  460.         if( pd && pd->petDB && pd->petDB->equip_script && pd->pet.intimate >= battle->bc->pet_equip_min_friendly )
  461.             script->run(pd->petDB->equip_script,0,sd->bl.id,0);
  462.         if( pd && pd->pet.intimate > 0 && (!battle->bc->pet_equip_required || pd->pet.equip > 0) && pd->state.skillbonus == 1 && pd->bonus )
  463.             pc->bonus(sd,pd->bonus->type, pd->bonus->val);
  464.     }
  465.  
  466.     //param_bonus now holds card bonuses.
  467.     if(bstatus->rhw.range < 1) bstatus->rhw.range = 1;
  468.     if(bstatus->lhw.range < 1) bstatus->lhw.range = 1;
  469.     if(bstatus->rhw.range < bstatus->lhw.range)
  470.         bstatus->rhw.range = bstatus->lhw.range;
  471.  
  472.     sd->bonus.double_rate += sd->bonus.double_add_rate;
  473.     sd->bonus.perfect_hit += sd->bonus.perfect_hit_add;
  474.     sd->bonus.splash_range += sd->bonus.splash_add_range;
  475.  
  476.     // Damage modifiers from weapon type
  477.     sd->right_weapon.atkmods[0] = status->atkmods[0][sd->weapontype1];
  478.     sd->right_weapon.atkmods[1] = status->atkmods[1][sd->weapontype1];
  479.     sd->right_weapon.atkmods[2] = status->atkmods[2][sd->weapontype1];
  480.     sd->left_weapon.atkmods[0] = status->atkmods[0][sd->weapontype2];
  481.     sd->left_weapon.atkmods[1] = status->atkmods[1][sd->weapontype2];
  482.     sd->left_weapon.atkmods[2] = status->atkmods[2][sd->weapontype2];
  483.  
  484.     if( (pc_isridingpeco(sd) || pc_isridingdragon(sd)) &&
  485.         (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR))
  486.     {   //When Riding with spear, damage modifier to mid-class becomes
  487.         //same as versus large size.
  488.         sd->right_weapon.atkmods[1] = sd->right_weapon.atkmods[2];
  489.         sd->left_weapon.atkmods[1] = sd->left_weapon.atkmods[2];
  490.     }
  491.  
  492.     // ----- STATS CALCULATION -----
  493.  
  494.     // Job bonuses
  495.     index = pc->class2idx(sd->status.class_);
  496.     for(i=0;i<(int)sd->status.job_level && i<MAX_LEVEL;i++){
  497.         if(!status->job_bonus[index][i])
  498.             continue;
  499.         switch(status->job_bonus[index][i]) {
  500.             case 1: bstatus->str++; break;
  501.             case 2: bstatus->agi++; break;
  502.             case 3: bstatus->vit++; break;
  503.             case 4: bstatus->int_++; break;
  504.             case 5: bstatus->dex++; break;
  505.             case 6: bstatus->luk++; break;
  506.         }
  507.     }
  508.  
  509.     // If a Super Novice has never died and is at least joblv 70, he gets all stats +10
  510.     if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->die_counter == 0 && sd->status.job_level >= 70) {
  511.         bstatus->str += 10;
  512.         bstatus->agi += 10;
  513.         bstatus->vit += 10;
  514.         bstatus->int_+= 10;
  515.         bstatus->dex += 10;
  516.         bstatus->luk += 10;
  517.     }
  518.  
  519.     // Absolute modifiers from passive skills
  520.     if(pc->checkskill(sd,BS_HILTBINDING)>0)
  521.         bstatus->str++;
  522.     if((skill_lv=pc->checkskill(sd,SA_DRAGONOLOGY))>0)
  523.         bstatus->int_ += (skill_lv+1)/2; // +1 INT / 2 lv
  524.     if((skill_lv=pc->checkskill(sd,AC_OWL))>0)
  525.         bstatus->dex += skill_lv;
  526.     if((skill_lv = pc->checkskill(sd,RA_RESEARCHTRAP))>0)
  527.         bstatus->int_ += skill_lv;
  528.  
  529.     // Bonuses from cards and equipment as well as base stat, remember to avoid overflows.
  530.     i = bstatus->str + sd->status.str + sd->param_bonus[0] + sd->param_equip[0];
  531.     bstatus->str = cap_value(i,0,USHRT_MAX);
  532.     i = bstatus->agi + sd->status.agi + sd->param_bonus[1] + sd->param_equip[1];
  533.     bstatus->agi = cap_value(i,0,USHRT_MAX);
  534.     i = bstatus->vit + sd->status.vit + sd->param_bonus[2] + sd->param_equip[2];
  535.     bstatus->vit = cap_value(i,0,USHRT_MAX);
  536.     i = bstatus->int_+ sd->status.int_+ sd->param_bonus[3] + sd->param_equip[3];
  537.     bstatus->int_ = cap_value(i,0,USHRT_MAX);
  538.     i = bstatus->dex + sd->status.dex + sd->param_bonus[4] + sd->param_equip[4];
  539.     bstatus->dex = cap_value(i,0,USHRT_MAX);
  540.     i = bstatus->luk + sd->status.luk + sd->param_bonus[5] + sd->param_equip[5];
  541.     bstatus->luk = cap_value(i,0,USHRT_MAX);
  542.  
  543.     // ------ BASE ATTACK CALCULATION ------
  544.  
  545.     // Base batk value is set on status->calc_misc
  546.     // weapon-type bonus (FIXME: Why is the weapon_atk bonus applied to base attack?)
  547.     if (sd->status.weapon < MAX_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon])
  548.         bstatus->batk += sd->weapon_atk[sd->status.weapon];
  549.     // Absolute modifiers from passive skills
  550. #ifndef RENEWAL
  551.     if((skill_lv=pc->checkskill(sd,BS_HILTBINDING))>0) // it doesn't work in RE.
  552.         bstatus->batk += 4;
  553. #endif
  554.  
  555.     // ----- HP MAX CALCULATION -----
  556.  
  557.     // Basic MaxHP value
  558.     //We hold the standard Max HP here to make it faster to recalculate on vit changes.
  559.     sd->status.max_hp = status->get_base_maxhp(sd,bstatus);
  560.     //This is done to handle underflows from negative Max HP bonuses
  561.     i64 = sd->status.max_hp + (int)bstatus->max_hp;
  562.     bstatus->max_hp = (unsigned int)cap_value(i64, 0, INT_MAX);
  563.  
  564.     // Absolute modifiers from passive skills
  565.     if((skill_lv=pc->checkskill(sd,CR_TRUST))>0)
  566.         bstatus->max_hp += skill_lv*200;
  567.  
  568.     // Apply relative modifiers from equipment
  569.     if(sd->hprate < 0)
  570.         sd->hprate = 0;
  571.     if(sd->hprate!=100)
  572.         bstatus->max_hp = APPLY_RATE(bstatus->max_hp, sd->hprate);
  573.     if(battle->bc->hp_rate != 100)
  574.         bstatus->max_hp = APPLY_RATE(bstatus->max_hp, battle->bc->hp_rate);
  575.  
  576.     if(bstatus->max_hp > (unsigned int)battle->bc->max_hp)
  577.         bstatus->max_hp = battle->bc->max_hp;
  578.     else if(!bstatus->max_hp)
  579.         bstatus->max_hp = 1;
  580.  
  581.     // ----- SP MAX CALCULATION -----
  582.  
  583.     // Basic MaxSP value
  584.     sd->status.max_sp = status->get_base_maxsp(sd,bstatus);
  585.     //This is done to handle underflows from negative Max SP bonuses
  586.     i64 = sd->status.max_sp + (int)bstatus->max_sp;
  587.     bstatus->max_sp = (unsigned int)cap_value(i64, 0, INT_MAX);
  588.  
  589.     // Absolute modifiers from passive skills
  590.     if((skill_lv=pc->checkskill(sd,SL_KAINA))>0)
  591.         bstatus->max_sp += 30*skill_lv;
  592.     if((skill_lv=pc->checkskill(sd,HP_MEDITATIO))>0)
  593.         bstatus->max_sp += (int64)bstatus->max_sp * skill_lv/100;
  594.     if((skill_lv=pc->checkskill(sd,HW_SOULDRAIN))>0)
  595.         bstatus->max_sp += (int64)bstatus->max_sp * 2*skill_lv/100;
  596.     if( (skill_lv = pc->checkskill(sd,RA_RESEARCHTRAP)) > 0 )
  597.         bstatus->max_sp += 200 + 20 * skill_lv;
  598.     if( (skill_lv = pc->checkskill(sd,WM_LESSON)) > 0 )
  599.         bstatus->max_sp += 30 * skill_lv;
  600.  
  601.  
  602.     // Apply relative modifiers from equipment
  603.     if(sd->sprate < 0)
  604.         sd->sprate = 0;
  605.     if(sd->sprate!=100)
  606.         bstatus->max_sp = APPLY_RATE(bstatus->max_sp, sd->sprate);
  607.     if(battle->bc->sp_rate != 100)
  608.         bstatus->max_sp = APPLY_RATE(bstatus->max_sp, battle->bc->sp_rate);
  609.  
  610.     if(bstatus->max_sp > (unsigned int)battle->bc->max_sp)
  611.         bstatus->max_sp = battle->bc->max_sp;
  612.     else if(!bstatus->max_sp)
  613.         bstatus->max_sp = 1;
  614.  
  615.     // ----- RESPAWN HP/SP -----
  616.     //
  617.     //Calc respawn hp and store it on base_status
  618.     if (sd->special_state.restart_full_recover)
  619.     {
  620.         bstatus->hp = bstatus->max_hp;
  621.         bstatus->sp = bstatus->max_sp;
  622.     } else {
  623.         if((sd->class_&MAPID_BASEMASK) == MAPID_NOVICE && !(sd->class_&JOBL_2)
  624.             && battle->bc->restart_hp_rate < 50)
  625.             bstatus->hp = bstatus->max_hp>>1;
  626.         else
  627.             bstatus->hp = APPLY_RATE(bstatus->max_hp, battle->bc->restart_hp_rate);
  628.         if(!bstatus->hp)
  629.             bstatus->hp = 1;
  630.  
  631.         bstatus->sp = APPLY_RATE(bstatus->max_sp, battle->bc->restart_sp_rate);
  632.  
  633.         if( !bstatus->sp ) /* the minimum for the respawn setting is SP:1 */
  634.             bstatus->sp = 1;
  635.     }
  636.  
  637.     // ----- MISC CALCULATION -----
  638.     status->calc_misc(&sd->bl, bstatus, sd->status.base_level);
  639.  
  640.     //Equipment modifiers for misc settings
  641.     if(sd->matk_rate < 0)
  642.         sd->matk_rate = 0;
  643.  
  644.     if(sd->matk_rate != 100){
  645.         bstatus->matk_max = bstatus->matk_max * sd->matk_rate/100;
  646.         bstatus->matk_min = bstatus->matk_min * sd->matk_rate/100;
  647.     }
  648.  
  649.     if(sd->hit_rate < 0)
  650.         sd->hit_rate = 0;
  651.     if(sd->hit_rate != 100)
  652.         bstatus->hit = bstatus->hit * sd->hit_rate/100;
  653.  
  654.     if(sd->flee_rate < 0)
  655.         sd->flee_rate = 0;
  656.     if(sd->flee_rate != 100)
  657.         bstatus->flee = bstatus->flee * sd->flee_rate/100;
  658.  
  659.     if(sd->def2_rate < 0)
  660.         sd->def2_rate = 0;
  661.     if(sd->def2_rate != 100)
  662.         bstatus->def2 = bstatus->def2 * sd->def2_rate/100;
  663.  
  664.     if(sd->mdef2_rate < 0)
  665.         sd->mdef2_rate = 0;
  666.     if(sd->mdef2_rate != 100)
  667.         bstatus->mdef2 = bstatus->mdef2 * sd->mdef2_rate/100;
  668.  
  669.     if(sd->critical_rate < 0)
  670.         sd->critical_rate = 0;
  671.     if(sd->critical_rate != 100)
  672.         bstatus->cri = bstatus->cri * sd->critical_rate/100;
  673.  
  674.     if(sd->flee2_rate < 0)
  675.         sd->flee2_rate = 0;
  676.     if(sd->flee2_rate != 100)
  677.         bstatus->flee2 = bstatus->flee2 * sd->flee2_rate/100;
  678.  
  679.     // ----- HIT CALCULATION -----
  680.  
  681.     // Absolute modifiers from passive skills
  682. #ifndef RENEWAL
  683.     if((skill_lv=pc->checkskill(sd,BS_WEAPONRESEARCH))>0) // is this correct in pre? there is already hitrate bonus in battle.c
  684.         bstatus->hit += skill_lv*2;
  685. #endif
  686.     if((skill_lv=pc->checkskill(sd,AC_VULTURE))>0) {
  687. #ifndef RENEWAL
  688.         bstatus->hit += skill_lv;
  689. #endif
  690.         if(sd->status.weapon == W_BOW)
  691.             bstatus->rhw.range += skill_lv;
  692.     }
  693.     if(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE) {
  694.         if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0)
  695.             bstatus->hit += 2*skill_lv;
  696.         if((skill_lv=pc->checkskill(sd,GS_SNAKEEYE))>0) {
  697.             bstatus->hit += skill_lv;
  698.             bstatus->rhw.range += skill_lv;
  699.         }
  700.     }
  701.     if( (sd->status.weapon == W_1HAXE || sd->status.weapon == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0 )
  702.         bstatus->hit += 3*skill_lv;
  703.     if((sd->status.weapon == W_MACE || sd->status.weapon == W_2HMACE) && ((skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0))
  704.         bstatus->hit += 2*skill_lv;
  705.  
  706.     // ----- FLEE CALCULATION -----
  707.  
  708.     // Absolute modifiers from passive skills
  709.     if((skill_lv=pc->checkskill(sd,TF_MISS))>0)
  710.         bstatus->flee += skill_lv*(sd->class_&JOBL_2 && (sd->class_&MAPID_BASEMASK) == MAPID_THIEF? 4 : 3);
  711.     if((skill_lv=pc->checkskill(sd,MO_DODGE))>0)
  712.         bstatus->flee += (skill_lv*3)>>1;
  713.     // ----- EQUIPMENT-DEF CALCULATION -----
  714.  
  715.     // Apply relative modifiers from equipment
  716.     if(sd->def_rate < 0)
  717.         sd->def_rate = 0;
  718.     if(sd->def_rate != 100) {
  719.         i =  bstatus->def * sd->def_rate/100;
  720.         bstatus->def = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX);
  721.     }
  722.  
  723.     if( pc_ismadogear(sd) && (skill_lv = pc->checkskill(sd,NC_MAINFRAME)) > 0 )
  724.         bstatus->def += 20 + 20 * skill_lv;
  725.  
  726. #ifndef RENEWAL
  727.     if (!battle->bc->weapon_defense_type && bstatus->def > battle->bc->max_def) {
  728.         bstatus->def2 += battle->bc->over_def_bonus*(bstatus->def -battle->bc->max_def);
  729.         bstatus->def = (unsigned char)battle->bc->max_def;
  730.     }
  731. #endif
  732.  
  733.     // ----- EQUIPMENT-MDEF CALCULATION -----
  734.  
  735.     // Apply relative modifiers from equipment
  736.     if(sd->mdef_rate < 0)
  737.         sd->mdef_rate = 0;
  738.     if(sd->mdef_rate != 100) {
  739.         i =  bstatus->mdef * sd->mdef_rate/100;
  740.         bstatus->mdef = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX);
  741.     }
  742.  
  743. #ifndef RENEWAL
  744.     if (!battle->bc->magic_defense_type && bstatus->mdef > battle->bc->max_def) {
  745.         bstatus->mdef2 += battle->bc->over_def_bonus*(bstatus->mdef -battle->bc->max_def);
  746.         bstatus->mdef = (signed char)battle->bc->max_def;
  747.     }
  748. #endif
  749.  
  750.     // ----- ASPD CALCULATION -----
  751.     // Unlike other stats, ASPD rate modifiers from skills/SCs/items/etc are first all added together, then the final modifier is applied
  752.  
  753.     // Basic ASPD value
  754.     i = status->base_amotion_pc(sd,bstatus);
  755.     bstatus->amotion = cap_value(i,((sd->class_&JOBL_THIRD) ? battle->bc->max_third_aspd : battle->bc->max_aspd),2000);
  756.  
  757.     // Relative modifiers from passive skills
  758. #ifndef RENEWAL_ASPD
  759.     if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK)
  760.         bstatus->aspd_rate -= 5*skill_lv;
  761.     if((skill_lv = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd))
  762.         bstatus->aspd_rate -= 30*skill_lv;
  763.     if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
  764.         (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE))
  765.         bstatus->aspd_rate -= ((skill_lv+1)/2) * 10;
  766.     if(pc_isridingpeco(sd))
  767.         bstatus->aspd_rate += 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
  768.     else if(pc_isridingdragon(sd))
  769.         bstatus->aspd_rate += 250-50*pc->checkskill(sd,RK_DRAGONTRAINING);
  770. #else // needs more info
  771.     if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK)
  772.         bstatus->aspd_rate += 5*skill_lv;
  773.     if((skill_lv = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd))
  774.         bstatus->aspd_rate += 30*skill_lv;
  775.     if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
  776.         (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE))
  777.         bstatus->aspd_rate += ((skill_lv+1)/2) * 10;
  778.     if(pc_isridingpeco(sd))
  779.         bstatus->aspd_rate -= 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
  780.     else if(pc_isridingdragon(sd))
  781.         bstatus->aspd_rate -= 250-50*pc->checkskill(sd,RK_DRAGONTRAINING);
  782. #endif
  783.     bstatus->adelay = 2*bstatus->amotion;
  784.  
  785.  
  786.     // ----- DMOTION -----
  787.     //
  788.     i =  800-bstatus->agi*4;
  789.     bstatus->dmotion = cap_value(i, 400, 800);
  790.     if(battle->bc->pc_damage_delay_rate != 100)
  791.         bstatus->dmotion = bstatus->dmotion*battle->bc->pc_damage_delay_rate/100;
  792.  
  793.     // ----- MISC CALCULATIONS -----
  794.  
  795.     // Weight
  796.     if((skill_lv=pc->checkskill(sd,MC_INCCARRY))>0)
  797.         sd->max_weight += 2000*skill_lv;
  798.     if(pc_isridingpeco(sd) && pc->checkskill(sd,KN_RIDING)>0)
  799.         sd->max_weight += 10000;
  800.     else if(pc_isridingdragon(sd))
  801.         sd->max_weight += 5000+2000*pc->checkskill(sd,RK_DRAGONTRAINING);
  802.     if(sc->data[SC_KNOWLEDGE])
  803.         sd->max_weight += sd->max_weight*sc->data[SC_KNOWLEDGE]->val1/10;
  804.     if((skill_lv=pc->checkskill(sd,ALL_INCCARRY))>0)
  805.         sd->max_weight += 2000*skill_lv;
  806.  
  807.     sd->cart_weight_max = battle->bc->max_cart_weight + (pc->checkskill(sd, GN_REMODELING_CART)*5000);
  808.  
  809.     if (pc->checkskill(sd,SM_MOVINGRECOVERY)>0)
  810.         sd->regen.state.walk = 1;
  811.     else
  812.         sd->regen.state.walk = 0;
  813.  
  814.     // Skill SP cost
  815.     if((skill_lv=pc->checkskill(sd,HP_MANARECHARGE))>0 )
  816.         sd->dsprate -= 4*skill_lv;
  817.  
  818.     if(sc->data[SC_SERVICEFORYOU])
  819.         sd->dsprate -= sc->data[SC_SERVICEFORYOU]->val3;
  820.  
  821.     if(sc->data[SC_ATKER_BLOOD])
  822.         sd->dsprate -= sc->data[SC_ATKER_BLOOD]->val1;
  823.  
  824.     //Underflow protections.
  825.     if(sd->dsprate < 0)
  826.         sd->dsprate = 0;
  827.     if(sd->castrate < 0)
  828.         sd->castrate = 0;
  829.     if(sd->delayrate < 0)
  830.         sd->delayrate = 0;
  831.     if(sd->hprecov_rate < 0)
  832.         sd->hprecov_rate = 0;
  833.     if(sd->sprecov_rate < 0)
  834.         sd->sprecov_rate = 0;
  835.  
  836.     // Anti-element and anti-race
  837.     if((skill_lv=pc->checkskill(sd,CR_TRUST))>0)
  838.         sd->subele[ELE_HOLY] += skill_lv*5;
  839.     if((skill_lv=pc->checkskill(sd,BS_SKINTEMPER))>0) {
  840.         sd->subele[ELE_NEUTRAL] += skill_lv;
  841.         sd->subele[ELE_FIRE] += skill_lv*4;
  842.     }
  843.     if((skill_lv=pc->checkskill(sd,NC_RESEARCHFE))>0) {
  844.         sd->subele[ELE_EARTH] += skill_lv*10;
  845.         sd->subele[ELE_FIRE] += skill_lv*10;
  846.     }
  847.     if((skill_lv=pc->checkskill(sd,SA_DRAGONOLOGY))>0 ) {
  848. #ifdef RENEWAL
  849.         skill_lv = skill_lv*2;
  850. #else
  851.         skill_lv = skill_lv*4;
  852. #endif
  853.         sd->right_weapon.addrace[RC_DRAGON]+=skill_lv;
  854.         sd->left_weapon.addrace[RC_DRAGON]+=skill_lv;
  855.         sd->magic_addrace[RC_DRAGON]+=skill_lv;
  856.         sd->subrace[RC_DRAGON]+=skill_lv;
  857.     }
  858.  
  859.     if( (skill_lv = pc->checkskill(sd, AB_EUCHARISTICA)) > 0 ) {
  860.         sd->right_weapon.addrace[RC_DEMON] += skill_lv;
  861.         sd->right_weapon.addele[ELE_DARK] += skill_lv;
  862.         sd->left_weapon.addrace[RC_DEMON] += skill_lv;
  863.         sd->left_weapon.addele[ELE_DARK] += skill_lv;
  864.         sd->magic_addrace[RC_DEMON] += skill_lv;
  865.         sd->magic_addele[ELE_DARK] += skill_lv;
  866.         sd->subrace[RC_DEMON] += skill_lv;
  867.         sd->subele[ELE_DARK] += skill_lv;
  868.     }
  869.  
  870.     if(sc->count) {
  871.         if(sc->data[SC_CONCENTRATION]) { //Update the card-bonus data
  872.             sc->data[SC_CONCENTRATION]->val3 = sd->param_bonus[1]; //Agi
  873.             sc->data[SC_CONCENTRATION]->val4 = sd->param_bonus[4]; //Dex
  874.         }
  875.         if(sc->data[SC_SIEGFRIED]){
  876.             i = sc->data[SC_SIEGFRIED]->val2;
  877.             sd->subele[ELE_WATER] += i;
  878.             sd->subele[ELE_EARTH] += i;
  879.             sd->subele[ELE_FIRE] += i;
  880.             sd->subele[ELE_WIND] += i;
  881.             sd->subele[ELE_POISON] += i;
  882.             sd->subele[ELE_HOLY] += i;
  883.             sd->subele[ELE_DARK] += i;
  884.             sd->subele[ELE_GHOST] += i;
  885.             sd->subele[ELE_UNDEAD] += i;
  886.         }
  887.         if(sc->data[SC_PROVIDENCE]){
  888.             sd->subele[ELE_HOLY] += sc->data[SC_PROVIDENCE]->val2;
  889.             sd->subrace[RC_DEMON] += sc->data[SC_PROVIDENCE]->val2;
  890.         }
  891.         if(sc->data[SC_ARMORPROPERTY]) {    //This status change should grant card-type elemental resist.
  892.             sd->subele[ELE_WATER] += sc->data[SC_ARMORPROPERTY]->val1;
  893.             sd->subele[ELE_EARTH] += sc->data[SC_ARMORPROPERTY]->val2;
  894.             sd->subele[ELE_FIRE] += sc->data[SC_ARMORPROPERTY]->val3;
  895.             sd->subele[ELE_WIND] += sc->data[SC_ARMORPROPERTY]->val4;
  896.         }
  897.         if(sc->data[SC_ARMOR_RESIST]) { // Undead Scroll
  898.             sd->subele[ELE_WATER] += sc->data[SC_ARMOR_RESIST]->val1;
  899.             sd->subele[ELE_EARTH] += sc->data[SC_ARMOR_RESIST]->val2;
  900.             sd->subele[ELE_FIRE] += sc->data[SC_ARMOR_RESIST]->val3;
  901.             sd->subele[ELE_WIND] += sc->data[SC_ARMOR_RESIST]->val4;
  902.         }
  903.         if( sc->data[SC_FIRE_CLOAK_OPTION] ) {
  904.             i = sc->data[SC_FIRE_CLOAK_OPTION]->val2;
  905.             sd->subele[ELE_FIRE] += i;
  906.             sd->subele[ELE_WATER] -= i;
  907.         }
  908.         if( sc->data[SC_WATER_DROP_OPTION] ) {
  909.             i = sc->data[SC_WATER_DROP_OPTION]->val2;
  910.             sd->subele[ELE_WATER] += i;
  911.             sd->subele[ELE_WIND] -= i;
  912.         }
  913.         if( sc->data[SC_WIND_CURTAIN_OPTION] ) {
  914.             i = sc->data[SC_WIND_CURTAIN_OPTION]->val2;
  915.             sd->subele[ELE_WIND] += i;
  916.             sd->subele[ELE_EARTH] -= i;
  917.         }
  918.         if( sc->data[SC_STONE_SHIELD_OPTION] ) {
  919.             i = sc->data[SC_STONE_SHIELD_OPTION]->val2;
  920.             sd->subele[ELE_EARTH] += i;
  921.             sd->subele[ELE_FIRE] -= i;
  922.         }
  923.         if( sc->data[SC_MTF_MLEATKED] )
  924.             sd->subele[ELE_NEUTRAL] += 2;
  925.         if( sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3 )
  926.             sd->magic_addele[ELE_FIRE] += 25;
  927.         if( sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3 )
  928.             sd->magic_addele[ELE_WATER] += 25;
  929.         if( sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 3 )
  930.             sd->magic_addele[ELE_WIND] += 25;
  931.         if( sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3 )
  932.             sd->magic_addele[ELE_EARTH] += 25;
  933.     }
  934.     status_cpy(&sd->battle_status, bstatus);
  935.  
  936.     // ----- CLIENT-SIDE REFRESH -----
  937.     if(!sd->bl.prev) {
  938.         //Will update on LoadEndAck
  939.         calculating = 0;
  940.         return 0;
  941.     }
  942.     if(memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill)))
  943.         clif->skillinfoblock(sd);
  944.     if(b_weight != sd->weight)
  945.         clif->updatestatus(sd,SP_WEIGHT);
  946.     if(b_max_weight != sd->max_weight) {
  947.         clif->updatestatus(sd,SP_MAXWEIGHT);
  948.         pc->updateweightstatus(sd);
  949.     }
  950.     if( b_cart_weight_max != sd->cart_weight_max ) {
  951.         clif->updatestatus(sd,SP_CARTINFO);
  952.     }
  953.  
  954.     calculating = 0;
  955.  
  956.     return 0;
  957. }
  958.  
  959. /* called when a item with combo is worn */
  960. int pc_checkcombo_mine(struct map_session_data *sd, struct item_data *data ) {
  961.     int i, j, k, z;
  962.     int index, success = 0;
  963.     struct pc_combos *combo;
  964.  
  965.     for( i = 0; i < data->combos_count; i++ ) {
  966.  
  967.         /* ensure this isn't a duplicate combo */
  968.         if( sd->combos != NULL ) {
  969.             int x;
  970.            
  971.             ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id );
  972.  
  973.             /* found a match, skip this combo */
  974.             if( x < sd->combo_count )
  975.                 continue;
  976.         }
  977.  
  978.         for( j = 0; j < data->combos[i]->count; j++ ) {
  979.             int id = data->combos[i]->nameid[j];
  980.             bool found = false;
  981.  
  982.             for( k = 0; k < EQI_MAX; k++ ) {
  983.                 index = sd->equip_index[k];
  984.                 if( index < 0 ) continue;
  985.                 if( k == EQI_HAND_R   &&  sd->equip_index[EQI_HAND_L] == index ) continue;
  986.                 if( k == EQI_HEAD_MID &&  sd->equip_index[EQI_HEAD_LOW] == index ) continue;
  987.                 if( k == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index) ) continue;
  988.  
  989.                 if( (int)MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) == reserved_costume_id ) continue;
  990.  
  991.                 if(!sd->inventory_data[index])
  992.                     continue;
  993.                
  994.                 if ( itemdb_type(id) != IT_CARD ) {
  995.                     if ( sd->inventory_data[index]->nameid != id )
  996.                         continue;
  997.  
  998.                     found = true;
  999.                     break;
  1000.                 } else { //Cards
  1001.                     if ( sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0]) )
  1002.                         continue;
  1003.  
  1004.                     for (z = 0; z < sd->inventory_data[index]->slot; z++) {
  1005.  
  1006.                         if (sd->status.inventory[index].card[z] != id)
  1007.                             continue;
  1008.  
  1009.                         // We have found a match
  1010.                         found = true;
  1011.                         break;
  1012.                     }
  1013.                 }
  1014.  
  1015.             }
  1016.  
  1017.             if( !found )
  1018.                 break;/* we haven't found all the ids for this combo, so we can return */
  1019.         }
  1020.  
  1021.         /* means we broke out of the count loop w/o finding all ids, we can move to the next combo */
  1022.         if( j < data->combos[i]->count )
  1023.             continue;
  1024.  
  1025.         /* we got here, means all items in the combo are matching */
  1026.  
  1027.         RECREATE(sd->combos, struct pc_combos, ++sd->combo_count);
  1028.        
  1029.         combo = &sd->combos[sd->combo_count - 1];
  1030.        
  1031.         combo->bonus = data->combos[i]->script;
  1032.         combo->id = data->combos[i]->id;
  1033.        
  1034.         success++;
  1035.     }
  1036.     return success;
  1037. }
  1038.  
  1039. int HPM_map_reqnickdb(struct map_session_data * sd, int *char_id) {
  1040.  
  1041.     if( !sd ) return 0;
  1042.  
  1043.     if( reserved_costume_id && reserved_costume_id == *char_id ) {
  1044.         clif->solved_charname(sd->fd, *char_id, "Costume");
  1045.     }
  1046.     hookStop();
  1047.     return 1;
  1048. }
  1049.  
  1050. int HPM_pc_equippoint(int ret, struct map_session_data *sd, int *nn) {
  1051.     int char_id = 0, n = *nn;
  1052.  
  1053.     if (!sd)
  1054.         return 0;
  1055.  
  1056.     if (!ret) // If the original function returned zero, we don't need to process it anymore
  1057.         return 0;
  1058.  
  1059.     if( reserved_costume_id &&
  1060.         sd->status.inventory[n].card[0] == CARD0_CREATE &&
  1061.         (char_id = MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3])) == reserved_costume_id )
  1062.     { // Costume Item - Converted
  1063.         if( ret&EQP_HEAD_TOP ) { ret &= ~EQP_HEAD_TOP; ret |= EQP_COSTUME_HEAD_TOP; }
  1064.         if( ret&EQP_HEAD_LOW ) { ret &= ~EQP_HEAD_LOW; ret |= EQP_COSTUME_HEAD_LOW; }
  1065.         if( ret&EQP_HEAD_MID ) { ret &= ~EQP_HEAD_MID; ret |= EQP_COSTUME_HEAD_MID; }
  1066.     }
  1067.     return ret;
  1068. }
  1069.  
  1070. ACMD(costumeitem) {
  1071.     char item_name[100];
  1072.     int item_id, flag = 0;
  1073.     struct item item_tmp;
  1074.     struct item_data *item_data;
  1075.  
  1076.     if( !sd ) return 0;
  1077.  
  1078.     if (!message || !*message || (
  1079.         sscanf(message, "\"%99[^\"]\"", item_name) < 1 &&
  1080.         sscanf(message, "%99s", item_name) < 1 )) {
  1081.             clif->message(fd, "Please enter an item name or ID (usage: @costumeitem <item name/ID>).");
  1082.             return false;
  1083.     }
  1084.  
  1085.     if ((item_data = itemdb->search_name(item_name)) == NULL &&
  1086.         (item_data = itemdb->exists(atoi(item_name))) == NULL) {
  1087.             clif->message(fd, "Invalid item ID or name.");
  1088.             return false;
  1089.     }
  1090.  
  1091.     if( !reserved_costume_id ) {
  1092.             clif->message(fd, "Costume conversion is disabled.");
  1093.             return false;
  1094.     }
  1095.     if( !(item_data->equip&EQP_HEAD_LOW) &&
  1096.         !(item_data->equip&EQP_HEAD_MID) &&
  1097.         !(item_data->equip&EQP_HEAD_TOP) &&
  1098.         !(item_data->equip&EQP_COSTUME_HEAD_LOW) &&
  1099.         !(item_data->equip&EQP_COSTUME_HEAD_MID) &&
  1100.         !(item_data->equip&EQP_COSTUME_HEAD_TOP) ) {
  1101.             clif->message(fd, "You cannot costume this item. Costume only work for headgears.");
  1102.             return false;
  1103.         }
  1104.  
  1105.     item_id = item_data->nameid;
  1106.     //Check if it's stackable.
  1107.     if (!itemdb->isstackable2(item_data)) {
  1108.         if( (item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR) ) {
  1109.             clif->message(fd, "Cannot create costume pet eggs or pet armors.");
  1110.             return false;
  1111.         }
  1112.     }
  1113.  
  1114.     // if not pet egg
  1115.     if (!pet->create_egg(sd, item_id)) {
  1116.         memset(&item_tmp, 0, sizeof(item_tmp));
  1117.         item_tmp.nameid = item_id;
  1118.         item_tmp.identify = 1;
  1119.         item_tmp.card[0] = CARD0_CREATE;
  1120.         item_tmp.card[2] = GetWord(reserved_costume_id, 0);
  1121.         item_tmp.card[3] = GetWord(reserved_costume_id, 1);
  1122.  
  1123.         if ((flag = pc->additem(sd, &item_tmp, 1, LOG_TYPE_COMMAND)))
  1124.             clif->additem(sd, 0, 0, flag);
  1125.     }
  1126.  
  1127.     if (flag == 0)
  1128.         clif->message(fd,"item created.");
  1129.     return true;
  1130. }
  1131.  
  1132. /*==========================================
  1133.  * Costume Items Hercules/[Mhalicot]
  1134.  *------------------------------------------*/
  1135. BUILDIN(costume) {
  1136.     int i = -1, num, ep;
  1137.     TBL_PC *sd;
  1138.  
  1139.     num = script_getnum(st,2); // Equip Slot
  1140.     sd = script->rid2sd(st);
  1141.  
  1142.     if( sd == NULL )
  1143.         return 0;
  1144.     if( num > 0 && num <= ARRAYLENGTH(script->equip) )
  1145.         i = pc->checkequip(sd, script->equip[num - 1]);
  1146.     if( i < 0 )
  1147.         return 0;
  1148.     ep = sd->status.inventory[i].equip;
  1149.     if( !(ep&EQP_HEAD_LOW) && !(ep&EQP_HEAD_MID) && !(ep&EQP_HEAD_TOP) )
  1150.         return 0;
  1151.  
  1152.     logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i],sd->inventory_data[i]);
  1153.     pc->unequipitem(sd,i,2);
  1154.     clif->delitem(sd,i,1,3);
  1155.     // --------------------------------------------------------------------
  1156.     sd->status.inventory[i].refine = 0;
  1157.     sd->status.inventory[i].attribute = 0;
  1158.     sd->status.inventory[i].card[0] = CARD0_CREATE;
  1159.     sd->status.inventory[i].card[1] = 0;
  1160.     sd->status.inventory[i].card[2] = GetWord(reserved_costume_id, 0);
  1161.     sd->status.inventory[i].card[3] = GetWord(reserved_costume_id, 1);
  1162.  
  1163.     if( ep&EQP_HEAD_TOP ) { ep &= ~EQP_HEAD_TOP; ep |= EQP_COSTUME_HEAD_TOP; }
  1164.     if( ep&EQP_HEAD_LOW ) { ep &= ~EQP_HEAD_LOW; ep |= EQP_COSTUME_HEAD_LOW; }
  1165.     if( ep&EQP_HEAD_MID ) { ep &= ~EQP_HEAD_MID; ep |= EQP_COSTUME_HEAD_MID; }
  1166.     // --------------------------------------------------------------------
  1167.     logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i],sd->inventory_data[i]);
  1168.  
  1169.     clif->additem(sd,i,1,0);
  1170.     pc->equipitem(sd,i,ep);
  1171.     clif->misceffect(&sd->bl,3);
  1172.  
  1173.     return true;
  1174. }
  1175.  
  1176. /* triggered when server starts loading, before any server-specific data is set */
  1177. HPExport void server_preinit (void) {
  1178.     /* makes map server listen to mysetting:value in any "battleconf" file (including imported or custom ones) */
  1179.     /* value is not limited to numbers, its passed to our plugins handler (parse_my_setting) as const char *,
  1180.      * and thus can be manipulated at will */
  1181.     addBattleConf("parse_my_setting",parse_my_setting);
  1182. };
  1183.  
  1184. /* Server Startup */
  1185. HPExport void plugin_init (void) {
  1186.     //iMalloc = GET_SYMBOL("iMalloc");
  1187.     //script = GET_SYMBOL("script");
  1188.     //  status = GET_SYMBOL("status");
  1189.     //battle = GET_SYMBOL("battle");
  1190.     //itemdb = GET_SYMBOL("itemdb");
  1191.     //logs = GET_SYMBOL("logs");
  1192.     //clif = GET_SYMBOL("clif");
  1193.     //pet = GET_SYMBOL("pet");
  1194.     //map = GET_SYMBOL("map");
  1195.     //pc = GET_SYMBOL("pc");
  1196.    
  1197.     status->calc_pc_ = status_calc_mine;
  1198.     pc->checkcombo = pc_checkcombo_mine;
  1199.         //Hook
  1200.     addHookPre("map->reqnickdb",HPM_map_reqnickdb);
  1201.     addHookPost("pc->equippoint",HPM_pc_equippoint);
  1202.    
  1203.         //atCommand
  1204.     addAtcommand("costumeitem",costumeitem);
  1205.  
  1206.         //scriptCommand
  1207.     addScriptCommand("costume","i",costume);
  1208. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement