All Activity
- Past hour
-
Thanks @Brynner, it's solved my issue.
-
Another simple update, just added a panel to show currency total for the account and also a Buy Currency button (if configured), can be linked to any page to buy the currency. Either donate module or anything custom.
- Today
-
UPDATES!! NOW, integrated with the Gemini Chatbot API for the Editor! Just ask it, and it will provide code for you directly in rAthena Text Editor. Simply provide your Gemini API key. We're using the latest and fastest Gemini model: "gemini-2.5-flash-preview-05-20".
-
try to replace the clif_changelook(&sd->bl,LOOK_BODY2,sd->status.body); with clif_changelook(sd,LOOK_BODY2,sd->status.body);
-
Utility: All In One - Random Options Script
Metrius replied to sader1992's topic in Utility Script Releases
also does anyone know how many itens we can put in to each id before we got a error or doest work? -
Utility: All In One - Random Options Script
Metrius replied to sader1992's topic in Utility Script Releases
anyone is able to have more than 4 groups ids? when i put a 5 i get the error "[Error]: script:run_script_main: infinity loop ! " -
I tested it with the latest rAthena version, and it works correctly. Are you perhaps using the 2025-05-08 client version?
-
[QoL] Show warning when trying to allocate skill points on a higher job tab
eleriaqueen replied to exequens's question in Source Requests
I'll look into these functions, thanks for the info. Look I'm happy to at least try and come up with a solution for this "puzzle", since I'll likely use it too! I tried to handle Super Novice, but at first glance it doesn't look doable, becuase the job has access to other classes' skills mixed with his skills. I'll try to work some more on Super Novice and Summoner. If I can't do it I'll look into using the functions you mentioned, it will likely require a huge rewrite so I rather try to fix it with the "current code". Edit: I managed to make Super Novice and Summoner work. I also swapped ShowError() with clif_displaymessage() so that the messages appear ingame. enum Job_Tier { Basic = 0, First, First_High, Second, Second_High, Third, Third_High, Fourth, Super_Novice, Super_Novice_E, Hyper_Novice, Summoner, Spirit_Handler, }; // Helper Function: Returns the job tier Job_Tier pc_get_job_tier(uint64 class_) { if (class_ == MAPID_SPIRIT_HANDLER) return Job_Tier::Spirit_Handler; if (class_ == MAPID_SUMMONER) return Job_Tier::Summoner; if (class_ == MAPID_HYPER_NOVICE) return Job_Tier::Hyper_Novice; if (class_ == MAPID_SUPER_NOVICE_E) return Job_Tier::Super_Novice_E; if (class_ == MAPID_SUPER_NOVICE) return Job_Tier::Super_Novice; if (class_ & JOBL_FOURTH) return Job_Tier::Fourth; if (class_ == MAPID_RUNE_KNIGHT_T) return Job_Tier::Third_High; if (class_ == MAPID_WARLOCK_T) return Job_Tier::Third_High; if (class_ == MAPID_RANGER_T) return Job_Tier::Third_High; if (class_ == MAPID_ARCH_BISHOP_T) return Job_Tier::Third_High; if (class_ == MAPID_MECHANIC_T) return Job_Tier::Third_High; if (class_ == MAPID_GUILLOTINE_CROSS_T) return Job_Tier::Third_High; if (class_ == MAPID_ROYAL_GUARD_T) return Job_Tier::Third_High; if (class_ == MAPID_SORCERER_T) return Job_Tier::Third_High; if (class_ == MAPID_MINSTRELWANDERER_T) return Job_Tier::Third_High; if (class_ == MAPID_SURA_T) return Job_Tier::Third_High; if (class_ == MAPID_GENETIC_T) return Job_Tier::Third_High; if (class_ == MAPID_SHADOW_CHASER_T) return Job_Tier::Third_High; if (class_ & JOBL_THIRD) return Job_Tier::Third; if (class_ == MAPID_LORD_KNIGHT) return Job_Tier::Second_High; if (class_ == MAPID_HIGH_WIZARD) return Job_Tier::Second_High; if (class_ == MAPID_SNIPER) return Job_Tier::Second_High; if (class_ == MAPID_HIGH_PRIEST) return Job_Tier::Second_High; if (class_ == MAPID_WHITESMITH) return Job_Tier::Second_High; if (class_ == MAPID_ASSASSIN_CROSS) return Job_Tier::Second_High; if (class_ == MAPID_PALADIN) return Job_Tier::Second_High; if (class_ == MAPID_PROFESSOR) return Job_Tier::Second_High; if (class_ == MAPID_CLOWNGYPSY) return Job_Tier::Second_High; if (class_ == MAPID_CHAMPION) return Job_Tier::Second_High; if (class_ == MAPID_CREATOR) return Job_Tier::Second_High; if (class_ == MAPID_STALKER) return Job_Tier::Second_High; if (class_ & JOBL_2) return Job_Tier::Second; if (class_ == MAPID_SWORDMAN_HIGH) return Job_Tier::First_High; if (class_ == MAPID_MAGE_HIGH) return Job_Tier::First_High; if (class_ == MAPID_ARCHER_HIGH) return Job_Tier::First_High; if (class_ == MAPID_ACOLYTE_HIGH) return Job_Tier::First_High; if (class_ == MAPID_MERCHANT_HIGH) return Job_Tier::First_High; if (class_ == MAPID_THIEF_HIGH) return Job_Tier::First_High; if ((class_ & MAPID_BASEMASK) != MAPID_NOVICE) return Job_Tier::First; return Job_Tier::Basic; // Novice/Summoner } // Helper Function : Returns the skill's job tier Job_Tier skill_get_job_tier(uint16 skill_id) { // Novice if (skill_id > 0 && skill_id < SM_SWORD) return Job_Tier::Basic; // Swordman else if (skill_id >= SM_SWORD && skill_id <= SM_ENDURE) return Job_Tier::First; // Magician else if (skill_id >= MG_SRECOVERY && skill_id <= MG_THUNDERSTORM) return Job_Tier::First; // Acolyte else if (skill_id >= AL_DP && skill_id <= AL_CURE) return Job_Tier::First; // Merchant else if (skill_id >= MC_INCCARRY && skill_id <= MC_MAMMONITE) return Job_Tier::First; // Archer else if (skill_id >= AC_OWL && skill_id <= AC_SHOWER) return Job_Tier::First; // Thief else if (skill_id >= TF_DOUBLE && skill_id <= TF_DETOXIFY) return Job_Tier::First; // Taekwon Kid else if (skill_id >= TK_RUN && skill_id <= TK_HIGHJUMP) return Job_Tier::First; else if (skill_id == TK_MISSION) return Job_Tier::First; // Knight else if (skill_id >= KN_SPEARMASTERY && skill_id <= KN_CAVALIERMASTERY) return Job_Tier::Second; // Priest else if (skill_id >= PR_MACEMASTERY && skill_id <= PR_MAGNUS) return Job_Tier::Second; // Wizard else if (skill_id >= WZ_FIREPILLAR && skill_id <= WZ_ESTIMATION) return Job_Tier::Second; // Blacksmith else if (skill_id >= BS_IRON && skill_id <= BS_MAXIMIZE) return Job_Tier::Second; // Hunter else if (skill_id >= HT_SKIDTRAP && skill_id <= HT_SPRINGTRAP) return Job_Tier::Second; // Assassin else if (skill_id >= AS_RIGHT && skill_id <= AS_SPLASHER) return Job_Tier::Second; // Rogue else if (skill_id >= RG_SNATCHER && skill_id <= RG_PLAGIARISM) return Job_Tier::Second; // Alchemist else if (skill_id >= AM_AXEMASTERY && skill_id <= AM_RESURRECTHOMUN) return Job_Tier::Second; // Crusader else if (skill_id >= CR_TRUST && skill_id <= CR_SPEARQUICKEN) return Job_Tier::Second; // Monk else if (skill_id >= MO_IRONHAND && skill_id <= MO_COMBOFINISH) return Job_Tier::Second; // Sage else if (skill_id >= SA_ADVANCEDBOOK && skill_id <= SA_COMA) return Job_Tier::Second; // Bard & Dancer else if (skill_id >= BD_ADAPTATION && skill_id <= BD_RAGNAROK) return Job_Tier::Second; // Bard else if (skill_id >= BA_MUSICALLESSON && skill_id <= BA_APPLEIDUN) return Job_Tier::Second; // Dancer else if (skill_id >= DC_DANCINGLESSON && skill_id <= DC_SERVICEFORYOU) return Job_Tier::Second; // Lord Knight else if (skill_id >= LK_AURABLADE && skill_id <= LK_FURY) return Job_Tier::Second_High; else if (skill_id >= LK_SPIRALPIERCE && skill_id <= LK_JOINTBEAT) return Job_Tier::Second_High; // High Priest else if (skill_id >= HP_ASSUMPTIO && skill_id <= HP_MEDITATIO) return Job_Tier::Second_High; else if (skill_id == HP_MANARECHARGE) return Job_Tier::Second_High; // High Wizard else if (skill_id >= HW_SOULDRAIN && skill_id <= HW_MAGICPOWER) return Job_Tier::Second_High; else if (skill_id == HW_NAPALMVULCAN) return Job_Tier::Second_High; else if (skill_id >= HW_GANBANTEIN && skill_id <= HW_GRAVITATION) return Job_Tier::Second_High; // Paladin else if (skill_id >= PA_PRESSURE && skill_id <= PA_GOSPEL) return Job_Tier::Second_High; else if (skill_id == PA_SHIELDCHAIN) return Job_Tier::Second_High; // Champion else if (skill_id >= CH_PALMSTRIKE && skill_id <= CH_CHAINCRUSH) return Job_Tier::Second_High; else if (skill_id == CH_SOULCOLLECT) return Job_Tier::Second_High; // Professor else if (skill_id >= PF_HPCONVERSION && skill_id <= PF_SOULBURN) return Job_Tier::Second_High; else if (skill_id >= PF_MINDBREAKER && skill_id <= PF_SPIDERWEB) return Job_Tier::Second_High; else if (skill_id == PF_DOUBLECASTING) return Job_Tier::Second_High; // Assassin Cross else if (skill_id >= ASC_KATAR && skill_id <= ASC_BREAKER) return Job_Tier::Second_High; else if (skill_id >= ASC_METEORASSAULT && skill_id <= ASC_CDP) return Job_Tier::Second_High; // Sniper else if (skill_id >= SN_SIGHT && skill_id <= SN_WINDWALK) return Job_Tier::Second_High; // Whitesmith else if (skill_id >= WS_MELTDOWN && skill_id <= WS_SYSTEMCREATE) return Job_Tier::Second_High; else if (skill_id == WS_WEAPONREFINE) return Job_Tier::Second_High; else if (skill_id >= WS_CARTTERMINATION && skill_id <= WS_OVERTHRUSTMAX) return Job_Tier::Second_High; // Stalker else if (skill_id >= ST_CHASEWALK && skill_id <= ST_STEALBACKPACK) return Job_Tier::Second_High; else if (skill_id >= ST_PRESERVE && skill_id <= ST_FULLSTRIP) return Job_Tier::Second_High; // Creator else if (skill_id >= CR_ALCHEMY && skill_id <= CR_SYNTHESISPOTION) return Job_Tier::Second_High; else if (skill_id >= CR_SLIMPITCHER && skill_id <= CR_FULLPROTECTION) return Job_Tier::Second_High; else if (skill_id == CR_ACIDDEMONSTRATION) return Job_Tier::Second_High; // Clown / Gypsy else if (skill_id >= CG_ARROWVULCAN && skill_id <= CG_MARIONETTE) return Job_Tier::Second_High; else if (skill_id >= CG_LONGINGFREEDOM && skill_id <= CG_TAROTCARD) return Job_Tier::Second_High; else if (skill_id == CG_SPECIALSINGER) return Job_Tier::Second_High; // Star Gladiator else if (skill_id >= SG_FEEL && skill_id <= SG_FUSION) return Job_Tier::Second; // Soul Linker else if (skill_id == SL_ALCHEMIST) return Job_Tier::Second; else if (skill_id >= SL_MONK && skill_id <= SL_SKA) return Job_Tier::Second; else if (skill_id == SL_HIGH) return Job_Tier::Second; // else if (skill_id >= SL_DEATHKNIGHT && skill_id <= SL_GUNNER) return 2; // Gunslinger else if (skill_id >= GS_GLITTERING && skill_id <= GS_GROUNDDRIFT) return Job_Tier::Second_High; // Ninja else if (skill_id >= NJ_TOBIDOUGU && skill_id <= NJ_ISSEN) return Job_Tier::Second_High; // Rune Knight else if (skill_id >= RK_ENCHANTBLADE && skill_id <= RK_PHANTOMTHRUST) return Job_Tier::Third; else if (skill_id >= RK_DRAGONBREATH_WATER && skill_id <= RK_LUXANIMA) return Job_Tier::Third; // Guillotine Cross else if (skill_id >= GC_VENOMIMPRESS && skill_id <= GC_CROSSRIPPERSLASHER) return Job_Tier::Third; else if (skill_id == GC_DARKCROW) return Job_Tier::Third; // Arch-Bishop else if (skill_id >= AB_JUDEX && skill_id <= AB_SILENTIUM) return Job_Tier::Third; else if (skill_id == AB_SECRAMENT) return Job_Tier::Third; else if (skill_id == AB_OFFERTORIUM) return Job_Tier::Third; else if (skill_id >= AB_VITUPERATUM && skill_id <= AB_CONVENIO) return Job_Tier::Third; // Warlock else if (skill_id >= WL_WHITEIMPRISON && skill_id <= WL_FREEZE_SP) return Job_Tier::Third; else if (skill_id == WL_TELEKINESIS_INTENSE) return Job_Tier::Third; // Ranger else if (skill_id >= RA_ARROWSTORM && skill_id <= RA_ICEBOUNDTRAP) return Job_Tier::Third; else if (skill_id == RA_UNLIMIT) return Job_Tier::Third; // Mechanic else if (skill_id >= NC_MADOLICENCE && skill_id <= NC_DISJOINT) return Job_Tier::Third; else if (skill_id == NC_MAGMA_ERUPTION) return Job_Tier::Third; // Shadow Chaser else if (skill_id >= SC_FATALMENACE && skill_id <= SC_FEINTBOMB) return Job_Tier::Third; else if (skill_id == SC_ESCAPE) return Job_Tier::Third; // Royal Guard else if (skill_id >= LG_CANNONSPEAR && skill_id <= LG_INSPIRATION) return Job_Tier::Third; else if (skill_id == LG_KINGS_GRACE) return Job_Tier::Third; // Sura else if (skill_id >= SR_DRAGONCOMBO && skill_id <= SR_GENTLETOUCH_REVITALIZE) return Job_Tier::Third; else if (skill_id >= SR_HOWLINGOFLION && skill_id <= SR_RIDEINLIGHTNING) return Job_Tier::Third; else if (skill_id == SR_FLASHCOMBO) return Job_Tier::Third; // Wanderer else if (skill_id >= WA_SWING_DANCE && skill_id <= WA_MOONLIT_SERENADE) return Job_Tier::Third; // Ministrel else if (skill_id >= MI_RUSH_WINDMILL && skill_id <= MI_HARMONIZE) return Job_Tier::Third; // Wanderer && Ministrel else if (skill_id >= WM_LESSON && skill_id <= WM_UNLIMITED_HUMMING_VOICE) return Job_Tier::Third; else if (skill_id == WM_FRIGG_SONG) return Job_Tier::Third; // Sorcerer else if (skill_id >= SO_FIREWALK && skill_id <= SO_EARTH_INSIGNIA) return Job_Tier::Third; else if (skill_id == SO_ELEMENTAL_SHIELD) return Job_Tier::Third; // Genetic else if (skill_id >= GN_TRAINING_SWORD && skill_id <= GN_SLINGITEM_RANGEMELEEATK) return Job_Tier::Third; else if (skill_id == GN_ILLUSIONDOPING) return Job_Tier::Third; // Rebellion else if (skill_id >= RL_GLITTERING_GREED && skill_id <= RL_B_FLICKER_ATK) return Job_Tier::Third; // Star Emperor else if (skill_id >= SJ_LIGHTOFMOON && skill_id <= SJ_PROMINENCEKICK) return Job_Tier::Third; // Soul Reaper else if (skill_id >= SP_SOULGOLEM && skill_id <= SP_KAUTE) return Job_Tier::Third; // Kagerou && Oboro else if (skill_id >= KO_YAMIKUMO && skill_id <= KO_IZAYOI) return Job_Tier::Third; // Kagerou else if (skill_id >= KG_KAGEHUMI && skill_id <= KG_KAGEMUSYA) return Job_Tier::Third; // Oboro else if (skill_id >= OB_ZANGETSU && skill_id <= OB_AKAITSUKI) return Job_Tier::Third; // Super Novice 2 else if (skill_id >= NV_BREAKTHROUGH && skill_id <= NV_TRANSCENDENCE) return Job_Tier::Third; // Summoner else if (skill_id >= SU_BASIC_SKILL && skill_id <= SU_SPIRITOFSEA) return Job_Tier::Third; // ALL 3rd jobs else if (skill_id == ALL_FULL_THROTTLE) return Job_Tier::Third; // Dragon Knight else if (skill_id >= DK_SERVANTWEAPON && skill_id <= DK_STORMSLASH) return Job_Tier::Fourth; else if (skill_id == DK_DRAGONIC_BREATH) return Job_Tier::Fourth; else if (skill_id == DK_DRAGONIC_PIERCE) return Job_Tier::Fourth; // Arc Mage else if (skill_id >= AG_DEADLY_PROJECTION && skill_id <= AG_FROZEN_SLASH) return Job_Tier::Fourth; else if (skill_id == AG_DESTRUCTIVE_HURRICANE_CLIMAX) return Job_Tier::Fourth; else if (skill_id == AG_ENERGY_CONVERSION) return Job_Tier::Fourth; // Inquisitor else if (skill_id >= IQ_POWERFUL_FAITH && skill_id <= IQ_THIRD_EXOR_FLAME) return Job_Tier::Fourth; else if (skill_id == IQ_BLAZING_FLAME_BLAST) return Job_Tier::Fourth; // Imperial Guard else if (skill_id >= IG_GUARD_STANCE && skill_id <= IG_CROSS_RAIN) return Job_Tier::Fourth; else if (skill_id >= IG_RADIANT_SPEAR && skill_id <= IG_IMPERIAL_PRESSURE) return Job_Tier::Fourth; // Cardinal else if (skill_id >= CD_REPARATIO && skill_id <= CD_FRAMEN) return Job_Tier::Fourth; else if (skill_id == CD_DIVINUS_FLOS) return Job_Tier::Fourth; // Shadow Cross else if (skill_id >= SHC_SHADOW_EXCEED && skill_id <= SHC_FATAL_SHADOW_CROW) return Job_Tier::Fourth; else if (skill_id == SHC_CROSS_SLASH) return Job_Tier::Fourth; // Meister else if (skill_id >= MT_AXE_STOMP && skill_id <= MT_SUMMON_ABR_INFINITY) return Job_Tier::Fourth; else if (skill_id >= MT_SPARK_BLASTER && skill_id <= MT_MIGHTY_SMASH) return Job_Tier::Fourth; else if (skill_id >= MT_RUSH_STRIKE && skill_id <= MT_ENERGY_CANNONADE) return Job_Tier::Fourth; // Biolo else if (skill_id >= BO_ACIDIFIED_ZONE_WATER_ATK && skill_id <= BO_ACIDIFIED_ZONE_FIRE_ATK) return Job_Tier::Fourth; else if (skill_id >= BO_BIONIC_PHARMACY && skill_id <= BO_HELLTREE) return Job_Tier::Fourth; else if (skill_id >= BO_EXPLOSIVE_POWDER && skill_id <= BO_MAYHEMIC_THORNS) return Job_Tier::Fourth; else if (skill_id >= BO_MYSTERY_POWDER && skill_id <= BO_DUST_EXPLOSION) return Job_Tier::Fourth; // Abyss Chaser else if (skill_id >= ABC_DAGGER_AND_BOW_M && skill_id <= ABC_FRENZY_SHOT) return Job_Tier::Fourth; else if (skill_id >= ABC_HIT_AND_SLIDING && skill_id <= ABC_ABYSS_FLAME) return Job_Tier::Fourth; // Wind Hawk else if (skill_id >= WH_ADVANCED_TRAP && skill_id <= WH_FLAMETRAP) return Job_Tier::Fourth; else if (skill_id == WH_WILD_WALK) return Job_Tier::Fourth; // Troubadour && Trouvere else if (skill_id >= TR_STAGE_MANNER && skill_id <= TR_PRON_MARCH) return Job_Tier::Fourth; else if (skill_id == TR_RHYTHMICAL_WAVE) return Job_Tier::Fourth; // Elemental Master else if (skill_id >= EM_MAGIC_BOOK_M && skill_id <= EM_ELEMENTAL_VEIL) return Job_Tier::Fourth; else if (skill_id == EM_PSYCHIC_STREAM) return Job_Tier::Fourth; // Night Watch else if (skill_id >= NW_P_F_I && skill_id <= NW_MISSION_BOMBARD) return Job_Tier::Fourth; else if (skill_id >= NW_WILD_SHOT && skill_id <= NW_MIDNIGHT_FALLEN) return Job_Tier::Fourth; // Soul Ascetic else if (skill_id >= SOA_TALISMAN_MASTERY && skill_id <= SOA_SOUL_OF_HEAVEN_AND_EARTH) return Job_Tier::Fourth; // Spirit Handler else if (skill_id >= SH_MYSTICAL_CREATURE_MASTERY && skill_id <= SH_BLESSING_OF_MYSTICAL_CREATURES) return Job_Tier::Fourth; else if (skill_id >= SH_CHUL_HO_BATTERING && skill_id <= SH_HYUN_ROK_SPIRIT_POWER) return Job_Tier::Fourth; // Hyper Novice else if (skill_id >= HN_SELFSTUDY_TATICS && skill_id <= HN_RULEBREAK) return Job_Tier::Fourth; else if (skill_id == HN_OVERCOMING_CRISIS) return Job_Tier::Fourth; // Sky Emperor else if (skill_id >= SKE_SKY_MASTERY && skill_id <= SKE_ENCHANTING_SKY) return Job_Tier::Fourth; else if (skill_id >= SKE_SKY_SUN && skill_id <= SKE_STAR_LIGHT_KICK) return Job_Tier::Fourth; // Shinkiro && Shiranui else if (skill_id >= SS_TOKEDASU && skill_id <= SS_ANKOKURYUUAKUMU) return Job_Tier::Fourth; else if (skill_id == SS_FOUR_CHARM) return Job_Tier::Fourth; // Sky Emperor else if (skill_id >= SKE_SKY_MASTERY && skill_id <= SKE_ENCHANTING_SKY) return Job_Tier::Fourth; return Job_Tier::Basic; // Default to Novice if unknown } /*========================================== * Update skill_lv for player sd * Skill point allocation *------------------------------------------*/ void pc_skillup(map_session_data *sd,uint16 skill_id) { uint16 idx = skill_get_index(skill_id); nullpo_retv(sd); if (!idx) { if (skill_id) ShowError("pc_skillup: Player attempts to level up invalid skill '%d'\n", skill_id); return; } int32 skill_point = pc_calc_skillpoint( sd ); int32 novice_max_skillpoint = job_db.find( JOB_NOVICE )->max_job_level - 1; int32 summoner_max_skillpoint = job_db.find( JOB_SUMMONER )->max_job_level - 1; int32 max_skillpoint_1st = job_db.find( JOB_SWORDMAN )->max_job_level - 1; int32 max_skillpoint_2nd = job_db.find( JOB_KNIGHT )->max_job_level - 1; int32 max_skillpoint_2nd_high = job_db.find( JOB_LORD_KNIGHT )->max_job_level - 1; int32 max_skillpoint_3rd = job_db.find( JOB_RUNE_KNIGHT )->max_job_level - 1; int32 max_skillpoint_sn = job_db.find( JOB_SUPER_NOVICE )->max_job_level - 1; int32 max_skillpoint_sn_e = job_db.find( JOB_SUPER_NOVICE_E )->max_job_level - 1; int32 max_skillpoint_summ = job_db.find( JOB_SUMMONER )->max_job_level - 1; int32 skillpoint_1st = sd->change_level_2nd - 1; int32 skillpoint_2nd = sd->change_level_3rd - 1; int32 must_spend_novice = novice_max_skillpoint - skill_point; int32 must_spend_1st = min(max_skillpoint_1st, novice_max_skillpoint + skillpoint_1st - skill_point); int32 must_spend_2nd = min(max_skillpoint_2nd, novice_max_skillpoint + skillpoint_1st + skillpoint_2nd - skill_point); int32 must_spend_2nd_high = min(max_skillpoint_2nd_high, novice_max_skillpoint + skillpoint_1st + skillpoint_2nd - skill_point); int32 must_spend_3rd = min(max_skillpoint_3rd, novice_max_skillpoint + skillpoint_1st + skillpoint_2nd + max_skillpoint_3rd - skill_point); int32 must_spend_sn = min(max_skillpoint_sn, novice_max_skillpoint + max_skillpoint_sn - skill_point); int32 must_spend_sn_e = min(max_skillpoint_sn_e, novice_max_skillpoint + max_skillpoint_sn + max_skillpoint_sn_e - skill_point); int32 must_spend_summ = max_skillpoint_summ - skill_point; StringBuf *helper_msg_novice = StringBuf_Malloc(); StringBuf *helper_msg_novice_high = StringBuf_Malloc(); StringBuf *helper_msg_1st = StringBuf_Malloc(); StringBuf *helper_msg_1st_high = StringBuf_Malloc(); StringBuf *helper_msg_2nd = StringBuf_Malloc(); StringBuf *helper_msg_2nd_high = StringBuf_Malloc(); StringBuf *helper_msg_3rd = StringBuf_Malloc(); StringBuf *helper_msg_sn = StringBuf_Malloc(); StringBuf *helper_msg_sn_e = StringBuf_Malloc(); StringBuf *helper_msg_hn = StringBuf_Malloc(); StringBuf *helper_msg_summoner = StringBuf_Malloc(); StringBuf_Printf(helper_msg_novice, "%d %s", must_spend_novice, "more skillpoints are required in Basic Skill\n"); StringBuf_Printf(helper_msg_novice_high, "%d %s", must_spend_novice, "more skillpoints are required in Basic Skill\n"); StringBuf_Printf(helper_msg_1st, "%d %s", must_spend_1st, "more skillpoints are required in 1st Job Skill Tree\n"); StringBuf_Printf(helper_msg_1st_high, "%d %s", must_spend_1st, "more skillpoints are required in 1st High Job Skill Tree\n"); StringBuf_Printf(helper_msg_2nd, "%d %s", must_spend_2nd, "more skillpoints are required in 2nd Job Skill Tree\n"); StringBuf_Printf(helper_msg_2nd_high, "%d %s", must_spend_2nd_high, "more skillpoints are required in 2nd High Job Skill Tree\n"); StringBuf_Printf(helper_msg_3rd, "%d %s", must_spend_3rd, "more skillpoints are required in 3rd Job Skill Tree\n"); StringBuf_Printf(helper_msg_sn, "%d %s", must_spend_sn, "more skillpoints are required in Super Novice (considered Novice Job) Skill Tree\n"); StringBuf_Printf(helper_msg_sn_e, "%d %s", must_spend_sn_e, "more skillpoints are required in Expanded Super Novice (considered 2nd Job) Skill Tree\n"); StringBuf_Printf(helper_msg_summoner, "%d %s", must_spend_summ, "more skillpoints are required in Summoner Skill Tree\n"); // Special Case for Super Novice if (pc_get_job_tier(sd->class_) == Job_Tier::Super_Novice) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } } // Special Case for Expanded Super Novice else if (pc_get_job_tier(sd->class_) == Job_Tier::Super_Novice_E) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second || skill_get_job_tier(skill_id) == Job_Tier::Third && (skill_point < novice_max_skillpoint + max_skillpoint_sn)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { // ShowError(helper_msg_sn, must_spend_sn); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_sn)); } } } // Special Case for Hyper Novice else if (pc_get_job_tier(sd->class_) == Job_Tier::Hyper_Novice) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second || skill_get_job_tier(skill_id) == Job_Tier::Third && (skill_point < novice_max_skillpoint + max_skillpoint_sn)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } if (skill_point < novice_max_skillpoint + max_skillpoint_sn) { // ShowError(helper_msg_sn, must_spend_sn); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_sn)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Fourth && (skill_point < novice_max_skillpoint + max_skillpoint_sn + max_skillpoint_sn_e)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } if (skill_point < novice_max_skillpoint + max_skillpoint_sn) { // ShowError(helper_msg_sn, must_spend_sn); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_sn)); } if (skill_point < novice_max_skillpoint + max_skillpoint_sn + max_skillpoint_sn_e) { // ShowError(helper_msg_sn_e, must_spend_sn_e); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_sn_e)); } } } // Special Case for Spirit Handler else if (pc_get_job_tier(sd->class_) == Job_Tier::Spirit_Handler) { if (skill_get_job_tier(skill_id) == Job_Tier::Fourth && (skill_point < max_skillpoint_summ)) { // ShowError(helper_msg_summoner, must_spend_summ); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_summoner)); } } else if (pc_get_job_tier(sd->class_) == Job_Tier::First) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } } else if (pc_get_job_tier(sd->class_) == Job_Tier::First_High) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } } } else if (pc_get_job_tier(sd->class_) == Job_Tier::Second) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second && (skill_point < novice_max_skillpoint + skillpoint_1st)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { // ShowError(helper_msg_1st, must_spend_1st); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_1st)); } } } else if (pc_get_job_tier(sd->class_) == Job_Tier::Second_High) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice_high, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice_high)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second && (skill_point < novice_max_skillpoint + skillpoint_1st)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice_high, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice_high)); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { // ShowError(helper_msg_1st_high, must_spend_1st); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_1st_high)); } } } else if (pc_get_job_tier(sd->class_) == Job_Tier::Third) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second && (skill_point < novice_max_skillpoint + skillpoint_1st)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { // ShowError(helper_msg_1st, must_spend_1st); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_1st)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Third && (skill_point < novice_max_skillpoint + skillpoint_1st + max_skillpoint_2nd)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { // ShowError(helper_msg_1st, must_spend_1st); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_1st)); } if (skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) { // ShowError(helper_msg_2nd, must_spend_2nd); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_2nd)); } } } else if (pc_get_job_tier(sd->class_) == Job_Tier::Third_High) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice_high, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice_high)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second && (skill_point < novice_max_skillpoint + skillpoint_1st)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice_high, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice_high)); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { // ShowError(helper_msg_1st_high, must_spend_1st); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_1st_high)); } } if ((skill_get_job_tier(skill_id) == Job_Tier::Third || Job_Tier::Third_High) && (skill_point < novice_max_skillpoint + skillpoint_1st + max_skillpoint_2nd)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice_high, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice_high)); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { // ShowError(helper_msg_1st_high, must_spend_1st); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_1st_high)); } if (skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) { // ShowError(helper_msg_2nd_high, must_spend_2nd_high); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_2nd_high)); } } } else if (pc_get_job_tier(sd->class_) == Job_Tier::Fourth) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second && (skill_point < novice_max_skillpoint + skillpoint_1st)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { // ShowError(helper_msg_1st, must_spend_1st); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_1st)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Third && (skill_point < novice_max_skillpoint + skillpoint_1st + max_skillpoint_2nd)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { // ShowError(helper_msg_1st, must_spend_1st); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_1st)); } // If character went rebirth 2nd and 3rd if ((skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) && (skillpoint_2nd == max_skillpoint_2nd_high)) { // ShowError(helper_msg_2nd_high, must_spend_2nd_high); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_2nd_high)); } // If character went non-rebirth 2nd and 3rd else if ((skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) && (skillpoint_2nd == max_skillpoint_2nd)) { // ShowError(helper_msg_2nd, must_spend_2nd); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_2nd)); } } if (skill_get_job_tier(skill_id) == Job_Tier::Fourth && (skill_point < novice_max_skillpoint + skillpoint_1st + max_skillpoint_2nd + max_skillpoint_3rd)) { if (skill_point < novice_max_skillpoint) { // ShowError(helper_msg_novice, must_spend_novice); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_novice)); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { // ShowError(helper_msg_1st, must_spend_1st); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_1st)); } // if (skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) { // // ShowError(helper_msg_2nd, must_spend_2nd); // clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_2nd)); // } // If character went rebirth 2nd and 3rd then 4th if ((skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) && (skillpoint_2nd == max_skillpoint_2nd_high)) { // ShowError(helper_msg_2nd_high, must_spend_2nd_high); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_2nd_high)); } // If character went non-rebirth 2nd and 3rd then 4th else if ((skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) && (skillpoint_2nd == max_skillpoint_2nd)) { // ShowError(helper_msg_2nd, must_spend_2nd); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_2nd)); } if (skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd + max_skillpoint_3rd) { // ShowError(helper_msg_3rd, must_spend_3rd); clif_displaymessage(sd->fd, StringBuf_Value(helper_msg_3rd)); } } } StringBuf_Free(helper_msg_novice); StringBuf_Free(helper_msg_novice_high); StringBuf_Free(helper_msg_1st); StringBuf_Free(helper_msg_1st_high); StringBuf_Free(helper_msg_2nd); StringBuf_Free(helper_msg_2nd_high); StringBuf_Free(helper_msg_3rd); StringBuf_Free(helper_msg_sn); StringBuf_Free(helper_msg_sn_e); StringBuf_Free(helper_msg_hn); StringBuf_Free(helper_msg_summoner); ... Rest of the function code ... } -
Keitenai Delay System ( Speed Hack Protection )
AinsLord replied to Keitenai's topic in Source Releases
Modified to use for latest rA git keitenai_SpeedHack_Protection_V5.diff tested got no errors in console -
Release: Soul Link Modification - Script-based
AinsLord replied to Secrets's topic in Source Releases
I modified this src to the latest rathena git singe_soul_link_mod_v1-1.patch i've tried it and no errors occurred -
[Showcase] Autoattack + Auto Assist Mode
namerpus18 replied to namerpus18's topic in Script Showcase
That script is old so if you use newest git of rathena you need to add it manually and ofcourse there are more changes needed. -
[QoL] Show warning when trying to allocate skill points on a higher job tab
exequens replied to exequens's question in Source Requests
Oh my God, thank you very much for going to such length. Unfortunately, I cannot contribute as much as you do as I am a newbie in the coding department. That is why I'm posting it in a source request sub-forum... I did some digging though. I think we should be able to make use of something like this? std::shared_ptr<s_job_info> job = job_db.find(sd->status.class_); std::shared_ptr<s_skill_tree> tree = skill_tree_db.find(job_class); If we make the code find the class and find the skill instead using that, it should make the code smaller no? The only problem is, I don't know how to use it. - Yesterday
-
I tried this already, but it didn’t work. Any other way I could try?
-
[Showcase] Autoattack + Auto Assist Mode
jackel2013 replied to namerpus18's topic in Script Showcase
Can someone post a step-by-step process on adding the patch or script of " Auto-attack". Thanks in advance. I did all my research here and on the Hercules page - still end up nothing. -
-
My server's folder is based on a clean kRO 2022-07-06 downloaded from this nemo page (which has a direct link to http://rofull.gnjoy.com/RAG_SETUP_220706.exe), updated with Ai4rei's RO Patcher Lite. I got all the latest ROEnglishRE files. I'm using 2022-04-06_Ragexe_1648707856.exe. Step 01: Ran ClientGenerator.bat and AdditionsGenerator.bat. Step 02: Got a client folder generated by the scripts, copied the SystemEN folder, DATA.ini, GuildTip.txt and tipOfTheDay.txt to my server's folder. Step 03: Put the generated data folder into a grf. The name of the grf matches what is in the DATA.ini file: [Data] 0=selune.grf 1=data.grf Step 04: Loaded 2022-04-06_Ragexe_1648707856.exe obtained from the nemo website into WARP. Applied the 2019-06_Translation.yml session file to it. Selected recommended patches. Selected all the "Customize ... lub file" patches not already applied, making sure I had the files in the SystemEN folder. WARP doesn't give any errors or warnings, seems to be applying all patches successfully. Step 05: I believe I followed all the documentation and tutorials/guides correctly. However when I run the patched ragexe, I get the following errors and can't open the client: ResetTheHotKey attempt to call a nil value Lua Files\SkillInfoz\skilltreeview [string "buf"]: 1080: attempt to index global 'JobSkillTab' (a nil value) queryRegionInfo attempt to call a nil value I have annexed images to this post to further illustrate my issues. I have had issues with making my own client work in the past, which I could not solve and made me put down the project for a few months. Now I'm trying again, still have issues I just can't solve, have been searching the internet, reading documentation and guides, watching video guides. Just can't get it to work. I deeply appreciate any and all help, a working client is all that is stopping me from having fun creating my own custom edits to RO.
-
Low vitamin D levels are associated with metastatic breast cancer priligy seratonin Hepatology 2004; 40 1222 1225
-
hello I am trying to run the Warp app to patch my client but is not running correctly in my windows 11. My Specs: Processor 13th Gen Intel(R) Core(TM) i9-13900K 3.00 GHz Installed RAM 64.0 GB (63.7 GB usable) System type 64-bit operating system, x64-based processor BaseBoard Product ROG MAXIMUS Z790 HERO Name NVIDIA GeForce RTX 4080 Adapter Type NVIDIA GeForce RTX 4080, NVIDIA compatible
-
[QoL] Show warning when trying to allocate skill points on a higher job tab
eleriaqueen replied to exequens's question in Source Requests
Class skills aren't well organized into neatly defined id ranges if I recall correctly. Some SM_ skills may have high ID's. We also need a way to check skillpoints invested in a specific job, so that if user tries to skill up a 2nd Job skill we could check if they spent all their first job skills. Oh dang, we also need to have specific code to handle Second High jobs / Third High jobs as high 2nd can go to joblvl 70. Edit: I may have found a way, but my code is very long. This time I'm using ShowError() function for testing purposes. enum Job_Tier { Basic = 0, First, First_High, Second, Second_High, Third, Third_High, Fourth }; // Helper Function: Returns the player character's job tier Job_Tier pc_get_job_tier(uint64 class_) { if (class_ & JOBL_FOURTH) return Job_Tier::Fourth; if (class_ == MAPID_RUNE_KNIGHT_T) return Job_Tier::Third_High; if (class_ == MAPID_WARLOCK_T) return Job_Tier::Third_High; if (class_ == MAPID_RANGER_T) return Job_Tier::Third_High; if (class_ == MAPID_ARCH_BISHOP_T) return Job_Tier::Third_High; if (class_ == MAPID_MECHANIC_T) return Job_Tier::Third_High; if (class_ == MAPID_GUILLOTINE_CROSS_T) return Job_Tier::Third_High; if (class_ == MAPID_ROYAL_GUARD_T) return Job_Tier::Third_High; if (class_ == MAPID_SORCERER_T) return Job_Tier::Third_High; if (class_ == MAPID_MINSTRELWANDERER_T) return Job_Tier::Third_High; if (class_ == MAPID_SURA_T) return Job_Tier::Third_High; if (class_ == MAPID_GENETIC_T) return Job_Tier::Third_High; if (class_ == MAPID_SHADOW_CHASER_T) return Job_Tier::Third_High; if (class_ & JOBL_THIRD) return Job_Tier::Third; if (class_ == MAPID_LORD_KNIGHT) return Job_Tier::Second_High; if (class_ == MAPID_HIGH_WIZARD) return Job_Tier::Second_High; if (class_ == MAPID_SNIPER) return Job_Tier::Second_High; if (class_ == MAPID_HIGH_PRIEST) return Job_Tier::Second_High; if (class_ == MAPID_WHITESMITH) return Job_Tier::Second_High; if (class_ == MAPID_ASSASSIN_CROSS) return Job_Tier::Second_High; if (class_ == MAPID_PALADIN) return Job_Tier::Second_High; if (class_ == MAPID_PROFESSOR) return Job_Tier::Second_High; if (class_ == MAPID_CLOWNGYPSY) return Job_Tier::Second_High; if (class_ == MAPID_CHAMPION) return Job_Tier::Second_High; if (class_ == MAPID_CREATOR) return Job_Tier::Second_High; if (class_ == MAPID_STALKER) return Job_Tier::Second_High; if (class_ & JOBL_2) return Job_Tier::Second; if (class_ == MAPID_SWORDMAN_HIGH) return Job_Tier::First_High; if (class_ == MAPID_MAGE_HIGH) return Job_Tier::First_High; if (class_ == MAPID_ARCHER_HIGH) return Job_Tier::First_High; if (class_ == MAPID_ACOLYTE_HIGH) return Job_Tier::First_High; if (class_ == MAPID_MERCHANT_HIGH) return Job_Tier::First_High; if (class_ == MAPID_THIEF_HIGH) return Job_Tier::First_High; if ((class_ & MAPID_BASEMASK) != MAPID_NOVICE) return Job_Tier::First; return Job_Tier::Basic; // Novice/Summoner } // Helper Function : Returns the skill's job tier Job_Tier skill_get_job_tier(uint16 skill_id) { // Novice if (skill_id > 0 && skill_id < SM_SWORD) return Job_Tier::Basic; // Swordman else if (skill_id >= SM_SWORD && skill_id <= SM_ENDURE) return Job_Tier::First; // Magician else if (skill_id >= MG_SRECOVERY && skill_id <= MG_THUNDERSTORM) return Job_Tier::First; // Acolyte else if (skill_id >= AL_DP && skill_id <= AL_CURE) return Job_Tier::First; // Merchant else if (skill_id >= MC_INCCARRY && skill_id <= MC_MAMMONITE) return Job_Tier::First; // Archer else if (skill_id >= AC_OWL && skill_id <= AC_SHOWER) return Job_Tier::First; // Thief else if (skill_id >= TF_DOUBLE && skill_id <= TF_DETOXIFY) return Job_Tier::First; // Taekwon Kid else if (skill_id >= TK_RUN && skill_id <= TK_HIGHJUMP) return Job_Tier::First; else if (skill_id == TK_MISSION) return Job_Tier::First; // Knight else if (skill_id >= KN_SPEARMASTERY && skill_id <= KN_CAVALIERMASTERY) return Job_Tier::Second; // Priest else if (skill_id >= PR_MACEMASTERY && skill_id <= PR_MAGNUS) return Job_Tier::Second; // Wizard else if (skill_id >= WZ_FIREPILLAR && skill_id <= WZ_ESTIMATION) return Job_Tier::Second; // Blacksmith else if (skill_id >= BS_IRON && skill_id <= BS_MAXIMIZE) return Job_Tier::Second; // Hunter else if (skill_id >= HT_SKIDTRAP && skill_id <= HT_SPRINGTRAP) return Job_Tier::Second; // Assassin else if (skill_id >= AS_RIGHT && skill_id <= AS_SPLASHER) return Job_Tier::Second; // Rogue else if (skill_id >= RG_SNATCHER && skill_id <= RG_PLAGIARISM) return Job_Tier::Second; // Alchemist else if (skill_id >= AM_AXEMASTERY && skill_id <= AM_RESURRECTHOMUN) return Job_Tier::Second; // Crusader else if (skill_id >= CR_TRUST && skill_id <= CR_SPEARQUICKEN) return Job_Tier::Second; // Monk else if (skill_id >= MO_IRONHAND && skill_id <= MO_COMBOFINISH) return Job_Tier::Second; // Sage else if (skill_id >= SA_ADVANCEDBOOK && skill_id <= SA_COMA) return Job_Tier::Second; // Bard & Dancer else if (skill_id >= BD_ADAPTATION && skill_id <= BD_RAGNAROK) return Job_Tier::Second; // Bard else if (skill_id >= BA_MUSICALLESSON && skill_id <= BA_APPLEIDUN) return Job_Tier::Second; // Dancer else if (skill_id >= DC_DANCINGLESSON && skill_id <= DC_SERVICEFORYOU) return Job_Tier::Second; // Lord Knight else if (skill_id >= LK_AURABLADE && skill_id <= LK_FURY) return Job_Tier::Second_High; else if (skill_id >= LK_SPIRALPIERCE && skill_id <= LK_JOINTBEAT) return Job_Tier::Second_High; // High Priest else if (skill_id >= HP_ASSUMPTIO && skill_id <= HP_MEDITATIO) return Job_Tier::Second_High; else if (skill_id == HP_MANARECHARGE) return Job_Tier::Second_High; // High Wizard else if (skill_id >= HW_SOULDRAIN && skill_id <= HW_MAGICPOWER) return Job_Tier::Second_High; else if (skill_id == HW_NAPALMVULCAN) return Job_Tier::Second_High; else if (skill_id >= HW_GANBANTEIN && skill_id <= HW_GRAVITATION) return Job_Tier::Second_High; // Paladin else if (skill_id >= PA_PRESSURE && skill_id <= PA_GOSPEL) return Job_Tier::Second_High; else if (skill_id == PA_SHIELDCHAIN) return Job_Tier::Second_High; // Champion else if (skill_id >= CH_PALMSTRIKE && skill_id <= CH_CHAINCRUSH) return Job_Tier::Second_High; else if (skill_id == CH_SOULCOLLECT) return Job_Tier::Second_High; // Professor else if (skill_id >= PF_HPCONVERSION && skill_id <= PF_SOULBURN) return Job_Tier::Second_High; else if (skill_id >= PF_MINDBREAKER && skill_id <= PF_SPIDERWEB) return Job_Tier::Second_High; else if (skill_id == PF_DOUBLECASTING) return Job_Tier::Second_High; // Assassin Cross else if (skill_id >= ASC_KATAR && skill_id <= ASC_BREAKER) return Job_Tier::Second_High; else if (skill_id >= ASC_METEORASSAULT && skill_id <= ASC_CDP) return Job_Tier::Second_High; // Sniper else if (skill_id >= SN_SIGHT && skill_id <= SN_WINDWALK) return Job_Tier::Second_High; // Whitesmith else if (skill_id >= WS_MELTDOWN && skill_id <= WS_SYSTEMCREATE) return Job_Tier::Second_High; else if (skill_id == WS_WEAPONREFINE) return Job_Tier::Second_High; else if (skill_id >= WS_CARTTERMINATION && skill_id <= WS_OVERTHRUSTMAX) return Job_Tier::Second_High; // Stalker else if (skill_id >= ST_CHASEWALK && skill_id <= ST_STEALBACKPACK) return Job_Tier::Second_High; else if (skill_id >= ST_PRESERVE && skill_id <= ST_FULLSTRIP) return Job_Tier::Second_High; // Creator else if (skill_id >= CR_ALCHEMY && skill_id <= CR_SYNTHESISPOTION) return Job_Tier::Second_High; else if (skill_id >= CR_SLIMPITCHER && skill_id <= CR_FULLPROTECTION) return Job_Tier::Second_High; else if (skill_id == CR_ACIDDEMONSTRATION) return Job_Tier::Second_High; // Clown / Gypsy else if (skill_id >= CG_ARROWVULCAN && skill_id <= CG_MARIONETTE) return Job_Tier::Second_High; else if (skill_id >= CG_LONGINGFREEDOM && skill_id <= CG_TAROTCARD) return Job_Tier::Second_High; else if (skill_id == CG_SPECIALSINGER) return Job_Tier::Second_High; // Star Gladiator else if (skill_id >= SG_FEEL && skill_id <= SG_FUSION) return Job_Tier::Second; // Soul Linker else if (skill_id == SL_ALCHEMIST) return Job_Tier::Second; else if (skill_id >= SL_MONK && skill_id <= SL_SKA) return Job_Tier::Second; else if (skill_id == SL_HIGH) return Job_Tier::Second; // else if (skill_id >= SL_DEATHKNIGHT && skill_id <= SL_GUNNER) return 2; // Gunslinger else if (skill_id >= GS_GLITTERING && skill_id <= GS_GROUNDDRIFT) return Job_Tier::Second_High; // Ninja else if (skill_id >= NJ_TOBIDOUGU && skill_id <= NJ_ISSEN) return Job_Tier::Second_High; // Rune Knight else if (skill_id >= RK_ENCHANTBLADE && skill_id <= RK_PHANTOMTHRUST) return Job_Tier::Third; else if (skill_id >= RK_DRAGONBREATH_WATER && skill_id <= RK_LUXANIMA) return Job_Tier::Third; // Guillotine Cross else if (skill_id >= GC_VENOMIMPRESS && skill_id <= GC_CROSSRIPPERSLASHER) return Job_Tier::Third; else if (skill_id == GC_DARKCROW) return Job_Tier::Third; // Arch-Bishop else if (skill_id >= AB_JUDEX && skill_id <= AB_SILENTIUM) return Job_Tier::Third; else if (skill_id == AB_SECRAMENT) return Job_Tier::Third; else if (skill_id == AB_OFFERTORIUM) return Job_Tier::Third; else if (skill_id >= AB_VITUPERATUM && skill_id <= AB_CONVENIO) return Job_Tier::Third; // Warlock else if (skill_id >= WL_WHITEIMPRISON && skill_id <= WL_FREEZE_SP) return Job_Tier::Third; else if (skill_id == WL_TELEKINESIS_INTENSE) return Job_Tier::Third; // Ranger else if (skill_id >= RA_ARROWSTORM && skill_id <= RA_ICEBOUNDTRAP) return Job_Tier::Third; else if (skill_id == RA_UNLIMIT) return Job_Tier::Third; // Mechanic else if (skill_id >= NC_MADOLICENCE && skill_id <= NC_DISJOINT) return Job_Tier::Third; else if (skill_id == NC_MAGMA_ERUPTION) return Job_Tier::Third; // Shadow Chaser else if (skill_id >= SC_FATALMENACE && skill_id <= SC_FEINTBOMB) return Job_Tier::Third; else if (skill_id == SC_ESCAPE) return Job_Tier::Third; // Royal Guard else if (skill_id >= LG_CANNONSPEAR && skill_id <= LG_INSPIRATION) return Job_Tier::Third; else if (skill_id == LG_KINGS_GRACE) return Job_Tier::Third; // Sura else if (skill_id >= SR_DRAGONCOMBO && skill_id <= SR_GENTLETOUCH_REVITALIZE) return Job_Tier::Third; else if (skill_id >= SR_HOWLINGOFLION && skill_id <= SR_RIDEINLIGHTNING) return Job_Tier::Third; else if (skill_id == SR_FLASHCOMBO) return Job_Tier::Third; // Wanderer else if (skill_id >= WA_SWING_DANCE && skill_id <= WA_MOONLIT_SERENADE) return Job_Tier::Third; // Ministrel else if (skill_id >= MI_RUSH_WINDMILL && skill_id <= MI_HARMONIZE) return Job_Tier::Third; // Wanderer && Ministrel else if (skill_id >= WM_LESSON && skill_id <= WM_UNLIMITED_HUMMING_VOICE) return Job_Tier::Third; else if (skill_id == WM_FRIGG_SONG) return Job_Tier::Third; // Sorcerer else if (skill_id >= SO_FIREWALK && skill_id <= SO_EARTH_INSIGNIA) return Job_Tier::Third; else if (skill_id == SO_ELEMENTAL_SHIELD) return Job_Tier::Third; // Genetic else if (skill_id >= GN_TRAINING_SWORD && skill_id <= GN_SLINGITEM_RANGEMELEEATK) return Job_Tier::Third; else if (skill_id == GN_ILLUSIONDOPING) return Job_Tier::Third; // Rebellion else if (skill_id >= RL_GLITTERING_GREED && skill_id <= RL_B_FLICKER_ATK) return Job_Tier::Third; // Star Emperor else if (skill_id >= SJ_LIGHTOFMOON && skill_id <= SJ_PROMINENCEKICK) return Job_Tier::Third; // Soul Reaper else if (skill_id >= SP_SOULGOLEM && skill_id <= SP_KAUTE) return Job_Tier::Third; // Kagerou && Oboro else if (skill_id >= KO_YAMIKUMO && skill_id <= KO_IZAYOI) return Job_Tier::Third; // Kagerou else if (skill_id >= KG_KAGEHUMI && skill_id <= KG_KAGEMUSYA) return Job_Tier::Third; // Oboro else if (skill_id >= OB_ZANGETSU && skill_id <= OB_AKAITSUKI) return Job_Tier::Third; // Super Novice 2 else if (skill_id >= NV_BREAKTHROUGH && skill_id <= NV_TRANSCENDENCE) return Job_Tier::Third; // ALL 3rd jobs else if (skill_id == ALL_FULL_THROTTLE) return Job_Tier::Third; // Dragon Knight else if (skill_id >= DK_SERVANTWEAPON && skill_id <= DK_STORMSLASH) return Job_Tier::Fourth; else if (skill_id == DK_DRAGONIC_BREATH) return Job_Tier::Fourth; else if (skill_id == DK_DRAGONIC_PIERCE) return Job_Tier::Fourth; // Arc Mage else if (skill_id >= AG_DEADLY_PROJECTION && skill_id <= AG_FROZEN_SLASH) return Job_Tier::Fourth; else if (skill_id == AG_DESTRUCTIVE_HURRICANE_CLIMAX) return Job_Tier::Fourth; else if (skill_id == AG_ENERGY_CONVERSION) return Job_Tier::Fourth; // Inquisitor else if (skill_id >= IQ_POWERFUL_FAITH && skill_id <= IQ_THIRD_EXOR_FLAME) return Job_Tier::Fourth; else if (skill_id == IQ_BLAZING_FLAME_BLAST) return Job_Tier::Fourth; // Imperial Guard else if (skill_id >= IG_GUARD_STANCE && skill_id <= IG_CROSS_RAIN) return Job_Tier::Fourth; else if (skill_id >= IG_RADIANT_SPEAR && skill_id <= IG_IMPERIAL_PRESSURE) return Job_Tier::Fourth; // Cardinal else if (skill_id >= CD_REPARATIO && skill_id <= CD_FRAMEN) return Job_Tier::Fourth; else if (skill_id == CD_DIVINUS_FLOS) return Job_Tier::Fourth; // Shadow Cross else if (skill_id >= SHC_SHADOW_EXCEED && skill_id <= SHC_FATAL_SHADOW_CROW) return Job_Tier::Fourth; else if (skill_id == SHC_CROSS_SLASH) return Job_Tier::Fourth; // Meister else if (skill_id >= MT_AXE_STOMP && skill_id <= MT_SUMMON_ABR_INFINITY) return Job_Tier::Fourth; else if (skill_id >= MT_SPARK_BLASTER && skill_id <= MT_MIGHTY_SMASH) return Job_Tier::Fourth; else if (skill_id >= MT_RUSH_STRIKE && skill_id <= MT_ENERGY_CANNONADE) return Job_Tier::Fourth; // Biolo else if (skill_id >= BO_ACIDIFIED_ZONE_WATER_ATK && skill_id <= BO_ACIDIFIED_ZONE_FIRE_ATK) return Job_Tier::Fourth; else if (skill_id >= BO_BIONIC_PHARMACY && skill_id <= BO_HELLTREE) return Job_Tier::Fourth; else if (skill_id >= BO_EXPLOSIVE_POWDER && skill_id <= BO_MAYHEMIC_THORNS) return Job_Tier::Fourth; else if (skill_id >= BO_MYSTERY_POWDER && skill_id <= BO_DUST_EXPLOSION) return Job_Tier::Fourth; // Abyss Chaser else if (skill_id >= ABC_DAGGER_AND_BOW_M && skill_id <= ABC_FRENZY_SHOT) return Job_Tier::Fourth; else if (skill_id >= ABC_HIT_AND_SLIDING && skill_id <= ABC_ABYSS_FLAME) return Job_Tier::Fourth; // Wind Hawk else if (skill_id >= WH_ADVANCED_TRAP && skill_id <= WH_FLAMETRAP) return Job_Tier::Fourth; else if (skill_id == WH_WILD_WALK) return Job_Tier::Fourth; // Troubadour && Trouvere else if (skill_id >= TR_STAGE_MANNER && skill_id <= TR_PRON_MARCH) return Job_Tier::Fourth; else if (skill_id == TR_RHYTHMICAL_WAVE) return Job_Tier::Fourth; // Elemental Master else if (skill_id >= EM_MAGIC_BOOK_M && skill_id <= EM_ELEMENTAL_VEIL) return Job_Tier::Fourth; else if (skill_id == EM_PSYCHIC_STREAM) return Job_Tier::Fourth; // Night Watch else if (skill_id >= NW_P_F_I && skill_id <= NW_MISSION_BOMBARD) return Job_Tier::Fourth; else if (skill_id >= NW_WILD_SHOT && skill_id <= NW_MIDNIGHT_FALLEN) return Job_Tier::Fourth; // Soul Ascetic else if (skill_id >= SOA_TALISMAN_MASTERY && skill_id <= SOA_SOUL_OF_HEAVEN_AND_EARTH) return Job_Tier::Fourth; // Spirit Handler else if (skill_id >= SH_MYSTICAL_CREATURE_MASTERY && skill_id <= SH_BLESSING_OF_MYSTICAL_CREATURES) return Job_Tier::Fourth; else if (skill_id >= SH_CHUL_HO_BATTERING && skill_id <= SH_HYUN_ROK_SPIRIT_POWER) return Job_Tier::Fourth; // Hyper Novice else if (skill_id >= HN_SELFSTUDY_TATICS && skill_id <= HN_RULEBREAK) return Job_Tier::Fourth; else if (skill_id == HN_OVERCOMING_CRISIS) return Job_Tier::Fourth; // Sky Emperor else if (skill_id >= SKE_SKY_MASTERY && skill_id <= SKE_ENCHANTING_SKY) return Job_Tier::Fourth; else if (skill_id >= SKE_SKY_SUN && skill_id <= SKE_STAR_LIGHT_KICK) return Job_Tier::Fourth; // Shinkiro && Shiranui else if (skill_id >= SS_TOKEDASU && skill_id <= SS_ANKOKURYUUAKUMU) return Job_Tier::Fourth; else if (skill_id == SS_FOUR_CHARM) return Job_Tier::Fourth; // Sky Emperor else if (skill_id >= SKE_SKY_MASTERY && skill_id <= SKE_ENCHANTING_SKY) return Job_Tier::Fourth; return Job_Tier::Basic; // Default to Novice if unknown } /*========================================== * Update skill_lv for player sd * Skill point allocation *------------------------------------------*/ void pc_skillup(map_session_data *sd,uint16 skill_id) { uint16 idx = skill_get_index(skill_id); nullpo_retv(sd); if (!idx) { if (skill_id) ShowError("pc_skillup: Player attempts to level up invalid skill '%d'\n", skill_id); return; } int32 skill_point = pc_calc_skillpoint( sd ); int32 novice_max_skillpoint = job_db.find( JOB_NOVICE )->max_job_level - 1; int32 summoner_max_skillpoint = job_db.find( JOB_SUMMONER )->max_job_level - 1; int32 max_skillpoint_1st = job_db.find( JOB_SWORDMAN )->max_job_level - 1; int32 max_skillpoint_2nd = job_db.find( JOB_KNIGHT )->max_job_level - 1; int32 max_skillpoint_2nd_high = job_db.find( JOB_LORD_KNIGHT )->max_job_level - 1; int32 max_skillpoint_3rd = job_db.find( JOB_RUNE_KNIGHT )->max_job_level - 1; int32 max_skillpoint_4th = job_db.find( JOB_DRAGON_KNIGHT )->max_job_level - 1; int32 skillpoint_1st = sd->change_level_2nd - 1; int32 skillpoint_2nd = sd->change_level_3rd - 1; int32 must_spend_novice = novice_max_skillpoint - skill_point; int32 must_spend_1st = min(max_skillpoint_1st, novice_max_skillpoint + skillpoint_1st - skill_point); int32 must_spend_2nd = min(max_skillpoint_2nd, novice_max_skillpoint + skillpoint_1st + skillpoint_2nd - skill_point); int32 must_spend_2nd_high = min(max_skillpoint_2nd_high, novice_max_skillpoint + skillpoint_1st + skillpoint_2nd - skill_point); int32 must_spend_3rd = min(max_skillpoint_3rd, novice_max_skillpoint + skillpoint_1st + skillpoint_2nd + max_skillpoint_3rd - skill_point); char helper_msg_novice[128]; char helper_msg_novice_high[128]; char helper_msg_1st[128]; char helper_msg_1st_high[128]; char helper_msg_2nd[128]; char helper_msg_2nd_high[128]; char helper_msg_3rd[128]; sprintf(helper_msg_novice, "%s", "You need to spend %d more skillpoints in Novice Skill Tree\n"); sprintf(helper_msg_novice_high, "%s", "You need to spend %d more skillpoints in Novice High Skill Tree\n"); sprintf(helper_msg_1st, "%s", "You need to spend %d more skillpoints in 1st Job Skill Tree\n"); sprintf(helper_msg_1st_high, "%s", "You need to spend %d more skillpoints in 1st High Job Skill Tree\n"); sprintf(helper_msg_2nd, "%s", "You need to spend %d more skillpoints in 2nd Job Skill Tree\n"); sprintf(helper_msg_2nd_high, "%s", "You need to spend %d more skillpoints in 2nd High Job Skill Tree\n"); sprintf(helper_msg_3rd, "%s", "You need to spend %d more skillpoints in 3rd Job Skill Tree\n"); if (pc_get_job_tier(sd->class_) == Job_Tier::First) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { ShowError(helper_msg_novice, must_spend_novice); } } if (pc_get_job_tier(sd->class_) == Job_Tier::First_High) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice, must_spend_novice); } } } if (pc_get_job_tier(sd->class_) == Job_Tier::Second) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice, must_spend_novice); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second && (skill_point < novice_max_skillpoint + skillpoint_1st)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice, must_spend_novice); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { ShowError(helper_msg_1st, must_spend_1st); } } } if (pc_get_job_tier(sd->class_) == Job_Tier::Second_High) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice_high, must_spend_novice); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second && (skill_point < novice_max_skillpoint + skillpoint_1st)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice_high, must_spend_novice); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { ShowError(helper_msg_1st_high, must_spend_1st); } } } if (pc_get_job_tier(sd->class_) == Job_Tier::Third) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice, must_spend_novice); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second && (skill_point < novice_max_skillpoint + skillpoint_1st)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice, must_spend_novice); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { ShowError(helper_msg_1st, must_spend_1st); } } if (skill_get_job_tier(skill_id) == Job_Tier::Third && (skill_point < novice_max_skillpoint + skillpoint_1st + max_skillpoint_2nd)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice, must_spend_novice); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { ShowError(helper_msg_1st, must_spend_1st); } if (skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) { ShowError(helper_msg_2nd, must_spend_2nd); } } } if (pc_get_job_tier(sd->class_) == Job_Tier::Third_High) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice_high, must_spend_novice); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second && (skill_point < novice_max_skillpoint + skillpoint_1st)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice_high, must_spend_novice); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { ShowError(helper_msg_1st_high, must_spend_1st); } } if ((skill_get_job_tier(skill_id) == Job_Tier::Third || Job_Tier::Third_High) && (skill_point < novice_max_skillpoint + skillpoint_1st + max_skillpoint_2nd)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice_high, must_spend_novice); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { ShowError(helper_msg_1st_high, must_spend_1st); } if (skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) { ShowError(helper_msg_2nd_high, must_spend_2nd_high); } } } if (pc_get_job_tier(sd->class_) == Job_Tier::Fourth) { if (skill_get_job_tier(skill_id) == Job_Tier::First && (skill_point < novice_max_skillpoint)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice, must_spend_novice); } } if (skill_get_job_tier(skill_id) == Job_Tier::Second && (skill_point < novice_max_skillpoint + skillpoint_1st)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice, must_spend_novice); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { ShowError(helper_msg_1st, must_spend_1st); } } if (skill_get_job_tier(skill_id) == Job_Tier::Third && (skill_point < novice_max_skillpoint + skillpoint_1st + max_skillpoint_2nd)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice, must_spend_novice); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { ShowError(helper_msg_1st, must_spend_1st); } if (skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) { ShowError(helper_msg_2nd, must_spend_2nd); } } if (skill_get_job_tier(skill_id) == Job_Tier::Fourth && (skill_point < novice_max_skillpoint + skillpoint_1st + max_skillpoint_2nd + max_skillpoint_3rd)) { if (skill_point < novice_max_skillpoint) { ShowError(helper_msg_novice, must_spend_novice); } if (skill_point < novice_max_skillpoint + skillpoint_1st) { ShowError(helper_msg_1st, must_spend_1st); } if (skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd) { ShowError(helper_msg_2nd, must_spend_2nd); } if (skill_point < novice_max_skillpoint + skillpoint_1st + skillpoint_2nd + max_skillpoint_3rd) { ShowError(helper_msg_3rd, must_spend_3rd); } } } ... Rest of Function ... } Summoner and Super Novice are likely badly handled. -
[QoL] Show warning when trying to allocate skill points on a higher job tab
exequens replied to exequens's question in Source Requests
Thanks for telling me to use code widget, edited first post. Also thanks for showing a clear working example. So if that works, then what we should do is make a function that can determine what skill_id is belong to what job tab? Something like this maybe? // Returns the job tier (Novice=0, 1st=1, 2nd=2, etc.) int pc_get_job_tier(uint64 class_) { if (class_ & JOBL_FOURTH) return 4; if (class_ & JOBL_THIRD) return 3; if (class_ & JOBL_2) return 2; if ((class_ & MAPID_BASEMASK) != MAPID_NOVICE) return 1; return 0; // Novice/Summoner } // Returns the skill's job tier int skill_get_job_tier(uint16 skill_id) { if (skill_id >= NV_BASIC && skill_id <= NV_TRICKDEAD) return 0; if (skill_id >= SM_SWORD && skill_id <= SM_BASH) return 1; return 0; // Default to Novice if unknown } I'm honestly not sure... -
TOKEI is GOD in EATHENA history. im so proud of you -the pugs
-
hello how put the name of monster on top and the element and race in the bottom? thank you
- Last week
-
-
The new enchant system cannot be opened/used correctly...
SilverB replied to redwingangel's question in Source Support
help.. I'm confused. what is 0 and 12460 here? where can i see the table guide? -
[QoL] Show warning when trying to allocate skill points on a higher job tab
eleriaqueen replied to exequens's question in Source Requests
Hi. I'm trying to achieve this too now that I read your request, It made me remember that a while ago I wanted to do something like what you explained. Here's what I managed to produce so far, sadly it only works with Novice as I'm checking NV_BASIC skill level. /*========================================== * Update skill_lv for player sd * Skill point allocation *------------------------------------------*/ void pc_skillup(map_session_data *sd,uint16 skill_id) { uint16 idx = skill_get_index(skill_id); nullpo_retv(sd); if (!idx) { if (skill_id) ShowError("pc_skillup: Player attempts to level up invalid skill '%d'\n", skill_id); return; } // If user tries to put points in a skill other than NV_BASIC while NV_BASIC is not maxed if(skill_id > NV_BASIC && sd->status.skill[NV_BASIC].lv < skill_tree_get_max(NV_BASIC, sd->status.class_)){ StringBuf *nov_msg = StringBuf_Malloc(); StringBuf_Printf(nov_msg, "You must spend %d skillpoints on Basic Skill in Novice skill tree first", skill_tree_get_max(NV_BASIC, sd->status.class_)); clif_displaymessage(sd->fd, StringBuf_Value(nov_msg)); StringBuf_Free(nov_msg); // Do not spend the point // return; } ... Rest of the function ... } Edit: I can't find a way to check how many skillpoints have been invested in a specific job by the player. With that info we could check invested points in 1st / 2nd / 3rd jobs and display a message when trying to up a skill when not all previous job skills have been invested.