Jump to content

Rebel

Members
  • Posts

    436
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by Rebel

  1. Ivion is a scripter on eAthena boards. Im sure someone fork or has her scripts lying around somewhere..
  2. Rebel

    MVP Board

    does anyone still have this? ty
  3. Rebel

    Disable Miracle

    Just put 0 and you're all set!
  4. Try this.. In skill.cpp add below: case WM_SATURDAY_NIGHT_FEVER: if( !mapdata_flag_vs(mapdata) ) { clif_skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails. return true; } break; this case TF_BACKSLIDING: case MO_BODYRELOCATION: if( sd && ( sd->sc.data[SC_RG_CCONFINE_S] || sd->sc.data[SC_ANKLESNARE] || sd->sc.data[SC_SPIDERWEB] ) ) { clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return true; } break; just add the Charge attack, Flying side kick, High jump and Shadow jump..
  5. skill.c? how outdated is your rathena?
  6. I have used this Git Hash: 3e1105b0cf8380b4e4646800305b59c3de0f96ea and its not working.. even the SG Parry dont work. ?
  7. Add the map that you want to disable in npc/mapflag/nowarp.txt
  8. What git hash of rathena are you using?
  9. Any working mod for this???
  10. Okay thank you. Will wait for it. BUMP! Any dev that can help? ? @vBrenth Not working. Still cant use 1 hand sword when soul linked..
  11. Requesting for a working Lord Knight Soul Link Modification.. If linked, LK_PARRYING skill can be used with One Handed Sword also. Tested all the available src mods here in forums but its not working.
  12. You sure you are the real Zephyrus? ?
  13. Pwede mo naman magawa yan manually. PM if need mo pa ng help.
  14. If killed by player: [Error]: buildin_getmonsterinfo: Wrong Monster ID: 2000000 [Debug]: Source (NPC): auto_ress_mvp (invisible/not on a map) If killed by monster: [Error]: buildin_getmonsterinfo: Wrong Monster ID: 110009749 [Debug]: Source (NPC): auto_ress_mvp (invisible/not on a map) But the player is resurrected after 5 seconds when apple is on inventory. (512 = Apple)
  15. Colosseum - PvP/GvG or Event Arena View File Join my facebook site at: https://www.facebook.com/OlroxMaps The whole main idea was to create a circular colosseum although the ambience style was intended to be a little different than this. I was inspired by the movie -gladiator- where there is a clandestine colosseum outside of Rome where slaves are forced to fight. Features: Rigging and animation in Palm Trees and Flags: This animation is based in bones/articulations and its working thanks by the GR2 project of animated mobs in 3D. They are loaded as none-clickeable NPC in game. Please watch the video to get what I mean! The circular core of the colosseum, the stairs, were made and texturized in 3D from scratch. Atm I'm focussing into the way Ragnarok has it textures which for me they tend to have a grainy surface and shadows on some edges. Thats what I did aswell Effects like sand, and a dense fog that you can see if you move the camera at a high zoom, gives the feeling I was looking for. Please I suggest you to watch the video. This map comes with animation that you can't see on screensshots Submitter Olrox Submitted 02/28/2014 Category Map  
  16. File Updated. Working with the Latest Commit 7f9f185
  17. Im using an old git hash.. and my battle.c is also modified. But I can send my battle.c if it can help.
  18. [root@server ~]# cd /home/rAthena [root@server rAthena]# gdb map-server core.2543 GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/rAthena/map-server...done. [New LWP 2543] Core was generated by `./map-server'. Program terminated with signal 11, Segmentation fault. #0 0x000000000042a512 in battle_calc_cardfix (attack_type=1, src=0x4bf2060, target=<optimized out>, nk=<optimized out>, rh_ele=<optimized out>, lh_ele=<optimized out>, damage=3167, left=0, flag=529) at battle.c:595 595 cardfix = cardfix * (100 + sd->magic_add race[tstatus->race] + sd->magic_addrace[RC_ALL] + sd->magic_addrace2[t_race2]) / 100; (gdb) bt full #0 0x000000000042a512 in battle_calc_cardfix (attack_type=1, src=0x4bf2060, target=<optimized out>, nk=<optimized out>, rh_ele=<optimized out>, lh_ele=<optimized out>, damage=3167, left=0, flag=529) at battle.c:595 sd = 0x4bf2060 tsd = <optimized out> cardfix = <optimized out> s_class = 4013 t_class = 4008 s_race2 = RC2_NONE t_race2 = <optimized out> s_defele = ELE_NEUTRAL sstatus = 0x4bf24e4 tstatus = 0x4a2fae4 original_damage = 3167 i = <optimized out> #1 0x00000000004372c7 in initialize_weapon_data (wflag=3167, skill_lv=<optimized out>, skill_id=0, target=0x4a2f660, src=0x4bf2060) at battle.c:5143 sstatus = 0x4a2f600 sc = 0x190 tstatus = 0x4a2fae4 sd = <optimized out> wd = {damage = <optimized out>, damage2 = <optimized out>, ---Type <return> to continue, or q <return> to quit---return type = DMG_NORMAL, div_ = <optimized out>, amotion = <optimized out>, dmotion = <optimized out>, blewcount = <optimized out>, flag = <optimized out>, miscflag = <optimized out>, dmg_lv = <optimized out>, isspdamage = <optimized out>} #2 battle_calc_weapon_attack (src=0x4bf2060, target=0x4a2f660, skill_id=<optimized out>, skill_lv=<optimized out>, wflag=3167) at battle.c:5266 sd = <optimized out> tsd = <optimized out> wd = {damage = 3167, damage2 = 830, type = DMG_NORMAL, div_ = 1, amotion = 30, dmotion = 400, blewcount = 0, flag = 529, miscflag = 0, dmg_lv = ATK_DEF, isspdamage = 0 '\000'} sc = 0x211 tstatus = 0x211 right_element = <optimized out> left_element = <optimized out> infdef = 0 '\000' __FUNCTION__.21951 = "battle_calc_weapon_attack" #3 0x000000000043c5b8 in battle_weapon_attack (src=0x7fff64e71ff0, target=0x4a2f660, tick=<optimized out>, flag=<optimized out>) at battle.c:7092 index = -31585 ---Type <return> to continue, or q <return> to quit---return sd = 0x4bf2060 tsd = <optimized out> sstatus = <optimized out> tstatus = <optimized out> sc = 0x4bf2540 tsc = 0x4a2fb40 damage = <optimized out> skillv = <optimized out> wd = {damage = 0, damage2 = 0, type = DMG_SIT_DOWN, div_ = 0, amotion = 659864132, dmotion = 13, blewcount = 14, flag = 15, miscflag = 659864132, dmg_lv = 32757, isspdamage = -126 '\202'} vanish_damage = 0 '\000' __FUNCTION__.22341 = "battle_weapon_attack" #4 0x00000000000e427d in ?? () No symbol table info available. #5 0x0000000004bf2060 in ?? () No symbol table info available. #6 0x0000000004a2f660 in ?? () No symbol table info available. #7 0x0000000004bf2080 in ?? () No symbol table info available. #8 0x0000000004bf2060 in ?? () No symbol table info available. ---Type <return> to continue, or q <return> to quit---return #9 0x0000000000000417 in ?? () No symbol table info available. #10 0x00000000000e427d in ?? () No symbol table info available. #11 0x0000000004bf2060 in ?? () No symbol table info available. #12 0x0000000004a2f660 in ?? () No symbol table info available. #13 0x0000000004bf2080 in ?? () No symbol table info available. #14 0x000000000055236a in unit_attack ( src=0x4e395e <skill_check_condition_mercenary+158>, target_id=0, continuous=77788768) at unit.c:2210 target = 0x4bf2060 ud = 0x4bf2060 range = <optimized out> #15 0x000000000000022d in ?? () No symbol table info available. #16 0x0000000004298560 in ?? () No symbol table info available. #17 0x00007ff52628113c in ?? () No symbol table info available. #18 0x00000000000e5b94 in ?? () ---Type <return> to continue, or q <return> to quit---return No symbol table info available. #19 0x00000000005ad7ba in get_uptime () at timer.c:405 No locals. #20 0x000e427e00000416 in ?? () No symbol table info available. #21 0x00000000028256f0 in ?? () No symbol table info available. #22 0x00007fff64e722a8 in ?? () No symbol table info available. #23 0x00000000028256f0 in ?? () No symbol table info available. #24 0x0000000000000002 in ?? () No symbol table info available. #25 0x0000000000000001 in ?? () No symbol table info available. #26 0x0000000000000000 in ?? () No symbol table info available. (gdb) battle.c int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int rh_ele, int lh_ele, int64 damage, int left, int flag){ struct map_session_data *sd, ///< Attacker session data if BL_PC *tsd; ///< Target session data if BL_PC short cardfix = 1000; enum e_classAE s_class, ///< Attacker class t_class; ///< Target class enum e_race2 s_race2, /// Attacker Race2 t_race2; ///< Target Race2 enum e_element s_defele; ///< Attacker Element (not a weapon or skill element!) struct status_data *sstatus, ///< Attacker status data *tstatus; ///< Target status data int64 original_damage; int i; if( !damage ) return 0; original_damage = damage; sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, target); t_class = (enum e_classAE)status_get_class(target); s_class = (enum e_classAE)status_get_class(src); sstatus = status_get_status_data(src); tstatus = status_get_status_data(target); s_race2 = status_get_race2(src); t_race2 = status_get_race2(target); s_defele = (tsd) ? (enum e_element)status_get_element(src) : ELE_NONE; //Official servers apply the cardfix value on a base of 1000 and round down the reduction/increase #define APPLY_CARDFIX(damage, fix) { (damage) = (damage) - (int64)(((damage) * (1000 - (fix))) / 1000); } switch( attack_type ) { case BF_MAGIC: // Affected by attacker ATK bonuses if( sd && !(nk&NK_NO_CARDFIX_ATK) ) { cardfix = cardfix * (100 + sd->magic_addrace[tstatus->race] + sd->magic_addrace[RC_ALL] + sd->magic_addrace2[t_race2]) / 100; if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses cardfix = cardfix * (100 + sd->magic_addele[tstatus->def_ele] + sd->magic_addele[ELE_ALL] + sd->magic_addele_script[tstatus->def_ele] + sd->magic_addele_script[ELE_ALL]) / 100; cardfix = cardfix * (100 + sd->magic_atk_ele[rh_ele] + sd->magic_atk_ele[ELE_ALL]) / 100; } cardfix = cardfix * (100 + sd->magic_addsize[tstatus->size] + sd->magic_addsize[SZ_ALL]) / 100; cardfix = cardfix * (100 + sd->magic_addclass[tstatus->class_] + sd->magic_addclass[CLASS_ALL]) / 100; for( i = 0; i < ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate; i++ ) { if( sd->add_mdmg[i].class_ == t_class ) { cardfix = cardfix * (100 + sd->add_mdmg[i].rate) / 100; break; } } APPLY_CARDFIX(damage, cardfix); } // Affected by target DEF bonuses if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) { cardfix = 1000; // reset var for target if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[rh_ele] + tsd->subele_script[ELE_ALL]; for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) { if( tsd->subele2[i].ele != rh_ele ) continue; if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK && ((tsd->subele2[i].flag)&flag)&BF_RANGEMASK && ((tsd->subele2[i].flag)&flag)&BF_SKILLMASK) ) continue; ele_fix += tsd->subele2[i].rate; } if (s_defele != ELE_NONE) ele_fix += tsd->subdefele[s_defele] + tsd->subdefele[ELE_ALL]; cardfix = cardfix * (100 - ele_fix) / 100; } cardfix = cardfix * (100 - tsd->subsize[sstatus->size] - tsd->subsize[SZ_ALL]) / 100; cardfix = cardfix * (100 - tsd->subrace2[s_race2]) / 100; cardfix = cardfix * (100 - tsd->subrace[sstatus->race] - tsd->subrace[RC_ALL]) / 100; cardfix = cardfix * (100 - tsd->subclass[sstatus->class_] - tsd->subclass[CLASS_ALL]) / 100; for( i = 0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate; i++ ) { if( tsd->add_mdef[i].class_ == s_class ) { cardfix = cardfix * (100 - tsd->add_mdef[i].rate) / 100; break; } } #ifndef RENEWAL //It was discovered that ranged defense also counts vs magic! [Skotlex] if( flag&BF_SHORT ) cardfix = cardfix * (100 - tsd->bonus.near_attack_def_rate) / 100; else cardfix = cardfix * (100 - tsd->bonus.long_attack_def_rate) / 100; #endif cardfix = cardfix * (100 - tsd->bonus.magic_def_rate) / 100; if( tsd->sc.data[SC_MDEF_RATE] ) cardfix = cardfix * (100 - tsd->sc.data[SC_MDEF_RATE]->val1) / 100; APPLY_CARDFIX(damage, cardfix); } break; case BF_WEAPON: // Affected by attacker ATK bonuses if( sd && !(nk&NK_NO_CARDFIX_ATK) && (left&2) ) { short cardfix_ = 1000; if( sd->state.arrow_atk ) { // Ranged attack cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->arrow_addrace[tstatus->race] + sd->right_weapon.addrace[RC_ALL] + sd->arrow_addrace[RC_ALL]) / 100; if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele] + sd->right_weapon.addele[ELE_ALL] + sd->arrow_addele[ELE_ALL]; for( i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++ ) { if( sd->right_weapon.addele2[i].ele != tstatus->def_ele ) continue; if( !(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK && ((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK && ((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) ) continue; ele_fix += sd->right_weapon.addele2[i].rate; } cardfix = cardfix * (100 + ele_fix) / 100; } cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size] + sd->arrow_addsize[tstatus->size] + sd->right_weapon.addsize[SZ_ALL] + sd->arrow_addsize[SZ_ALL]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addclass[tstatus->class_] + sd->arrow_addclass[tstatus->class_] + sd->right_weapon.addclass[CLASS_ALL] + sd->arrow_addclass[CLASS_ALL]) / 100; } else { // Melee attack int skill = 0; // Calculates each right & left hand weapon bonuses separatedly if( !battle_config.left_cardfix_to_right ) { // Right-handed weapon cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->right_weapon.addrace[RC_ALL]) / 100; if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->right_weapon.addele[ELE_ALL]; for( i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++ ) { if( sd->right_weapon.addele2[i].ele != tstatus->def_ele ) continue; if( !(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK && ((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK && ((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) ) continue; ele_fix += sd->right_weapon.addele2[i].rate; } cardfix = cardfix * (100 + ele_fix) / 100; } cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size] + sd->right_weapon.addsize[SZ_ALL]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addclass[tstatus->class_] + sd->right_weapon.addclass[CLASS_ALL]) / 100; if( left&1 ) { // Left-handed weapon cardfix_ = cardfix_ * (100 + sd->left_weapon.addrace[tstatus->race] + sd->left_weapon.addrace[RC_ALL]) / 100; if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[ELE_ALL]; for( i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++ ) { if( sd->left_weapon.addele2[i].ele != tstatus->def_ele ) continue; if( !(((sd->left_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK && ((sd->left_weapon.addele2[i].flag)&flag)&BF_RANGEMASK && ((sd->left_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) ) continue; ele_fix_lh += sd->left_weapon.addele2[i].rate; } cardfix_ = cardfix_ * (100 + ele_fix_lh) / 100; } cardfix_ = cardfix_ * (100 + sd->left_weapon.addsize[tstatus->size] + sd->left_weapon.addsize[SZ_ALL]) / 100; cardfix_ = cardfix_ * (100 + sd->left_weapon.addrace2[t_race2]) / 100; cardfix_ = cardfix_ * (100 + sd->left_weapon.addclass[tstatus->class_] + sd->left_weapon.addclass[CLASS_ALL]) / 100; } } // Calculates right & left hand weapon as unity else { //! CHECKME: If 'left_cardfix_to_right' is yes, doesn't need to check NK_NO_ELEFIX? //if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele] + sd->right_weapon.addele[ELE_ALL] + sd->left_weapon.addele[ELE_ALL]; for( i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++ ) { if( sd->right_weapon.addele2[i].ele != tstatus->def_ele ) continue; if( !(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK && ((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK && ((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) ) continue; ele_fix += sd->right_weapon.addele2[i].rate; } for( i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++ ) { if( sd->left_weapon.addele2[i].ele != tstatus->def_ele ) continue; if( !(((sd->left_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK && ((sd->left_weapon.addele2[i].flag)&flag)&BF_RANGEMASK && ((sd->left_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) ) continue; ele_fix += sd->left_weapon.addele2[i].rate; } cardfix = cardfix * (100 + ele_fix) / 100; //} cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->left_weapon.addrace[tstatus->race] + sd->right_weapon.addrace[RC_ALL] + sd->left_weapon.addrace[RC_ALL]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size] + sd->left_weapon.addsize[tstatus->size] + sd->right_weapon.addsize[SZ_ALL] + sd->left_weapon.addsize[SZ_ALL]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2] + sd->left_weapon.addrace2[t_race2]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addclass[tstatus->class_] + sd->left_weapon.addclass[tstatus->class_] + sd->right_weapon.addclass[CLASS_ALL] + sd->left_weapon.addclass[CLASS_ALL]) / 100; } if( sd->status.weapon == W_KATAR && (skill = pc_checkskill(sd,ASC_KATAR)) > 0 ) // Adv. Katar Mastery functions similar to a +%ATK card on official [helvetica] cardfix = cardfix * (100 + (10 + 2 * skill)) / 100; } //! CHECKME: These right & left hand weapon ignores 'left_cardfix_to_right'? for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ ) { if( sd->right_weapon.add_dmg[i].class_ == t_class ) { cardfix = cardfix * (100 + sd->right_weapon.add_dmg[i].rate) / 100; break; } } if( left&1 ) { for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ ) { if( sd->left_weapon.add_dmg[i].class_ == t_class ) { cardfix_ = cardfix_ * (100 + sd->left_weapon.add_dmg[i].rate) / 100; break; } } } #ifndef RENEWAL if( flag&BF_LONG ) cardfix = cardfix * (100 + sd->bonus.long_attack_atk_rate) / 100; #endif if (left&1) { APPLY_CARDFIX(damage, cardfix_); } else { APPLY_CARDFIX(damage, cardfix); } } // Affected by target DEF bonuses else if( tsd && !(nk&NK_NO_CARDFIX_DEF) && !(left&2) ) { if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[rh_ele] + tsd->subele_script[ELE_ALL]; for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) { if( tsd->subele2[i].ele != rh_ele ) continue; if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK && ((tsd->subele2[i].flag)&flag)&BF_RANGEMASK && ((tsd->subele2[i].flag)&flag)&BF_SKILLMASK) ) continue; ele_fix += tsd->subele2[i].rate; } cardfix = cardfix * (100 - ele_fix) / 100; if( left&1 && lh_ele != rh_ele ) { int ele_fix_lh = tsd->subele[lh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[lh_ele] + tsd->subele_script[ELE_ALL]; for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) { if( tsd->subele2[i].ele != lh_ele ) continue; if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK && ((tsd->subele2[i].flag)&flag)&BF_RANGEMASK && ((tsd->subele2[i].flag)&flag)&BF_SKILLMASK) ) continue; ele_fix_lh += tsd->subele2[i].rate; } cardfix = cardfix * (100 - ele_fix_lh) / 100; } cardfix = cardfix * (100 - tsd->subdefele[s_defele] - tsd->subdefele[ELE_ALL]) / 100; } cardfix = cardfix * (100 - tsd->subsize[sstatus->size] - tsd->subsize[SZ_ALL]) / 100; cardfix = cardfix * (100 - tsd->subrace2[s_race2]) / 100; cardfix = cardfix * (100 - tsd->subrace[sstatus->race] - tsd->subrace[RC_ALL]) / 100; cardfix = cardfix * (100 - tsd->subclass[sstatus->class_] - tsd->subclass[CLASS_ALL]) / 100; for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate; i++ ) { if( tsd->add_def[i].class_ == s_class ) { cardfix = cardfix * (100 - tsd->add_def[i].rate) / 100; break; } } if( flag&BF_SHORT ) cardfix = cardfix * (100 - tsd->bonus.near_attack_def_rate) / 100; else // BF_LONG (there's no other choice) cardfix = cardfix * (100 - tsd->bonus.long_attack_def_rate) / 100; if( tsd->sc.data[SC_DEF_RATE] ) cardfix = cardfix * (100 - tsd->sc.data[SC_DEF_RATE]->val1) / 100; APPLY_CARDFIX(damage, cardfix); } break; case BF_MISC: // Affected by target DEF bonuses if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) { if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[rh_ele] + tsd->subele_script[ELE_ALL]; for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) { if( tsd->subele2[i].ele != rh_ele ) continue; if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK && ((tsd->subele2[i].flag)&flag)&BF_RANGEMASK && ((tsd->subele2[i].flag)&flag)&BF_SKILLMASK)) continue; ele_fix += tsd->subele2[i].rate; } if (s_defele != ELE_NONE) ele_fix += tsd->subdefele[s_defele] + tsd->subdefele[ELE_ALL]; cardfix = cardfix * (100 - ele_fix) / 100; } cardfix = cardfix * (100 - tsd->subsize[sstatus->size] - tsd->subsize[SZ_ALL]) / 100; cardfix = cardfix * (100 - tsd->subrace2[s_race2]) / 100; cardfix = cardfix * (100 - tsd->subrace[sstatus->race] - tsd->subrace[RC_ALL]) / 100; cardfix = cardfix * (100 - tsd->subclass[sstatus->class_] - tsd->subclass[CLASS_ALL]) / 100; cardfix = cardfix * (100 - tsd->bonus.misc_def_rate) / 100; if( flag&BF_SHORT ) cardfix = cardfix * (100 - tsd->bonus.near_attack_def_rate) / 100; else // BF_LONG (there's no other choice) cardfix = cardfix * (100 - tsd->bonus.long_attack_def_rate) / 100; APPLY_CARDFIX(damage, cardfix); } break; } #undef APPLY_CARDFIX return (int)cap_value(damage - original_damage, INT_MIN, INT_MAX); } ...... static struct Damage initialize_weapon_data(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int wflag) { struct status_data *sstatus = status_get_status_data(src); struct status_data *tstatus = status_get_status_data(target); struct status_change *sc = status_get_sc(src); struct map_session_data *sd = BL_CAST(BL_PC, src); struct Damage wd; wd.type = DMG_NORMAL; //Normal attack wd.div_ = skill_id?skill_get_num(skill_id,skill_lv):1; wd.amotion = (skill_id && skill_get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. // counter attack DOES obey ASPD delay on official, uncomment if you want the old (bad) behavior [helvetica] /*if(skill_id == KN_AUTOCOUNTER) wd.amotion >>= 1; */ wd.dmotion = tstatus->dmotion; wd.blewcount =skill_get_blewcount(skill_id,skill_lv); wd.miscflag = wflag; wd.flag = BF_WEAPON; //Initial Flag wd.flag |= (skill_id||wd.miscflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish] wd.damage = wd.damage2 = #ifdef RENEWAL wd.statusAtk = wd.statusAtk2 = wd.equipAtk = wd.equipAtk2 = wd.weaponAtk = wd.weaponAtk2 = wd.masteryAtk = wd.masteryAtk2 = #endif 0; wd.dmg_lv=ATK_DEF; //This assumption simplifies the assignation later if(sd) wd.blewcount += battle_blewcount_bonus(sd, skill_id); if (skill_id) { wd.flag |= battle_range_type(src, target, skill_id, skill_lv); switch(skill_id) { case MH_SONIC_CRAW:{ TBL_HOM *hd = BL_CAST(BL_HOM,src); wd.div_ = hd->homunculus.spiritball; } break; case MO_FINGEROFFENSIVE: if(sd) { if (battle_config.finger_offensive_type) wd.div_ = 1; else wd.div_ = sd->spiritball_old; } break; case KN_PIERCE: case ML_PIERCE: wd.div_= (wd.div_>0?tstatus->size+1:-(tstatus->size+1)); break; case TF_DOUBLE: //For NPC used skill. case GS_CHAINACTION: wd.type = DMG_MULTI_HIT; break; case GS_GROUNDDRIFT: wd.amotion = sstatus->amotion; //Fall through case KN_SPEARSTAB: case KN_BOWLINGBASH: case MS_BOWLINGBASH: case MO_BALKYOUNG: case TK_TURNKICK: wd.blewcount = 0; break; case KN_AUTOCOUNTER: wd.flag = (wd.flag&~BF_SKILLMASK)|BF_NORMAL; break; case LK_SPIRALPIERCE: if (!sd) wd.flag = (wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC; break; // The number of hits is set to 3 by default for use in Inspiration status. // When in Banding, the number of hits is equal to the number of Royal Guards in Banding. case LG_HESPERUSLIT: if( sc && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 3 ) wd.div_ = sc->data[SC_BANDING]->val2; break; } } else { wd.flag |= is_skill_using_arrow(src, skill_id)?BF_LONG:BF_SHORT; } return wd; } ...... static struct Damage battle_calc_weapon_attack(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int wflag) { struct map_session_data *sd, *tsd; struct Damage wd; struct status_change *sc = status_get_sc(src); struct status_change *tsc = status_get_sc(target); struct status_data *tstatus = status_get_status_data(target); int right_element, left_element; bool infdef = false; memset(&wd,0,sizeof(wd)); if (src == NULL || target == NULL) { nullpo_info(NLP_MARK); return wd; } wd = initialize_weapon_data(src, target, skill_id, skill_lv, wflag); right_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_R, false); left_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_L, false); if (sc && !sc->count) sc = NULL; //Skip checking as there are no status changes active. if (tsc && !tsc->count) tsc = NULL; //Skip checking as there are no status changes active. sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, target); //Check for Lucky Dodge if ((!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2) { wd.type = DMG_LUCY_DODGE; wd.dmg_lv = ATK_LUCKY; if(wd.div_ < 0) wd.div_ *= -1; return wd; } // on official check for multi hit first so we can override crit on double attack [helvetica] wd = battle_calc_multi_attack(wd, src, target, skill_id, skill_lv); // crit check is next since crits always hit on official [helvetica] if (is_attack_critical(wd, src, target, skill_id, skill_lv, true)) wd.type = DMG_CRITICAL; // check if we're landing a hit if(!is_attack_hitting(wd, src, target, skill_id, skill_lv, true)) wd.dmg_lv = ATK_FLEE; else if(!(infdef = is_infinite_defense(target, wd.flag))) { //no need for math against plants int64 ratio = 0; int i = 0; wd = battle_calc_skill_base_damage(wd, src, target, skill_id, skill_lv); // base skill damage ratio = battle_calc_attack_skill_ratio(wd, src, target, skill_id, skill_lv); // skill level ratios ATK_RATE(wd.damage, wd.damage2, ratio); RE_ALLATK_RATE(wd, ratio); ratio = battle_calc_skill_constant_addition(wd, src, target, skill_id, skill_lv); // other skill bonuses ATK_ADD(wd.damage, wd.damage2, ratio); RE_ALLATK_ADD(wd, ratio); #ifdef RENEWAL if(skill_id == HW_MAGICCRASHER) { // Add weapon attack for MATK onto Magic Crasher struct status_data *sstatus = status_get_status_data(src); if (sstatus->matk_max > sstatus->matk_min) { ATK_ADD(wd.weaponAtk, wd.weaponAtk2, sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); } else ATK_ADD(wd.weaponAtk, wd.weaponAtk2, sstatus->matk_min); } #endif // add any miscellaneous player ATK bonuses if( sd && skill_id && (i = pc_skillatk_bonus(sd, skill_id))) { ATK_ADDRATE(wd.damage, wd.damage2, i); RE_ALLATK_ADDRATE(wd, i); } if (tsd && (i = pc_sub_skillatk_bonus(tsd, skill_id))) { ATK_ADDRATE(wd.damage, wd.damage2, -i); RE_ALLATK_ADDRATE(wd, -i); } #ifdef RENEWAL // In Renewal we only cardfix to the weapon and equip ATK //Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only" wd.weaponAtk += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.weaponAtk, 2, wd.flag); wd.equipAtk += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.equipAtk, 2, wd.flag); if (is_attack_left_handed(src, skill_id)) { wd.weaponAtk2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.weaponAtk2, 3, wd.flag); wd.equipAtk2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.equipAtk2, 3, wd.flag); } // final attack bonuses that aren't affected by cards wd = battle_attack_sc_bonus(wd, src, target, skill_id, skill_lv); if (sd) { //monsters, homuns and pets have their damage computed directly wd.damage = wd.statusAtk + wd.weaponAtk + wd.equipAtk + wd.masteryAtk; wd.damage2 = wd.statusAtk2 + wd.weaponAtk2 + wd.equipAtk2 + wd.masteryAtk2; if(wd.flag&BF_LONG && (skill_id != RA_WUGBITE && skill_id != RA_WUGSTRIKE)) //Long damage rate addition doesn't use weapon + equip attack ATK_ADDRATE(wd.damage, wd.damage2, sd->bonus.long_attack_atk_rate); } #else // final attack bonuses that aren't affected by cards wd = battle_attack_sc_bonus(wd, src, target, skill_id, skill_lv); #endif if (wd.damage + wd.damage2) { //Check if attack ignores DEF if(!attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L) || !attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R)) wd = battle_calc_defense_reduction(wd, src, target, skill_id, skill_lv); wd = battle_calc_attack_post_defense(wd, src, target, skill_id, skill_lv); } } #ifdef RENEWAL if(!sd) // monsters only have a single ATK for element, in pre-renewal we also apply element to entire ATK on players [helvetica] #endif wd = battle_calc_element_damage(wd, src, target, skill_id, skill_lv); if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS) return wd; //Enough, rest is not needed. #ifdef RENEWAL if (is_attack_critical(wd, src, target, skill_id, skill_lv, false)) { if (sd) { //Check for player so we don't crash out, monsters don't have bonus crit rates [helvetica] wd.damage = (int)floor((float)((wd.damage * 140) / 100 * (100 + sd->bonus.crit_atk_rate)) / 100); if (is_attack_left_handed(src, skill_id)) wd.damage2 = (int)floor((float)((wd.damage2 * 140) / 100 * (100 + sd->bonus.crit_atk_rate)) / 100); } else wd.damage = (int)floor((float)(wd.damage * 140) / 100); } #endif #ifndef RENEWAL if (skill_id == NJ_KUNAI) { short nk = battle_skill_get_damage_properties(skill_id, wd.miscflag); ATK_ADD(wd.damage, wd.damage2, 90); nk |= NK_IGNORE_DEF; } #endif switch (skill_id) { case TK_DOWNKICK: case TK_STORMKICK: case TK_TURNKICK: case TK_COUNTER: if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST) ATK_ADD(wd.damage, wd.damage2, 10 * pc_checkskill(sd, TK_RUN)); break; case SR_TIGERCANNON: // (Tiger Cannon skill level x 240) + (Target Base Level x 40) if (wd.miscflag&8) { ATK_ADD(wd.damage, wd.damage2, skill_lv * 500 + status_get_lv(target) * 40); } else ATK_ADD(wd.damage, wd.damage2, skill_lv * 240 + status_get_lv(target) * 40); break; case SR_GATEOFHELL: { struct status_data *sstatus = status_get_status_data(src); ATK_ADD(wd.damage, wd.damage2, sstatus->max_hp - status_get_hp(src)); if(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) { ATK_ADD(wd.damage, wd.damage2, (sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status_get_lv(src)); } else ATK_ADD(wd.damage, wd.damage2, (sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status_get_lv(src)); } break; } if(sd) { #ifndef RENEWAL uint16 skill; if ((skill = pc_checkskill(sd, BS_WEAPONRESEARCH)) > 0) ATK_ADD(wd.damage, wd.damage2, skill * 2); if (skill_id == TF_POISON) ATK_ADD(wd.damage, wd.damage2, 15 * skill_lv); if (skill_id == GS_GROUNDDRIFT) ATK_ADD(wd.damage, wd.damage2, 50 * skill_lv); if (skill_id != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus. ATK_ADD2(wd.damage, wd.damage2, ((wd.div_ < 1) ? 1 : wd.div_) * sd->right_weapon.star, ((wd.div_ < 1) ? 1 : wd.div_) * sd->left_weapon.star); if (skill_id != MC_CARTREVOLUTION && pc_checkskill(sd, BS_HILTBINDING) > 0) ATK_ADD(wd.damage, wd.damage2, 4); if (skill_id == MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex] ATK_ADD(wd.damage, wd.damage2, ((wd.div_ < 1) ? 1 : wd.div_) * sd->spiritball_old * 3); } else ATK_ADD(wd.damage, wd.damage2, ((wd.div_ < 1) ? 1 : wd.div_) * sd->spiritball * 3); #endif if( skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ) { //Refine bonus applies after cards and elements. short index = sd->equip_index[EQI_HAND_L]; if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR ) ATK_ADD(wd.damage, wd.damage2, 10*sd->inventory.u.items_inventory[index].refine); } #ifndef RENEWAL //Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only" switch(skill_id) { case RK_DRAGONBREATH: case RK_DRAGONBREATH_WATER: if(wd.flag&BF_LONG) { //Add check here, because we want to apply the same behavior in pre-renewal [exneval] wd.damage = wd.damage * (100 + sd->bonus.long_attack_atk_rate) / 100; if(is_attack_left_handed(src, skill_id)) wd.damage2 = wd.damage2 * (100 + sd->bonus.long_attack_atk_rate) / 100; } break; default: wd.damage += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage, 2, wd.flag); if( is_attack_left_handed(src, skill_id )) wd.damage2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage2, 3, wd.flag); break; } #endif } if(tsd) { // Card Fix for target (tsd), 2 is not added to the "left" flag meaning "target cards only" switch(skill_id) { #ifdef RENEWAL case NJ_ISSEN: case GS_MAGICALBULLET: case ASC_BREAKER: case CR_ACIDDEMONSTRATION: case GN_FIRE_EXPANSION_ACID: #endif case SO_VARETYR_SPEAR: break; //These skills will do a card fix later default: wd.damage += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage, 0, wd.flag); if(is_attack_left_handed(src, skill_id)) wd.damage2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage2, 1, wd.flag); break; } } #ifdef RENEWAL // forced to neutral skills [helvetica] // skills forced to neutral gain benefits from weapon element // but final damage is considered "neutral" and resistances are applied again switch (skill_id) { case MC_CARTREVOLUTION: case MO_INVESTIGATE: case CR_ACIDDEMONSTRATION: case SR_GATEOFHELL: case GN_FIRE_EXPANSION_ACID: case KO_BAKURETSU: // Forced to neutral element wd.damage = battle_attr_fix(src, target, wd.damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); break; case CR_SHIELDBOOMERANG: case LK_SPIRALPIERCE: case ML_SPIRALPIERCE: case PA_SHIELDCHAIN: case PA_SACRIFICE: case RK_DRAGONBREATH: case RK_DRAGONBREATH_WATER: case NC_SELFDESTRUCTION: case KO_HAPPOKUNAI: { int64 tmp = wd.damage; if (sd) { if (skill_id == PA_SHIELDCHAIN) { wd.damage = battle_attr_fix(src, target, wd.damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); if (wd.damage > 0) { wd.damage = battle_attr_fix(src, target, tmp, right_element, tstatus->def_ele, tstatus->ele_lv); if (!wd.damage) wd.damage = battle_attr_fix(src, target, tmp, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); } } else if (skill_id == KO_HAPPOKUNAI) { wd.damage = battle_attr_fix(src, target, wd.damage, (sd->bonus.arrow_ele) ? sd->bonus.arrow_ele : ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); if (wd.damage > 0) { wd.damage = battle_attr_fix(src, target, tmp, right_element, tstatus->def_ele, tstatus->ele_lv); if (!wd.damage) wd.damage = battle_attr_fix(src, target, tmp, (sd->bonus.arrow_ele) ? sd->bonus.arrow_ele : ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); } } else wd.damage = battle_attr_fix(src, target, wd.damage, right_element, tstatus->def_ele, tstatus->ele_lv); } } break; case GN_CARTCANNON: // Cart Cannon gets forced to element of cannon ball (neutral or holy/shadow/ghost) wd.damage = battle_attr_fix(src, target, wd.damage, (sd && sd->bonus.arrow_ele) ? sd->bonus.arrow_ele : ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); break; } // perform multihit calculations DAMAGE_DIV_FIX_RENEWAL(wd, wd.div_); #endif // only do 1 dmg to plant, no need to calculate rest if(infdef) return battle_calc_attack_plant(wd, src, target, skill_id, skill_lv); //Apply DAMAGE_DIV_FIX and check for min damage wd = battle_apply_div_fix(wd, skill_id); wd = battle_calc_attack_left_right_hands(wd, src, target, skill_id, skill_lv); switch (skill_id) { #ifdef RENEWAL case NJ_ISSEN: case GS_MAGICALBULLET: case ASC_BREAKER: case CR_ACIDDEMONSTRATION: case GN_FIRE_EXPANSION_ACID: #endif case SO_VARETYR_SPEAR: return wd; //These skills will do a GVG fix later default: wd = battle_calc_attack_gvg_bg(wd, src, target, skill_id, skill_lv); break; } wd = battle_calc_weapon_final_atk_modifiers(wd, src, target, skill_id, skill_lv); battle_absorb_damage(target, &wd); battle_do_reflect(BF_WEAPON,&wd, src, target, skill_id, skill_lv); //WIP [lighta] return wd; } ...... enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, unsigned int tick, int flag) { struct map_session_data *sd = NULL, *tsd = NULL; struct status_data *sstatus, *tstatus; struct status_change *sc, *tsc; int64 damage; int skillv; struct Damage wd; bool vanish_damage = false; nullpo_retr(ATK_NONE, src); nullpo_retr(ATK_NONE, target); if (src->prev == NULL || target->prev == NULL) return ATK_NONE; sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, target); sstatus = status_get_status_data(src); tstatus = status_get_status_data(target); sc = status_get_sc(src); tsc = status_get_sc(target); if (sc && !sc->count) //Avoid sc checks when there's none to check for. [Skotlex] sc = NULL; if (tsc && !tsc->count) tsc = NULL; if (sd) { sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)); if (sd->state.arrow_atk) { short index = sd->equip_index[EQI_AMMO]; if (index < 0) { if (sd->weapontype1 > W_KATAR && sd->weapontype1 < W_HUUMA) clif_skill_fail(sd,0,USESKILL_FAIL_NEED_MORE_BULLET,0); else clif_arrow_fail(sd,0); return ATK_NONE; } //Ammo check by Ishizu-chan if (sd->inventory_data[index]) { switch (sd->status.weapon) { case W_BOW: if (sd->inventory_data[index]->look != A_ARROW) { clif_arrow_fail(sd,0); return ATK_NONE; } break; case W_REVOLVER: case W_RIFLE: case W_GATLING: case W_SHOTGUN: if (sd->inventory_data[index]->look != A_BULLET) { clif_skill_fail(sd,0,USESKILL_FAIL_NEED_MORE_BULLET,0); return ATK_NONE; } break; case W_GRENADE: if (sd->inventory_data[index]->look != A_GRENADE) { clif_skill_fail(sd,0,USESKILL_FAIL_NEED_MORE_BULLET,0); return ATK_NONE; } break; } } } } if (sc && sc->count) { if (sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4 & 2)) status_change_end(src, SC_CLOAKING, INVALID_TIMER); else if (sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4 & 2)) status_change_end(src, SC_CLOAKINGEXCEED, INVALID_TIMER); } if (tsc && tsc->data[SC_AUTOCOUNTER] && status_check_skilluse(target, src, KN_AUTOCOUNTER, 1)) { uint8 dir = map_calc_dir(target,src->x,src->y); int t_dir = unit_getdir(target); int dist = distance_bl(src, target); if (dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) { uint16 skill_lv = tsc->data[SC_AUTOCOUNTER]->val1; clif_skillcastcancel(target); //Remove the casting bar. [Skotlex] clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, DMG_NORMAL, 0, false); //Display MISS. status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER); skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0); return ATK_BLOCK; } } if( tsc && tsc->data[SC_BLADESTOP_WAIT] && status_get_class_(src) != CLASS_BOSS && (src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->status.weapon == W_FIST ? 1 : 2)) ) { uint16 skill_lv = tsc->data[SC_BLADESTOP_WAIT]->val1; int duration = skill_get_time2(MO_BLADESTOP,skill_lv); status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER); if(sc_start4(src,src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) { //Target locked. clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, DMG_NORMAL, 0, false); //Display MISS. clif_bladestop(target, src->id, 1); sc_start4(src,target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration); return ATK_BLOCK; } } if(sd && (skillv = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0) { int triple_rate= 30 - skillv; //Base Rate if (sc && sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK) { triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100; status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); } if (rnd()%100 < triple_rate) { //Need to apply canact_tick here because it doesn't go through skill_castend_id sd->ud.canact_tick = max(tick + skill_delayfix(src, MO_TRIPLEATTACK, skillv), sd->ud.canact_tick); if( skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0) ) return ATK_DEF; return ATK_MISS; } } if (sc) { if (sc->data[SC_SACRIFICE]) { uint16 skill_lv = sc->data[SC_SACRIFICE]->val1; damage_lv ret_val; if( --sc->data[SC_SACRIFICE]->val2 <= 0 ) status_change_end(src, SC_SACRIFICE, INVALID_TIMER); /** * We need to calculate the DMG before the hp reduction, because it can kill the source. * For further information: bugreport:4950 */ ret_val = (damage_lv)skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,skill_lv,tick,0); status_zap(src, sstatus->max_hp*9/100, 0);//Damage to self is always 9% if( ret_val == ATK_NONE ) return ATK_MISS; return ret_val; } if (sc->data[SC_MAGICALATTACK]) { if( skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0) ) return ATK_DEF; return ATK_MISS; } if( sc->data[SC_GT_ENERGYGAIN] ) { int spheres = 5; if( sc->data[SC_RAISINGDRAGON] ) spheres += sc->data[SC_RAISINGDRAGON]->val1; if( sd && rnd()%100 < sc->data[SC_GT_ENERGYGAIN]->val2 ) pc_addspiritball(sd, skill_get_time2(SR_GENTLETOUCH_ENERGYGAIN, sc->data[SC_GT_ENERGYGAIN]->val1), spheres); } } if( tsc && tsc->data[SC_GT_ENERGYGAIN] ) { int spheres = 5; if( tsc->data[SC_RAISINGDRAGON] ) spheres += tsc->data[SC_RAISINGDRAGON]->val1; if( tsd && rnd()%100 < tsc->data[SC_GT_ENERGYGAIN]->val2 ) pc_addspiritball(tsd, skill_get_time2(SR_GENTLETOUCH_ENERGYGAIN, tsc->data[SC_GT_ENERGYGAIN]->val1), spheres); } if (tsc && tsc->data[SC_MTF_MLEATKED] && rnd()%100 < tsc->data[SC_MTF_MLEATKED]->val2) clif_skill_nodamage(target, target, SM_ENDURE, tsc->data[SC_MTF_MLEATKED]->val1, sc_start(src, target, SC_ENDURE, 100, tsc->data[SC_MTF_MLEATKED]->val1, skill_get_time(SM_ENDURE, tsc->data[SC_MTF_MLEATKED]->val1))); if(tsc && tsc->data[SC_KAAHI] && tstatus->hp < tstatus->max_hp && status_charge(target, 0, tsc->data[SC_KAAHI]->val3)) { int hp_heal = tstatus->max_hp - tstatus->hp; if (hp_heal > tsc->data[SC_KAAHI]->val2) hp_heal = tsc->data[SC_KAAHI]->val2; if (hp_heal) status_heal(target, hp_heal, 0, 2); } wd = battle_calc_attack(BF_WEAPON, src, target, 0, 0, flag); wd.isspdamage = false; // Default normal attacks to non-SP Damage attack until battle_vanish is determined if (sd && wd.damage + wd.damage2 > 0) vanish_damage = battle_vanish(sd, target, &wd); if( sc && sc->count ) { if (sc->data[SC_EXEEDBREAK]) { if (!is_infinite_defense(target, wd.flag) && !vanish_damage) wd.damage *= sc->data[SC_EXEEDBREAK]->val2 / 100; status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER); } if( sc->data[SC_SPELLFIST] ) { if( --(sc->data[SC_SPELLFIST]->val1) >= 0 && !vanish_damage ){ if (!is_infinite_defense(target, wd.flag)) { struct Damage ad = battle_calc_attack(BF_MAGIC, src, target, sc->data[SC_SPELLFIST]->val3, sc->data[SC_SPELLFIST]->val4, flag | BF_SHORT); wd.damage = ad.damage; DAMAGE_DIV_FIX(wd.damage, wd.div_); // Double the damage for multiple hits. } else { wd.damage = 1; DAMAGE_DIV_FIX(wd.damage, wd.div_); } } else status_change_end(src,SC_SPELLFIST,INVALID_TIMER); } if (sc->data[SC_GIANTGROWTH] && (wd.flag&BF_SHORT) && rnd()%100 < sc->data[SC_GIANTGROWTH]->val2 && !is_infinite_defense(target, wd.flag) && !vanish_damage) { wd.damage <<= 1; // Double Damage if (!sc->data[SC_CRUSHSTRIKE]) { // Increase damage again if Crush Strike is not active if (map_flag_vs(src->m)) // Only half of the 2.5x increase on versus-type maps wd.damage += wd.damage * 125 / 100; else wd.damage += wd.damage * 250 / 100; } } if( sd && battle_config.arrow_decrement && sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0) { short idx = sd->equip_index[EQI_AMMO]; if (idx >= 0 && sd->inventory.u.items_inventory[idx].amount >= sc->data[SC_FEARBREEZE]->val4) { pc_delitem(sd,idx,sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME); sc->data[SC_FEARBREEZE]->val4 = 0; } } } if (sd && sd->state.arrow_atk) //Consume arrow. battle_consume_ammo(sd, 0, 0); damage = wd.damage + wd.damage2; if( damage > 0 && src != target ) { if( sc && sc->data[SC_DUPLELIGHT] && (wd.flag&BF_SHORT) && rnd()%100 <= 10+2*sc->data[SC_DUPLELIGHT]->val1 ) { // Activates it only from melee damage uint16 skill_id; if( rnd()%2 == 1 ) skill_id = AB_DUPLELIGHT_MELEE; else skill_id = AB_DUPLELIGHT_MAGIC; skill_attack(skill_get_type(skill_id), src, src, target, skill_id, sc->data[SC_DUPLELIGHT]->val1, tick, SD_LEVEL); } } wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2, wd.isspdamage); if (sd && sd->bonus.splash_range > 0 && damage > 0) skill_castend_damage_id(src, target, 0, 1, tick, 0); if ( target->type == BL_SKILL && damage > 0 ) { TBL_SKILL *su = (TBL_SKILL*)target; if (su && su->group) { if (su->group->skill_id == HT_BLASTMINE) skill_blown(src, target, 3, -1, BLOWN_NONE); if (su->group->skill_id == GN_WALLOFTHORN) { if (--su->val2 <= 0) skill_delunit(su); } } } map_freeblock_lock(); if( !(tsc && tsc->data[SC_DEVOTION]) && !vanish_damage && skill_check_shadowform(target, damage, wd.div_) ) { if( !status_isdead(target) ) skill_additional_effect(src, target, 0, 0, wd.flag, wd.dmg_lv, tick); if( wd.dmg_lv > ATK_BLOCK ) skill_counter_additional_effect(src, target, 0, 0, wd.flag, tick); } else battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion, true, wd.isspdamage); if( tsc ) { if( tsc->data[SC_DEVOTION] ) { struct status_change_entry *sce = tsc->data[SC_DEVOTION]; struct block_list *d_bl = map_id2bl(sce->val1); if( d_bl && ( (d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == target->id) || (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id) ) && check_distance_bl(target, d_bl, sce->val3) ) { clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0, false); status_fix_damage(NULL, d_bl, damage, 0); } else status_change_end(target, SC_DEVOTION, INVALID_TIMER); } if (target->type == BL_PC && (wd.flag&BF_SHORT) && tsc->data[SC_CIRCLE_OF_FIRE_OPTION]) { struct elemental_data *ed = ((TBL_PC*)target)->ed; if (ed) { clif_skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, DMG_SKILL); skill_attack(BF_WEAPON,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag); } } if (tsc->data[SC_WATER_SCREEN_OPTION]) { struct block_list *e_bl = map_id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1); if (e_bl && !status_isdead(e_bl)) { clif_damage(e_bl, e_bl, tick, 0, 0, damage, wd.div_, DMG_NORMAL, 0, false); status_fix_damage(NULL, e_bl, damage, 0); } } } if (sc && sc->data[SC_AUTOSPELL] && rnd()%100 < sc->data[SC_AUTOSPELL]->val4) { int sp = 0; uint16 skill_id = sc->data[SC_AUTOSPELL]->val2; uint16 skill_lv = sc->data[SC_AUTOSPELL]->val3; int i = rnd()%100; if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_SAGE) i = 0; //Max chance, no skill_lv reduction. [Skotlex] //reduction only for skill_lv > 1 if (skill_lv > 1) { if (i >= 50) skill_lv /= 2; else if (i >= 15) skill_lv--; } sp = skill_get_sp(skill_id,skill_lv) * 2 / 3; if (status_charge(src, 0, sp)) { struct unit_data *ud = unit_bl2ud(src); switch (skill_get_casttype(skill_id)) { case CAST_GROUND: skill_castend_pos2(src, target->x, target->y, skill_id, skill_lv, tick, flag); break; case CAST_NODAMAGE: skill_castend_nodamage_id(src, target, skill_id, skill_lv, tick, flag); break; case CAST_DAMAGE: skill_castend_damage_id(src, target, skill_id, skill_lv, tick, flag); break; } if (ud) { int autospell_tick = skill_delayfix(src, skill_id, skill_lv); if (DIFF_TICK(ud->canact_tick, tick + autospell_tick) < 0) { ud->canact_tick = max(tick + autospell_tick, ud->canact_tick); if (battle_config.display_status_timers && sd) clif_status_change(src, SI_ACTIONDELAY, 1, autospell_tick, 0, 0, 0); } } } } if (sd) { uint16 r_skill = 0, sk_idx = 0; if( wd.flag&BF_SHORT && sc && sc->data[SC__AUTOSHADOWSPELL] && rnd()%100 < sc->data[SC__AUTOSHADOWSPELL]->val3 && (r_skill = (uint16)sc->data[SC__AUTOSHADOWSPELL]->val1) && (sk_idx = skill_get_index(r_skill)) && sd->status.skill[sk_idx].id != 0 && sd->status.skill[sk_idx].flag == SKILL_FLAG_PLAGIARIZED ) { int r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2; if (r_skill != AL_HOLYLIGHT && r_skill != PR_MAGNUS) { int type; if( (type = skill_get_casttype(r_skill)) == CAST_GROUND ) { int maxcount = 0; if( !(BL_PC&battle_config.skill_reiteration) && skill_get_unit_flag(r_skill)&UF_NOREITERATION ) type = -1; if( BL_PC&battle_config.skill_nofootset && skill_get_unit_flag(r_skill)&UF_NOFOOTSET ) type = -1; if( BL_PC&battle_config.land_skill_limit && (maxcount = skill_get_maxcount(r_skill, r_lv)) > 0 ) { int v; for(v=0;v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount;v++) { if(sd->ud.skillunit[v]->skill_id == r_skill) maxcount--; } if( maxcount == 0 ) type = -1; } if( type != CAST_GROUND ){ clif_skill_fail(sd,r_skill,USESKILL_FAIL_LEVEL,0); map_freeblock_unlock(); return wd.dmg_lv; } } if (sd->state.autocast == 0) { sd->state.autocast = 1; skill_consume_requirement(sd, r_skill, r_lv, 3); switch (type) { case CAST_GROUND: skill_castend_pos2(src, target->x, target->y, r_skill, r_lv, tick, flag); break; case CAST_NODAMAGE: skill_castend_nodamage_id(src, target, r_skill, r_lv, tick, flag); break; case CAST_DAMAGE: skill_castend_damage_id(src, target, r_skill, r_lv, tick, flag); break; } } sd->state.autocast = 0; sd->ud.canact_tick = max(tick + skill_delayfix(src, r_skill, r_lv), sd->ud.canact_tick); clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, r_skill, r_lv), 0, 0, 1); } } if (wd.flag & BF_WEAPON && src != target && damage > 0) { if (battle_config.left_cardfix_to_right) battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, tstatus->class_); else battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, tstatus->class_); } } if (tsc) { if (damage > 0 && tsc->data[SC_POISONREACT] && (rnd()%100 < tsc->data[SC_POISONREACT]->val3 || sstatus->def_ele == ELE_POISON) && // check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O; status_check_skilluse(target, src, TF_POISON, 0) ) { //Poison React struct status_change_entry *sce = tsc->data[SC_POISONREACT]; if (sstatus->def_ele == ELE_POISON) { sce->val2 = 0; skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0); } else { skill_attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, 0); --sce->val2; } if (sce->val2 <= 0) status_change_end(target, SC_POISONREACT, INVALID_TIMER); } } map_freeblock_unlock(); return wd.dmg_lv; } unit.c int unit_attack(struct block_list *src,int target_id,int continuous) { struct block_list *target; struct unit_data *ud; int range; nullpo_ret(ud = unit_bl2ud(src)); target = map_id2bl(target_id); if( target == NULL || status_isdead(target) ) { unit_unattackable(src); return 1; } if( src->type == BL_PC ) { TBL_PC* sd = (TBL_PC*)src; if( target->type == BL_NPC ) { // Monster npcs [Valaris] npc_click(sd,(TBL_NPC*)target); // Submitted by leinsirk10 [Celest] return 0; } if( pc_is90overweight(sd) || pc_isridingwug(sd) ) { // Overweight or mounted on warg - stop attacking unit_stop_attack(src); return 0; } if( !pc_can_attack(sd, target_id) ) { unit_stop_attack(src); return 0; } } if( battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) ) { unit_unattackable(src); return 1; } ud->state.attack_continue = (continuous&1)?1:0; ud->state.step_attack = (continuous&2)?1:0; unit_set_target(ud, target_id); range = status_get_range(src); if (continuous) // If you're to attack continously, set to auto-chase character ud->chaserange = range; // Just change target/type. [Skotlex] if(ud->attacktimer != INVALID_TIMER) return 0; // New action request received, delete previous action request if not executed yet if(ud->stepaction || ud->steptimer != INVALID_TIMER) unit_stop_stepaction(src); // Remember the attack request from the client while walking to the next cell if(src->type == BL_PC && ud->walktimer != INVALID_TIMER && !battle_check_range(src, target, range-1)) { ud->stepaction = true; ud->target_to = ud->target; ud->stepskill_id = 0; ud->stepskill_lv = 0; return 0; // Attacking will be handled by unit_walktoxy_timer in this case } if(DIFF_TICK(ud->attackabletime, gettick()) > 0) // Do attack next time it is possible. [Skotlex] ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,src->id,0); else // Attack NOW. unit_attack_timer(INVALID_TIMER, gettick(), src->id, 0); return 0; } timer.c unsigned long get_uptime(void) { return (unsigned long)difftime(time(NULL), start_time); } Git Hash: 5fda4f0f65d3a239becb9f44df38a7cfad9a6160 our src has modification that im not aware of. Can anyone help me to fix this.. I tried looking at it and comparing every line to the recent commit but Im having a hard time fixing it..
  19. Rebel

    Market Clone

    // Market Clone [AnnieRuru/Dastgir] int mob_clone_spawn_market( struct map_session_data *sd, int16 m, int16 x, int16 y, char market_title[], char market_msg[] ) { //Copy of mob_clone_spawn with some modification. int mob_id; struct mob_data *md; struct mob_db* db; struct status_data *mstatus; struct chat_data* cd; ARR_FIND( MOB_CLONE_START, MOB_CLONE_END, mob_id, mob_db_data[mob_id] == NULL ); if ( mob_id >= MOB_CLONE_END ) return 0; db = mob_db_data[mob_id] = (struct mob_db*)aCalloc( 1, sizeof(struct mob_db) ); mstatus = &db->status; safestrncpy( db->sprite, sd->status.name, NAME_LENGTH ); safestrncpy( db->name, sd->status.name, NAME_LENGTH ); safestrncpy( db->jname, sd->status.name, NAME_LENGTH ); db->lv = status_get_lv(&sd->bl); memcpy( mstatus, &sd->base_status, sizeof( struct status_data ) ); mstatus->rhw.atk = mstatus->rhw.atk2 = mstatus->lhw.atk = mstatus->lhw.atk2 = mstatus->hp = mstatus->max_hp = mstatus->sp = mstatus->max_sp = 1; mstatus->mode = 0; memcpy( &db->vd, &sd->vd, sizeof( struct view_data ) ); db->base_exp = db->job_exp = db->range2 = db->range3 = 1; db->option = 0; md = mob_once_spawn_sub( &sd->bl, m, x, y, sd->status.name, mob_id, "", SZ_SMALL, AI_NONE ); if ( !md ) return 0; md->special_state.clone = 1; mob_spawn(md); unit_setdir( &md->bl, unit_getdir(&sd->bl) ); cd = chat_createchat( &md->bl, market_title, "", 1, false, 0, "", 0, 1, MAX_LEVEL ); if ( !cd ) return 0; md->market_chat_id = cd->bl.id; safestrncpy( md->market_message, market_msg, CHAT_SIZE_MAX ); clif_dispchat( cd, 0 ); if ( sd->vd.dead_sit == 2 ) clif_sitting( &md->bl ); return md->bl.id; } Anyone can help me. I tried the market clone by AnnieRuru/Dastgir in the latest rA commit but it has error when compiling.. Hoping that someone can help me.
  20. Anyone has this file? Including the source files. Thank you.
  21. [Error]: Skill '5065' is undefined! status.cpp:185::set_sc [Error]: set_sc: Unsupported skill id 5065 (SC: 685. Icon: 992) Dont know what cause this error.. anybody know what cause this?
  22. hi anyone can help me.. it only shows 1 result but when i try it on php sql it shows many results.. fluxcp result: Schema: <?php if (!defined('FLUX_ROOT')) exit; $title = 'PvP Ranking'; $classes = Flux::config('JobClasses')->toArray(); $jobClass = $params->get('jobclass'); $bind = array(); if (trim($jobClass) === '') { $jobClass = null; } if (!is_null($jobClass) && !array_key_exists($jobClass, $classes)) { $this->deny(); } $col = "ch.char_id, ch.name AS char_name, ch.class AS char_class, ch.base_level, ch.base_exp, ch.job_level, ch.job_exp, "; $col .= "ch.guild_id, guild.name AS guild_name, guild.emblem_len AS guild_emblem_len, "; $col .= "ph.char_id, ph.kills, ph.deaths, ph.streaks "; $sql = "SELECT $col FROM {$server->charMapDatabase}.char AS ch INNER JOIN {$server->charMapDatabase}.pvpladder AS ph "; $sql .= "LEFT JOIN {$server->charMapDatabase}.pvpladder ON ph.char_id = ch.char_id "; $sql .= "LEFT JOIN {$server->charMapDatabase}.guild ON guild.guild_id = ch.guild_id "; $sql .= "LEFT JOIN {$server->loginDatabase}.login ON login.account_id = ch.account_id "; $sql .= "WHERE 1=1 GROUP BY ch.char_id "; if (Flux::config('PvpHidePermBannedCharRank')) { $sql .= "AND login.state != 5 "; } if (Flux::config('PvpHideTempBannedCharRank')) { $sql .= "AND (login.unban_time IS NULL OR login.unban_time = 0) "; } $groups = AccountLevel::getGroupID((int)Flux::config('PvPRankingHideGroupLevel'), '<'); if(!empty($groups)) { $ids = implode(', ', array_fill(0, count($groups), '?')); $sql .= "AND login.group_id IN ($ids) "; $bind = array_merge($bind, $groups); } if ($days=Flux::config('PvpCharRankingThreshold')) { $sql .= 'AND TIMESTAMPDIFF(DAY, login.lastlogin, NOW()) <= ? '; $bind[] = $days * 24 * 60 * 60; } if (!is_null($jobClass)) { $sql .= "AND ch.class = ? "; $bind[] = $jobClass; } $sql .= "ORDER BY ph.kills DESC "; $sql .= "LIMIT ".(int)Flux::config('PvpRankingLimit'); $sth = $server->connection->getStatement($sql); $sth->execute($bind); $chars = $sth->fetchAll(); ?> Phpmyadmin Result:
×
×
  • Create New...