Advertisement
victorbh

Costume Item Plugin

Aug 16th, 2015
342
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 40.74 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_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->dbs->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->dbs->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->dbs->refine_info[wlv].bonus[r-1] / 100;
  303. #endif
  304.  
  305.             //Overrefine bonus.
  306.             if (r)
  307.                 wd->overrefine =  status->dbs->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->dbs->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->dbs->atkmods[0][sd->weapontype1];
  478.     sd->right_weapon.atkmods[1] = status->dbs->atkmods[1][sd->weapontype1];
  479.     sd->right_weapon.atkmods[2] = status->dbs->atkmods[2][sd->weapontype1];
  480.     sd->left_weapon.atkmods[0] = status->dbs->atkmods[0][sd->weapontype2];
  481.     sd->left_weapon.atkmods[1] = status->dbs->atkmods[1][sd->weapontype2];
  482.     sd->left_weapon.atkmods[2] = status->dbs->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->dbs->job_bonus[index][i])
  498.             continue;
  499.         switch(status->dbs->job_bonus[index][i]) {
  500.            
  501.             case 1: bstatus->str++; break;
  502.             case 2: bstatus->agi++; break;
  503.             case 3: bstatus->vit++; break;
  504.             case 4: bstatus->int_++; break;
  505.             case 5: bstatus->dex++; break;
  506.             case 6: bstatus->luk++; break;
  507.         }
  508.     }
  509.  
  510.     // If a Super Novice has never died and is at least joblv 70, he gets all stats +10
  511.     if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->die_counter == 0 && sd->status.job_level >= 70) {
  512.         bstatus->str += 10;
  513.         bstatus->agi += 10;
  514.         bstatus->vit += 10;
  515.         bstatus->int_+= 10;
  516.         bstatus->dex += 10;
  517.         bstatus->luk += 10;
  518.     }
  519.  
  520.     // Absolute modifiers from passive skills
  521.     if(pc->checkskill(sd,BS_HILTBINDING)>0)
  522.         bstatus->str++;
  523.     if((skill_lv=pc->checkskill(sd,SA_DRAGONOLOGY))>0)
  524.         bstatus->int_ += (skill_lv+1)/2; // +1 INT / 2 lv
  525.     if((skill_lv=pc->checkskill(sd,AC_OWL))>0)
  526.         bstatus->dex += skill_lv;
  527.     if((skill_lv = pc->checkskill(sd,RA_RESEARCHTRAP))>0)
  528.         bstatus->int_ += skill_lv;
  529.  
  530.     // Bonuses from cards and equipment as well as base stat, remember to avoid overflows.
  531.     i = bstatus->str + sd->status.str + sd->param_bonus[0] + sd->param_equip[0];
  532.     bstatus->str = cap_value(i,0,USHRT_MAX);
  533.     i = bstatus->agi + sd->status.agi + sd->param_bonus[1] + sd->param_equip[1];
  534.     bstatus->agi = cap_value(i,0,USHRT_MAX);
  535.     i = bstatus->vit + sd->status.vit + sd->param_bonus[2] + sd->param_equip[2];
  536.     bstatus->vit = cap_value(i,0,USHRT_MAX);
  537.     i = bstatus->int_+ sd->status.int_+ sd->param_bonus[3] + sd->param_equip[3];
  538.     bstatus->int_ = cap_value(i,0,USHRT_MAX);
  539.     i = bstatus->dex + sd->status.dex + sd->param_bonus[4] + sd->param_equip[4];
  540.     bstatus->dex = cap_value(i,0,USHRT_MAX);
  541.     i = bstatus->luk + sd->status.luk + sd->param_bonus[5] + sd->param_equip[5];
  542.     bstatus->luk = cap_value(i,0,USHRT_MAX);
  543.  
  544.     // ------ BASE ATTACK CALCULATION ------
  545.  
  546.     // Base batk value is set on status->calc_misc
  547.     // weapon-type bonus (FIXME: Why is the weapon_atk bonus applied to base attack?)
  548.     if (sd->status.weapon < MAX_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon])
  549.         bstatus->batk += sd->weapon_atk[sd->status.weapon];
  550.     // Absolute modifiers from passive skills
  551. #ifndef RENEWAL
  552.     if((skill_lv=pc->checkskill(sd,BS_HILTBINDING))>0) // it doesn't work in RE.
  553.         bstatus->batk += 4;
  554. #endif
  555.  
  556.     // ----- HP MAX CALCULATION -----
  557.  
  558.     // Basic MaxHP value
  559.     //We hold the standard Max HP here to make it faster to recalculate on vit changes.
  560.     sd->status.max_hp = status->get_base_maxhp(sd,bstatus);
  561.     //This is done to handle underflows from negative Max HP bonuses
  562.     i64 = sd->status.max_hp + (int)bstatus->max_hp;
  563.     bstatus->max_hp = (unsigned int)cap_value(i64, 0, INT_MAX);
  564.  
  565.     // Absolute modifiers from passive skills
  566.     if((skill_lv=pc->checkskill(sd,CR_TRUST))>0)
  567.         bstatus->max_hp += skill_lv*200;
  568.  
  569.     // Apply relative modifiers from equipment
  570.     if(sd->hprate < 0)
  571.         sd->hprate = 0;
  572.     if(sd->hprate!=100)
  573.         bstatus->max_hp = APPLY_RATE(bstatus->max_hp, sd->hprate);
  574.     if(battle->bc->hp_rate != 100)
  575.         bstatus->max_hp = APPLY_RATE(bstatus->max_hp, battle->bc->hp_rate);
  576.  
  577.     if(bstatus->max_hp > (unsigned int)battle->bc->max_hp)
  578.         bstatus->max_hp = battle->bc->max_hp;
  579.     else if(!bstatus->max_hp)
  580.         bstatus->max_hp = 1;
  581.  
  582.     // ----- SP MAX CALCULATION -----
  583.  
  584.     // Basic MaxSP value
  585.     sd->status.max_sp = status->get_base_maxsp(sd,bstatus);
  586.     //This is done to handle underflows from negative Max SP bonuses
  587.     i64 = sd->status.max_sp + (int)bstatus->max_sp;
  588.     bstatus->max_sp = (unsigned int)cap_value(i64, 0, INT_MAX);
  589.  
  590.     // Absolute modifiers from passive skills
  591.     if((skill_lv=pc->checkskill(sd,SL_KAINA))>0)
  592.         bstatus->max_sp += 30*skill_lv;
  593.     if((skill_lv=pc->checkskill(sd,HP_MEDITATIO))>0)
  594.         bstatus->max_sp += (int64)bstatus->max_sp * skill_lv/100;
  595.     if((skill_lv=pc->checkskill(sd,HW_SOULDRAIN))>0)
  596.         bstatus->max_sp += (int64)bstatus->max_sp * 2*skill_lv/100;
  597.     if( (skill_lv = pc->checkskill(sd,RA_RESEARCHTRAP)) > 0 )
  598.         bstatus->max_sp += 200 + 20 * skill_lv;
  599.     if( (skill_lv = pc->checkskill(sd,WM_LESSON)) > 0 )
  600.         bstatus->max_sp += 30 * skill_lv;
  601.  
  602.  
  603.     // Apply relative modifiers from equipment
  604.     if(sd->sprate < 0)
  605.         sd->sprate = 0;
  606.     if(sd->sprate!=100)
  607.         bstatus->max_sp = APPLY_RATE(bstatus->max_sp, sd->sprate);
  608.     if(battle->bc->sp_rate != 100)
  609.         bstatus->max_sp = APPLY_RATE(bstatus->max_sp, battle->bc->sp_rate);
  610.  
  611.     if(bstatus->max_sp > (unsigned int)battle->bc->max_sp)
  612.         bstatus->max_sp = battle->bc->max_sp;
  613.     else if(!bstatus->max_sp)
  614.         bstatus->max_sp = 1;
  615.  
  616.     // ----- RESPAWN HP/SP -----
  617.     //
  618.     //Calc respawn hp and store it on base_status
  619.     if (sd->special_state.restart_full_recover)
  620.     {
  621.         bstatus->hp = bstatus->max_hp;
  622.         bstatus->sp = bstatus->max_sp;
  623.     } else {
  624.         if((sd->class_&MAPID_BASEMASK) == MAPID_NOVICE && !(sd->class_&JOBL_2)
  625.             && battle->bc->restart_hp_rate < 50)
  626.             bstatus->hp = bstatus->max_hp>>1;
  627.         else
  628.             bstatus->hp = APPLY_RATE(bstatus->max_hp, battle->bc->restart_hp_rate);
  629.         if(!bstatus->hp)
  630.             bstatus->hp = 1;
  631.  
  632.         bstatus->sp = APPLY_RATE(bstatus->max_sp, battle->bc->restart_sp_rate);
  633.  
  634.         if( !bstatus->sp ) /* the minimum for the respawn setting is SP:1 */
  635.             bstatus->sp = 1;
  636.     }
  637.  
  638.     // ----- MISC CALCULATION -----
  639.     status->calc_misc(&sd->bl, bstatus, sd->status.base_level);
  640.  
  641.     //Equipment modifiers for misc settings
  642.     if(sd->matk_rate < 0)
  643.         sd->matk_rate = 0;
  644.  
  645.     if(sd->matk_rate != 100){
  646.         bstatus->matk_max = bstatus->matk_max * sd->matk_rate/100;
  647.         bstatus->matk_min = bstatus->matk_min * sd->matk_rate/100;
  648.     }
  649.  
  650.     if(sd->hit_rate < 0)
  651.         sd->hit_rate = 0;
  652.     if(sd->hit_rate != 100)
  653.         bstatus->hit = bstatus->hit * sd->hit_rate/100;
  654.  
  655.     if(sd->flee_rate < 0)
  656.         sd->flee_rate = 0;
  657.     if(sd->flee_rate != 100)
  658.         bstatus->flee = bstatus->flee * sd->flee_rate/100;
  659.  
  660.     if(sd->def2_rate < 0)
  661.         sd->def2_rate = 0;
  662.     if(sd->def2_rate != 100)
  663.         bstatus->def2 = bstatus->def2 * sd->def2_rate/100;
  664.  
  665.     if(sd->mdef2_rate < 0)
  666.         sd->mdef2_rate = 0;
  667.     if(sd->mdef2_rate != 100)
  668.         bstatus->mdef2 = bstatus->mdef2 * sd->mdef2_rate/100;
  669.  
  670.     if(sd->critical_rate < 0)
  671.         sd->critical_rate = 0;
  672.     if(sd->critical_rate != 100)
  673.         bstatus->cri = bstatus->cri * sd->critical_rate/100;
  674.  
  675.     if(sd->flee2_rate < 0)
  676.         sd->flee2_rate = 0;
  677.     if(sd->flee2_rate != 100)
  678.         bstatus->flee2 = bstatus->flee2 * sd->flee2_rate/100;
  679.  
  680.     // ----- HIT CALCULATION -----
  681.  
  682.     // Absolute modifiers from passive skills
  683. #ifndef RENEWAL
  684.     if((skill_lv=pc->checkskill(sd,BS_WEAPONRESEARCH))>0) // is this correct in pre? there is already hitrate bonus in battle.c
  685.         bstatus->hit += skill_lv*2;
  686. #endif
  687.     if((skill_lv=pc->checkskill(sd,AC_VULTURE))>0) {
  688. #ifndef RENEWAL
  689.         bstatus->hit += skill_lv;
  690. #endif
  691.         if(sd->status.weapon == W_BOW)
  692.             bstatus->rhw.range += skill_lv;
  693.     }
  694.     if(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE) {
  695.         if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0)
  696.             bstatus->hit += 2*skill_lv;
  697.         if((skill_lv=pc->checkskill(sd,GS_SNAKEEYE))>0) {
  698.             bstatus->hit += skill_lv;
  699.             bstatus->rhw.range += skill_lv;
  700.         }
  701.     }
  702.     if( (sd->status.weapon == W_1HAXE || sd->status.weapon == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0 )
  703.         bstatus->hit += 3*skill_lv;
  704.     if((sd->status.weapon == W_MACE || sd->status.weapon == W_2HMACE) && ((skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0))
  705.         bstatus->hit += 2*skill_lv;
  706.  
  707.     // ----- FLEE CALCULATION -----
  708.  
  709.     // Absolute modifiers from passive skills
  710.     if((skill_lv=pc->checkskill(sd,TF_MISS))>0)
  711.         bstatus->flee += skill_lv*(sd->class_&JOBL_2 && (sd->class_&MAPID_BASEMASK) == MAPID_THIEF? 4 : 3);
  712.     if((skill_lv=pc->checkskill(sd,MO_DODGE))>0)
  713.         bstatus->flee += (skill_lv*3)>>1;
  714.     // ----- EQUIPMENT-DEF CALCULATION -----
  715.  
  716.     // Apply relative modifiers from equipment
  717.     if(sd->def_rate < 0)
  718.         sd->def_rate = 0;
  719.     if(sd->def_rate != 100) {
  720.         i =  bstatus->def * sd->def_rate/100;
  721.         bstatus->def = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX);
  722.     }
  723.  
  724.     if( pc_ismadogear(sd) && (skill_lv = pc->checkskill(sd,NC_MAINFRAME)) > 0 )
  725.         bstatus->def += 20 + 20 * skill_lv;
  726.  
  727. #ifndef RENEWAL
  728.     if (!battle->bc->weapon_defense_type && bstatus->def > battle->bc->max_def) {
  729.         bstatus->def2 += battle->bc->over_def_bonus*(bstatus->def -battle->bc->max_def);
  730.         bstatus->def = (unsigned char)battle->bc->max_def;
  731.     }
  732. #endif
  733.  
  734.     // ----- EQUIPMENT-MDEF CALCULATION -----
  735.  
  736.     // Apply relative modifiers from equipment
  737.     if(sd->mdef_rate < 0)
  738.         sd->mdef_rate = 0;
  739.     if(sd->mdef_rate != 100) {
  740.         i =  bstatus->mdef * sd->mdef_rate/100;
  741.         bstatus->mdef = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX);
  742.     }
  743.  
  744. #ifndef RENEWAL
  745.     if (!battle->bc->magic_defense_type && bstatus->mdef > battle->bc->max_def) {
  746.         bstatus->mdef2 += battle->bc->over_def_bonus*(bstatus->mdef -battle->bc->max_def);
  747.         bstatus->mdef = (signed char)battle->bc->max_def;
  748.     }
  749. #endif
  750.  
  751.     // ----- ASPD CALCULATION -----
  752.     // Unlike other stats, ASPD rate modifiers from skills/SCs/items/etc are first all added together, then the final modifier is applied
  753.  
  754.     // Basic ASPD value
  755.     i = status->base_amotion_pc(sd,bstatus);
  756.     bstatus->amotion = cap_value(i,((sd->class_&JOBL_THIRD) ? battle->bc->max_third_aspd : battle->bc->max_aspd),2000);
  757.  
  758.     // Relative modifiers from passive skills
  759. #ifndef RENEWAL_ASPD
  760.     if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK)
  761.         bstatus->aspd_rate -= 5*skill_lv;
  762.     if((skill_lv = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd))
  763.         bstatus->aspd_rate -= 30*skill_lv;
  764.     if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
  765.         (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE))
  766.         bstatus->aspd_rate -= ((skill_lv+1)/2) * 10;
  767.     if(pc_isridingpeco(sd))
  768.         bstatus->aspd_rate += 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
  769.     else if(pc_isridingdragon(sd))
  770.         bstatus->aspd_rate += 250-50*pc->checkskill(sd,RK_DRAGONTRAINING);
  771. #else // needs more info
  772.     if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK)
  773.         bstatus->aspd_rate += 5*skill_lv;
  774.     if((skill_lv = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd))
  775.         bstatus->aspd_rate += 30*skill_lv;
  776.     if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
  777.         (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE))
  778.         bstatus->aspd_rate += ((skill_lv+1)/2) * 10;
  779.     if(pc_isridingpeco(sd))
  780.         bstatus->aspd_rate -= 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
  781.     else if(pc_isridingdragon(sd))
  782.         bstatus->aspd_rate -= 250-50*pc->checkskill(sd,RK_DRAGONTRAINING);
  783. #endif
  784.     bstatus->adelay = 2*bstatus->amotion;
  785.  
  786.  
  787.     // ----- DMOTION -----
  788.     //
  789.     i =  800-bstatus->agi*4;
  790.     bstatus->dmotion = cap_value(i, 400, 800);
  791.     if(battle->bc->pc_damage_delay_rate != 100)
  792.         bstatus->dmotion = bstatus->dmotion*battle->bc->pc_damage_delay_rate/100;
  793.  
  794.     // ----- MISC CALCULATIONS -----
  795.  
  796.     // Weight
  797.     if((skill_lv=pc->checkskill(sd,MC_INCCARRY))>0)
  798.         sd->max_weight += 2000*skill_lv;
  799.     if(pc_isridingpeco(sd) && pc->checkskill(sd,KN_RIDING)>0)
  800.         sd->max_weight += 10000;
  801.     else if(pc_isridingdragon(sd))
  802.         sd->max_weight += 5000+2000*pc->checkskill(sd,RK_DRAGONTRAINING);
  803.     if(sc->data[SC_KNOWLEDGE])
  804.         sd->max_weight += sd->max_weight*sc->data[SC_KNOWLEDGE]->val1/10;
  805.     if((skill_lv=pc->checkskill(sd,ALL_INCCARRY))>0)
  806.         sd->max_weight += 2000*skill_lv;
  807.  
  808.     sd->cart_weight_max = battle->bc->max_cart_weight + (pc->checkskill(sd, GN_REMODELING_CART)*5000);
  809.  
  810.     if (pc->checkskill(sd,SM_MOVINGRECOVERY)>0)
  811.         sd->regen.state.walk = 1;
  812.     else
  813.         sd->regen.state.walk = 0;
  814.  
  815.     // Skill SP cost
  816.     if((skill_lv=pc->checkskill(sd,HP_MANARECHARGE))>0 )
  817.         sd->dsprate -= 4*skill_lv;
  818.  
  819.     if(sc->data[SC_SERVICEFORYOU])
  820.         sd->dsprate -= sc->data[SC_SERVICEFORYOU]->val3;
  821.  
  822.     if(sc->data[SC_ATKER_BLOOD])
  823.         sd->dsprate -= sc->data[SC_ATKER_BLOOD]->val1;
  824.  
  825.     //Underflow protections.
  826.     if(sd->dsprate < 0)
  827.         sd->dsprate = 0;
  828.     if(sd->castrate < 0)
  829.         sd->castrate = 0;
  830.     if(sd->delayrate < 0)
  831.         sd->delayrate = 0;
  832.     if(sd->hprecov_rate < 0)
  833.         sd->hprecov_rate = 0;
  834.     if(sd->sprecov_rate < 0)
  835.         sd->sprecov_rate = 0;
  836.  
  837.     // Anti-element and anti-race
  838.     if((skill_lv=pc->checkskill(sd,CR_TRUST))>0)
  839.         sd->subele[ELE_HOLY] += skill_lv*5;
  840.     if((skill_lv=pc->checkskill(sd,BS_SKINTEMPER))>0) {
  841.         sd->subele[ELE_NEUTRAL] += skill_lv;
  842.         sd->subele[ELE_FIRE] += skill_lv*4;
  843.     }
  844.     if((skill_lv=pc->checkskill(sd,NC_RESEARCHFE))>0) {
  845.         sd->subele[ELE_EARTH] += skill_lv*10;
  846.         sd->subele[ELE_FIRE] += skill_lv*10;
  847.     }
  848.     if((skill_lv=pc->checkskill(sd,SA_DRAGONOLOGY))>0 ) {
  849. #ifdef RENEWAL
  850.         skill_lv = skill_lv*2;
  851. #else
  852.         skill_lv = skill_lv*4;
  853. #endif
  854.         sd->right_weapon.addrace[RC_DRAGON]+=skill_lv;
  855.         sd->left_weapon.addrace[RC_DRAGON]+=skill_lv;
  856.         sd->magic_addrace[RC_DRAGON]+=skill_lv;
  857.         sd->subrace[RC_DRAGON]+=skill_lv;
  858.     }
  859.  
  860.     if( (skill_lv = pc->checkskill(sd, AB_EUCHARISTICA)) > 0 ) {
  861.         sd->right_weapon.addrace[RC_DEMON] += skill_lv;
  862.         sd->right_weapon.addele[ELE_DARK] += skill_lv;
  863.         sd->left_weapon.addrace[RC_DEMON] += skill_lv;
  864.         sd->left_weapon.addele[ELE_DARK] += skill_lv;
  865.         sd->magic_addrace[RC_DEMON] += skill_lv;
  866.         sd->magic_addele[ELE_DARK] += skill_lv;
  867.         sd->subrace[RC_DEMON] += skill_lv;
  868.         sd->subele[ELE_DARK] += skill_lv;
  869.     }
  870.  
  871.     if(sc->count) {
  872.         if(sc->data[SC_CONCENTRATION]) { //Update the card-bonus data
  873.             sc->data[SC_CONCENTRATION]->val3 = sd->param_bonus[1]; //Agi
  874.             sc->data[SC_CONCENTRATION]->val4 = sd->param_bonus[4]; //Dex
  875.         }
  876.         if(sc->data[SC_SIEGFRIED]){
  877.             i = sc->data[SC_SIEGFRIED]->val2;
  878.             sd->subele[ELE_WATER] += i;
  879.             sd->subele[ELE_EARTH] += i;
  880.             sd->subele[ELE_FIRE] += i;
  881.             sd->subele[ELE_WIND] += i;
  882.             sd->subele[ELE_POISON] += i;
  883.             sd->subele[ELE_HOLY] += i;
  884.             sd->subele[ELE_DARK] += i;
  885.             sd->subele[ELE_GHOST] += i;
  886.             sd->subele[ELE_UNDEAD] += i;
  887.         }
  888.         if(sc->data[SC_PROVIDENCE]){
  889.             sd->subele[ELE_HOLY] += sc->data[SC_PROVIDENCE]->val2;
  890.             sd->subrace[RC_DEMON] += sc->data[SC_PROVIDENCE]->val2;
  891.         }
  892.         if(sc->data[SC_ARMORPROPERTY]) {    //This status change should grant card-type elemental resist.
  893.             sd->subele[ELE_WATER] += sc->data[SC_ARMORPROPERTY]->val1;
  894.             sd->subele[ELE_EARTH] += sc->data[SC_ARMORPROPERTY]->val2;
  895.             sd->subele[ELE_FIRE] += sc->data[SC_ARMORPROPERTY]->val3;
  896.             sd->subele[ELE_WIND] += sc->data[SC_ARMORPROPERTY]->val4;
  897.         }
  898.         if(sc->data[SC_ARMOR_RESIST]) { // Undead Scroll
  899.             sd->subele[ELE_WATER] += sc->data[SC_ARMOR_RESIST]->val1;
  900.             sd->subele[ELE_EARTH] += sc->data[SC_ARMOR_RESIST]->val2;
  901.             sd->subele[ELE_FIRE] += sc->data[SC_ARMOR_RESIST]->val3;
  902.             sd->subele[ELE_WIND] += sc->data[SC_ARMOR_RESIST]->val4;
  903.         }
  904.         if( sc->data[SC_FIRE_CLOAK_OPTION] ) {
  905.             i = sc->data[SC_FIRE_CLOAK_OPTION]->val2;
  906.             sd->subele[ELE_FIRE] += i;
  907.             sd->subele[ELE_WATER] -= i;
  908.         }
  909.         if( sc->data[SC_WATER_DROP_OPTION] ) {
  910.             i = sc->data[SC_WATER_DROP_OPTION]->val2;
  911.             sd->subele[ELE_WATER] += i;
  912.             sd->subele[ELE_WIND] -= i;
  913.         }
  914.         if( sc->data[SC_WIND_CURTAIN_OPTION] ) {
  915.             i = sc->data[SC_WIND_CURTAIN_OPTION]->val2;
  916.             sd->subele[ELE_WIND] += i;
  917.             sd->subele[ELE_EARTH] -= i;
  918.         }
  919.         if( sc->data[SC_STONE_SHIELD_OPTION] ) {
  920.             i = sc->data[SC_STONE_SHIELD_OPTION]->val2;
  921.             sd->subele[ELE_EARTH] += i;
  922.             sd->subele[ELE_FIRE] -= i;
  923.         }
  924.         if( sc->data[SC_MTF_MLEATKED] )
  925.             sd->subele[ELE_NEUTRAL] += 2;
  926.         if( sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3 )
  927.             sd->magic_addele[ELE_FIRE] += 25;
  928.         if( sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3 )
  929.             sd->magic_addele[ELE_WATER] += 25;
  930.         if( sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 3 )
  931.             sd->magic_addele[ELE_WIND] += 25;
  932.         if( sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3 )
  933.             sd->magic_addele[ELE_EARTH] += 25;
  934.     }
  935.     status_cpy(&sd->battle_status, bstatus);
  936.  
  937.     // ----- CLIENT-SIDE REFRESH -----
  938.     if(!sd->bl.prev) {
  939.         //Will update on LoadEndAck
  940.         calculating = 0;
  941.         return 0;
  942.     }
  943.     if(memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill)))
  944.         clif->skillinfoblock(sd);
  945.     if(b_weight != sd->weight)
  946.         clif->updatestatus(sd,SP_WEIGHT);
  947.     if(b_max_weight != sd->max_weight) {
  948.         clif->updatestatus(sd,SP_MAXWEIGHT);
  949.         pc->updateweightstatus(sd);
  950.     }
  951.     if( b_cart_weight_max != sd->cart_weight_max ) {
  952.         clif->updatestatus(sd,SP_CARTINFO);
  953.     }
  954.  
  955.     calculating = 0;
  956.  
  957.     return 0;
  958. }
  959.  
  960. /* called when a item with combo is worn */
  961. int pc_checkcombo_mine(struct map_session_data *sd, struct item_data *data ) {
  962.     int i, j, k, z;
  963.     int index, success = 0;
  964.     struct pc_combos *combo;
  965.  
  966.     for( i = 0; i < data->combos_count; i++ ) {
  967.  
  968.         /* ensure this isn't a duplicate combo */
  969.         if( sd->combos != NULL ) {
  970.             int x;
  971.            
  972.             ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id );
  973.  
  974.             /* found a match, skip this combo */
  975.             if( x < sd->combo_count )
  976.                 continue;
  977.         }
  978.  
  979.         for( j = 0; j < data->combos[i]->count; j++ ) {
  980.             int id = data->combos[i]->nameid[j];
  981.             bool found = false;
  982.  
  983.             for( k = 0; k < EQI_MAX; k++ ) {
  984.                 index = sd->equip_index[k];
  985.                 if( index < 0 ) continue;
  986.                 if( k == EQI_HAND_R   &&  sd->equip_index[EQI_HAND_L] == index ) continue;
  987.                 if( k == EQI_HEAD_MID &&  sd->equip_index[EQI_HEAD_LOW] == index ) continue;
  988.                 if( k == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index) ) continue;
  989.  
  990.                 if( (int)MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) == reserved_costume_id ) continue;
  991.  
  992.                 if(!sd->inventory_data[index])
  993.                     continue;
  994.                
  995.                 if ( itemdb_type(id) != IT_CARD ) {
  996.                     if ( sd->inventory_data[index]->nameid != id )
  997.                         continue;
  998.  
  999.                     found = true;
  1000.                     break;
  1001.                 } else { //Cards
  1002.                     if ( sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0]) )
  1003.                         continue;
  1004.  
  1005.                     for (z = 0; z < sd->inventory_data[index]->slot; z++) {
  1006.  
  1007.                         if (sd->status.inventory[index].card[z] != id)
  1008.                             continue;
  1009.  
  1010.                         // We have found a match
  1011.                         found = true;
  1012.                         break;
  1013.                     }
  1014.                 }
  1015.  
  1016.             }
  1017.  
  1018.             if( !found )
  1019.                 break;/* we haven't found all the ids for this combo, so we can return */
  1020.         }
  1021.  
  1022.         /* means we broke out of the count loop w/o finding all ids, we can move to the next combo */
  1023.         if( j < data->combos[i]->count )
  1024.             continue;
  1025.  
  1026.         /* we got here, means all items in the combo are matching */
  1027.  
  1028.         RECREATE(sd->combos, struct pc_combos, ++sd->combo_count);
  1029.        
  1030.         combo = &sd->combos[sd->combo_count - 1];
  1031.        
  1032.         combo->bonus = data->combos[i]->script;
  1033.         combo->id = data->combos[i]->id;
  1034.        
  1035.         success++;
  1036.     }
  1037.     return success;
  1038. }
  1039.  
  1040. int HPM_map_reqnickdb(struct map_session_data * sd, int *char_id) {
  1041.  
  1042.     if( !sd ) return 0;
  1043.  
  1044.     if( reserved_costume_id && reserved_costume_id == *char_id ) {
  1045.         clif->solved_charname(sd->fd, *char_id, "Costume");
  1046.     }
  1047.     hookStop();
  1048.     return 1;
  1049. }
  1050.  
  1051. int HPM_pc_equippoint(int ret, struct map_session_data *sd, int *nn) {
  1052.     int char_id = 0, n = *nn;
  1053.  
  1054.     if (!sd)
  1055.         return 0;
  1056.  
  1057.     if (!ret) // If the original function returned zero, we don't need to process it anymore
  1058.         return 0;
  1059.  
  1060.     if( reserved_costume_id &&
  1061.         sd->status.inventory[n].card[0] == CARD0_CREATE &&
  1062.         (char_id = MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3])) == reserved_costume_id )
  1063.     { // Costume Item - Converted
  1064.         if( ret&EQP_HEAD_TOP ) { ret &= ~EQP_HEAD_TOP; ret |= EQP_COSTUME_HEAD_TOP; }
  1065.         if( ret&EQP_HEAD_LOW ) { ret &= ~EQP_HEAD_LOW; ret |= EQP_COSTUME_HEAD_LOW; }
  1066.         if( ret&EQP_HEAD_MID ) { ret &= ~EQP_HEAD_MID; ret |= EQP_COSTUME_HEAD_MID; }
  1067.     }
  1068.     return ret;
  1069. }
  1070.  
  1071. ACMD(costumeitem) {
  1072.     char item_name[100];
  1073.     int item_id, flag = 0;
  1074.     struct item item_tmp;
  1075.     struct item_data *item_data;
  1076.  
  1077.     if( !sd ) return 0;
  1078.  
  1079.     if (!message || !*message || (
  1080.         sscanf(message, "\"%99[^\"]\"", item_name) < 1 &&
  1081.         sscanf(message, "%99s", item_name) < 1 )) {
  1082.             clif->message(fd, "Please enter an item name or ID (usage: @costumeitem <item name/ID>).");
  1083.             return false;
  1084.     }
  1085.  
  1086.     if ((item_data = itemdb->search_name(item_name)) == NULL &&
  1087.         (item_data = itemdb->exists(atoi(item_name))) == NULL) {
  1088.             clif->message(fd, "Invalid item ID or name.");
  1089.             return false;
  1090.     }
  1091.  
  1092.     if( !reserved_costume_id ) {
  1093.             clif->message(fd, "Costume conversion is disabled.");
  1094.             return false;
  1095.     }
  1096.     if( !(item_data->equip&EQP_HEAD_LOW) &&
  1097.         !(item_data->equip&EQP_HEAD_MID) &&
  1098.         !(item_data->equip&EQP_HEAD_TOP) &&
  1099.         !(item_data->equip&EQP_COSTUME_HEAD_LOW) &&
  1100.         !(item_data->equip&EQP_COSTUME_HEAD_MID) &&
  1101.         !(item_data->equip&EQP_COSTUME_HEAD_TOP) ) {
  1102.             clif->message(fd, "You cannot costume this item. Costume only work for headgears.");
  1103.             return false;
  1104.         }
  1105.  
  1106.     item_id = item_data->nameid;
  1107.     //Check if it's stackable.
  1108.     if (!itemdb->isstackable2(item_data)) {
  1109.         if( (item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR) ) {
  1110.             clif->message(fd, "Cannot create costume pet eggs or pet armors.");
  1111.             return false;
  1112.         }
  1113.     }
  1114.  
  1115.     // if not pet egg
  1116.     if (!pet->create_egg(sd, item_id)) {
  1117.         memset(&item_tmp, 0, sizeof(item_tmp));
  1118.         item_tmp.nameid = item_id;
  1119.         item_tmp.identify = 1;
  1120.         item_tmp.card[0] = CARD0_CREATE;
  1121.         item_tmp.card[2] = GetWord(reserved_costume_id, 0);
  1122.         item_tmp.card[3] = GetWord(reserved_costume_id, 1);
  1123.  
  1124.         if ((flag = pc->additem(sd, &item_tmp, 1, LOG_TYPE_COMMAND)))
  1125.             clif->additem(sd, 0, 0, flag);
  1126.     }
  1127.  
  1128.     if (flag == 0)
  1129.         clif->message(fd,"item created.");
  1130.     return true;
  1131. }
  1132.  
  1133. /*==========================================
  1134.  * Costume Items Hercules/[Mhalicot]
  1135.  *------------------------------------------*/
  1136. BUILDIN(costume) {
  1137.     int i = -1, num, ep;
  1138.     TBL_PC *sd;
  1139.  
  1140.     num = script_getnum(st,2); // Equip Slot
  1141.     sd = script->rid2sd(st);
  1142.  
  1143.     if( sd == NULL )
  1144.         return 0;
  1145.     if( num > 0 && num <= ARRAYLENGTH(script->equip) )
  1146.         i = pc->checkequip(sd, script->equip[num - 1]);
  1147.     if( i < 0 )
  1148.         return 0;
  1149.     ep = sd->status.inventory[i].equip;
  1150.     if( !(ep&EQP_HEAD_LOW) && !(ep&EQP_HEAD_MID) && !(ep&EQP_HEAD_TOP) )
  1151.         return 0;
  1152.  
  1153.     logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i],sd->inventory_data[i]);
  1154.     pc->unequipitem(sd,i,2);
  1155.     clif->delitem(sd,i,1,3);
  1156.     // --------------------------------------------------------------------
  1157.     sd->status.inventory[i].refine = 0;
  1158.     sd->status.inventory[i].attribute = 0;
  1159.     sd->status.inventory[i].card[0] = CARD0_CREATE;
  1160.     sd->status.inventory[i].card[1] = 0;
  1161.     sd->status.inventory[i].card[2] = GetWord(reserved_costume_id, 0);
  1162.     sd->status.inventory[i].card[3] = GetWord(reserved_costume_id, 1);
  1163.  
  1164.     if( ep&EQP_HEAD_TOP ) { ep &= ~EQP_HEAD_TOP; ep |= EQP_COSTUME_HEAD_TOP; }
  1165.     if( ep&EQP_HEAD_LOW ) { ep &= ~EQP_HEAD_LOW; ep |= EQP_COSTUME_HEAD_LOW; }
  1166.     if( ep&EQP_HEAD_MID ) { ep &= ~EQP_HEAD_MID; ep |= EQP_COSTUME_HEAD_MID; }
  1167.     // --------------------------------------------------------------------
  1168.     logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i],sd->inventory_data[i]);
  1169.  
  1170.     clif->additem(sd,i,1,0);
  1171.     pc->equipitem(sd,i,ep);
  1172.     clif->misceffect(&sd->bl,3);
  1173.  
  1174.     return true;
  1175. }
  1176.  
  1177. /* triggered when server starts loading, before any server-specific data is set */
  1178. HPExport void server_preinit (void) {
  1179.     /* makes map server listen to mysetting:value in any "battleconf" file (including imported or custom ones) */
  1180.     /* value is not limited to numbers, its passed to our plugins handler (parse_my_setting) as const char *,
  1181.      * and thus can be manipulated at will */
  1182.     addBattleConf("parse_my_setting",parse_my_setting);
  1183. };
  1184.  
  1185. /* Server Startup */
  1186. HPExport void plugin_init (void) {
  1187.     //iMalloc = GET_SYMBOL("iMalloc");
  1188.     //script = GET_SYMBOL("script");
  1189.     //  status = GET_SYMBOL("status");
  1190.     //battle = GET_SYMBOL("battle");
  1191.     //itemdb = GET_SYMBOL("itemdb");
  1192.     //logs = GET_SYMBOL("logs");
  1193.     //clif = GET_SYMBOL("clif");
  1194.     //pet = GET_SYMBOL("pet");
  1195.     //map = GET_SYMBOL("map");
  1196.     //pc = GET_SYMBOL("pc");
  1197.    
  1198.     status->calc_pc_ = status_calc_mine;
  1199.     pc->checkcombo = pc_checkcombo_mine;
  1200.         //Hook
  1201.     addHookPre("map->reqnickdb",HPM_map_reqnickdb);
  1202.     addHookPost("pc->equippoint",HPM_pc_equippoint);
  1203.    
  1204.         //atCommand
  1205.     addAtcommand("costumeitem",costumeitem);
  1206.  
  1207.         //scriptCommand
  1208.     addScriptCommand("costume","i",costume);
  1209. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement