Hello everyone! I've always found it illogical to have a clickable skill called "Call Horse" that does nothing, forcing players to use items like 50051, 50052, or 50053.
With this little tutorial, you can make the "Call Horse" skill (131) fully functional directly from the skill bark.
Features:
- MP Scaling: The mana cost starts at 250 MP (level 0) and scales down to 50 MP (level 10).
- Success Chance: Follows the classic probability (starts at 10% and reaches 100% at level 10).
- Anti-Spam: Prevents MP consumption if the horse is already summoned.
- Level 0 fix: The skill is usable even if the player hasn't read any books yet.
Tutorial:
Server-side:
Open char_skill.cpp and search for:
if (dwVnum == SKILL_HORSE_SUMMON)
{
if (GetSkillLevel(dwVnum) == 0)
return false;
if (GetHorseLevel() <= 0)
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("말이 없습니다. 마굿간 경비병을 찾아가세요."));
else
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("말 소환 아이템을 사용하세요."));
return true;
}
#ifdef ENABLE_HORSE_SUMMON_SKILL
if (dwVnum == SKILL_HORSE_SUMMON)
{
// 1. Check if the horse is already summoned
if (get_pointer(m_chHorse) != NULL)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("HORSE_ALREADY_SUMMONED"));
return true;
}
// 2. Check if the player owns a horse
if (GetHorseLevel() <= 0)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("YOU_DONT_HAVE_HORSE"));
return true;
}
// 3. Calculate dynamic MP cost (250 at lv0 -> 50 at lv10)
BYTE bSkillLev = GetSkillLevel(dwVnum);
int iNeededSP = 250 - (MIN(10, bSkillLev) * 20);
// 4. Check if player has enough MP
if (GetSP() < iNeededSP)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("NOT_ENOUGH_SP_FOR_SUMMON"));
return true;
}
// 5. Check if the horse is dead
if (GetHorseHealth() <= 0)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("HORSE_IS_DEAD_REVIVE_IT"));
return true;
}
// --- ALL CHECKS PASSED: NOW SUBTRACT MP ---
PointChange(POINT_SP, -iNeededSP);
// 6. Probability Logic
int prob = 10;
if (bSkillLev == 1) prob = 15;
else if (bSkillLev == 2) prob = 20;
else if (bSkillLev >= 3) prob = MIN(100, bSkillLev * 10);
if (number(1, 100) <= prob)
{
HorseSummon(true);
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("HORSE_SUMMON_SUCCESS"));
}
else
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("HORSE_SUMMON_FAILED"));
}
return true;
}
#else
if (dwVnum == SKILL_HORSE_SUMMON)
{
if (GetSkillLevel(dwVnum) == 0)
return false;
if (GetHorseLevel() <= 0)
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("말이 없습니다. 마굿간 경비병을 찾아가세요."));
else
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("말 소환 아이템을 사용하세요."));
return true;
}
#endif
#define ENABLE_HORSE_SUMMON_SKILL
"YOU_DONT_HAVE_HORSE";
"You don't have a horse.";
"HORSE_IS_DEAD_REVIVE_IT";
"Your horse is dead. You must revive it first.";
"NOT_ENOUGH_SP_FOR_SUMMON";
"Not enough MP to summon the horse.";
"HORSE_SUMMON_FAILED";
"The horse summon has failed.";
"HORSE_SUMMON_SUCCESS";
"The horse has been summoned.";
"HORSE_ALREADY_SUMMONED";
"Your horse is already summoned.";
Open UserInterface/PythonPlayerSkill.cpp and search:
if (m_sysIsLevelLimit)
{
if (rkSkillInst.iLevel <= 0) if (m_sysIsLevelLimit)
{
#ifdef ENABLE_HORSE_SUMMON_SKILL
if (rkSkillInst.iLevel <= 0 && rkSkillInst.dwIndex != 131)
#else
if (rkSkillInst.iLevel <= 0)#define ENABLE_HORSE_SUMMON_SKILL________________________
Regards






