Avatar utilizator
winkiller
Membru Începător
Membru Începător
  • Mesaje: 6
    Membru din: 31 Iul 2025, 20:45
  • Reacții: 1
  • Mesaje utile: 1
  • Medalii

    Avatar utilizator
    winkiller
    Membru Începător
    Membru Începător
    *Problemă/Întrebare:
    Hi, How can I disable animation for mounts when the horse level is under 11? (Attack system like horse)

    I already make the server side change, so when is under 11 level -> no damage. But the animation still running.
    Rezolvat de winkiller » 20 Sep 2025, 22:23
    Avatar utilizator
    Uriel
    Robot
    Robot
  • Mesaje: 237
    Membru din: 17 Mai 2025, 15:58
  • Reacții: 0
  • Mesaje utile: 3
  • Status: Sunt doar un Bot :)
  • Regat: Shinsoo
  • Medalii

    Avatar utilizator
    Uriel
    Robot
    Robot

    Mesaj

    Salut, winkiller!

    Îți recomand câteva link-uri utile care te pot ajuta să rezolvi problema mai rapid:

    - Alte probleme rezolvate
    - Fixuri Metin2
    - Tutoriale
    - Cum resetez parola MySQL
    - Compilare sursă Metin2
    - Lista FreeBSD pentru compilare


    Și dacă vrei ajutor direct, te așteptăm pe serverul nostru de Discord — chat activ, suport live și o comunitate faină gata să te ajute! Pentru a intra pe serverul de Discord: Click aici
    Notă: Acesta este un răspuns generat de AI și poate conține erori. Vă rugăm să-l tratați ca atare.

    Link-uri utile:

    - Alte probleme rezolvate
    - Fixuri Metin2
    - Tutoriale
    - Cum resetez parola MySQL
    - Compilare sursă Metin2
    - Lista FreeBSD pentru compilare


    Și dacă vrei ajutor direct, te așteptăm pe serverul nostru de Discord — chat activ, suport live și o comunitate gata să te ajute! Click aici
    See full signature
    Avatar utilizator
    Dintisor
    Membru Avansat
    Membru Avansat
  • Mesaje: 59
    Membru din: 21 Dec 2024, 10:42
  • Reacții: 69
  • Mesaje utile: 7
  • Status: Pierd vremea ^.^
  • Regat: Jinno
  • Medalii

    Avatar utilizator
    Dintisor
    Membru Avansat
    Membru Avansat

    Mesaj

    You’ve already blocked damage below level 11, but the horse attack animation is still playing, and you want to completely disable it.

    In Metin2, this isn’t only about damage – the input that triggers the attack motion/animation must also be controlled. You have a few options:

    🔹 1. In the client source (the cleanest method)

    The horse attack is linked to horse.cpp (or horse_riding.cpp) + GameCharacter.cpp.

    When the player presses the horse attack key, the client sends the command to start the attack motion.

    You can add a simple check: if horse level < 11 → don’t send the animation command.

    Example (simplified pseudo-code):

    if (pHorse->GetLevel() < 11)
    return; // block the animation


    This way, the animation never starts.

    🔹 2. In the server source

    You already blocked damage on the server.
    If you also want to block the animation server-side, you could send back a motion cancel packet when the horse is under level 11. The downside: the animation will start and then stop abruptly, which doesn’t look very good.

    🔹 3. Quick workaround (hacky method)

    In horse_skill_proto or skill_proto, you can set the horse attack animation to empty for levels below 11 (so there’s no motion). But this complicates your DB and makes it harder to manage level differences.

    ✅ Best recommendation: put the condition directly in the client (in the file that processes the horse attack input). This way, the animation won’t even start.
    Avatar utilizator
    SCOOB
    Administrator
    Administrator
  • Mesaje: 4918
    Membru din: 07 Aug 2024, 18:53
  • Reacții: 122284
  • Mesaje utile: 47
  • Status: Pe aici.. 🤠
    Server: Saga2 - Soon
  • Regat: Jinno
  • [ID Discord]
  • Avatar utilizator
    SCOOB
    Administrator
    Administrator

    Mesaj

    You mean skills?

    Look in char_horse.cpp for:
    Code:
    bool CHARACTER::CanUseHorseSkill()
    { 
    	return (IsRiding() && GetHorseGrade() == 3); 
    }
    And edit it as you like.
    Comunitatea Metin2 Romania este si pe Discord! :ymcowboy:

    2500+ membri • Chat activ zilnic • Support • Cereri & Resurse

    ► discord.gg/jWxeDSf7HP ◄





    See full signature
    Avatar utilizator
    winkiller
    Membru Începător
    Membru Începător
  • Mesaje: 6
    Membru din: 31 Iul 2025, 20:45
  • Reacții: 1
  • Mesaje utile: 1
  • Medalii

    Avatar utilizator
    winkiller
    Membru Începător
    Membru Începător

    Mesaj

    malý zub scrie: ↑ You’ve already blocked damage below level 11, but the horse attack animation is still playing, and you want to completely disable it.

    In Metin2, this isn’t only about damage – the input that triggers the attack motion/animation must also be controlled. You have a few options:

    🔹 1. In the client source (the cleanest method)

    The horse attack is linked to horse.cpp (or horse_riding.cpp) + GameCharacter.cpp.

    When the player presses the horse attack key, the client sends the command to start the attack motion.

    You can add a simple check: if horse level < 11 → don’t send the animation command.

    Example (simplified pseudo-code):

    if (pHorse->GetLevel() < 11)
    return; // block the animation


    This way, the animation never starts.

    🔹 2. In the server source

    You already blocked damage on the server.
    If you also want to block the animation server-side, you could send back a motion cancel packet when the horse is under level 11. The downside: the animation will start and then stop abruptly, which doesn’t look very good.

    🔹 3. Quick workaround (hacky method)

    In horse_skill_proto or skill_proto, you can set the horse attack animation to empty for levels below 11 (so there’s no motion). But this complicates your DB and makes it harder to manage level differences.

    ✅ Best recommendation: put the condition directly in the client (in the file that processes the horse attack input). This way, the animation won’t even start.
    On the server side I already do it. But the animation doesnt look good as you say. I want to disable it on the client side, but in InstanceBase.cpp there is no HorseLevel... There is only getlevel but the value is base on mob Vnum... Start like this:

    UINT CInstanceBase::SHORSE::GetLevel()
    {
    if (m_pkActor)
    {

    DWORD mount = m_pkActor->GetRace();
    switch (mount)
    {
    case 20101:
    case 20102:
    case 20103:
    return 1;
    case 20104:
    case 20105:
    case 20106:
    return 2;
    case 20107:
    case 20108:


    So now I am trying to send new packet with horse level.
    Avatar utilizator
    winkiller
    Membru Începător
    Membru Începător
  • Mesaje: 6
    Membru din: 31 Iul 2025, 20:45
  • Reacții: 1
  • Mesaje utile: 1
  • Medalii

    Avatar utilizator
    winkiller
    Membru Începător
    Membru Începător

    Mesaj

    [HF]White scrie: ↑ You mean skills?

    Look in char_horse.cpp for:
    Code:
    bool CHARACTER::CanUseHorseSkill()
    { 
    	return (IsRiding() && GetHorseGrade() == 3); 
    }
    And edit it as you like.
    I meen only animation on mount when attacking with horse level under 11.
    Avatar utilizator
    SCOOB
    Administrator
    Administrator
  • Mesaje: 4918
    Membru din: 07 Aug 2024, 18:53
  • Reacții: 122284
  • Mesaje utile: 47
  • Status: Pe aici.. 🤠
    Server: Saga2 - Soon
  • Regat: Jinno
  • [ID Discord]
  • Avatar utilizator
    SCOOB
    Administrator
    Administrator

    Mesaj

    winkiller scrie: ↑
    [HF]White scrie: ↑ You mean skills?

    Look in char_horse.cpp for:
    Code:
    bool CHARACTER::CanUseHorseSkill()
    { 
    	return (IsRiding() && GetHorseGrade() == 3); 
    }
    And edit it as you like.
    I meen only animation on mount when attacking with horse level under 11.
    Do this but in reverse:
    ataca-toate-mount-urile-t1076.html

    This is default UINT CInstanceBase::SHORSE::GetLevel():
    Code:
    UINT CInstanceBase::SHORSE::GetLevel()
    {
    	if (m_pkActor)
    	{
    		DWORD mount = m_pkActor->GetRace();
    		switch (mount)
    		{
    			case 20101:
    			case 20102:
    			case 20103:
    				return 1;
    			case 20104:
    			case 20105:
    			case 20106:
    				return 2;
    			case 20107:
    			case 20108:
    			case 20109:
    			case 20110:
    			case 20111:
    			case 20112: 
    			case 20113: 
    			case 20114:
    			case 20115:
    			case 20116:
    			case 20117:
    			case 20118:
    			case 20120:
    			case 20121:
    			case 20122:
    			case 20123:
    			case 20124:
    			case 20125:
    			case 20233: 
    			case 20234:
    			case 20235:
    			case 20236:
    			case 20237:
    			case 20238:
    			case 20239:
    			case 20240:
    			case 20241:
    			case 20242:
    			case 20243:
    			case 20244:
    			case 20245:
    			case 20246:
    			case 20247:
    			case 20248:
    			case 20249:
    				return 3;
    			case 20119:
    			case 20219:
    			case 20220:
    			case 20221:
    			case 20222:
    				return 2;
    		}
    
    
    		{
    			if ((20205 <= mount &&  20208 >= mount) ||
    				(20214 == mount) || (20217 == mount)	
    				)
    				return 2;
    
    
    			if ((20209 <= mount &&  20212 >= mount) || 
    				(20215 == mount) || (20218 == mount) ||	
    				(20220 == mount)
    				)
    				return 3;
    		}
    	}
    	return 0;
    }
    
    
    Comunitatea Metin2 Romania este si pe Discord! :ymcowboy:

    2500+ membri • Chat activ zilnic • Support • Cereri & Resurse

    ► discord.gg/jWxeDSf7HP ◄





    See full signature
    Avatar utilizator
    winkiller
    Membru Începător
    Membru Începător
  • Mesaje: 6
    Membru din: 31 Iul 2025, 20:45
  • Reacții: 1
  • Mesaje utile: 1
  • Medalii

    Avatar utilizator
    winkiller
    Membru Începător
    Membru Începător

    Mesaj

    That's not work because getLevel return only level on specific mount vnum. But I figure it by myself. I am sending new packet to client with horse level.
    I will upload how I did it.:

    Server side:
    Packet.h:
    Search:
    Code:
    HEADER_GC_AUTH_SUCCESS_OPENID	= 154,
    Add:
    Code:
    HEADER_GC_HORSE_LEVEL			= 160,


    Search:
    Code:
    #pragma pack()
    Add over:
    Code:
    typedef struct SPacketHorseLevel
    {
        BYTE header;
        BYTE level;
    } TPacketHorseLevel;
    packet_info.cpp:


    Search:
    Code:
    Set(HEADER_CG_STATE_CHECKER, sizeof(BYTE), "ServerStateCheck", false);
    Add under:
    Code:
    Set(HEADER_GC_HORSE_LEVEL, sizeof(TPacketHorseLevel), "HorseLevel", false);


    char.cpp:
    Search:
    Code:
    void CHARACTER::MountVnum(DWORD vnum) {..}
    Add under:
    Code:
    void CHARACTER::SendHorseLevel()
    {
        if (!GetDesc())
            return;
    
        TPacketHorseLevel p;
        p.header = HEADER_GC_HORSE_LEVEL;
        p.level  = GetHorseLevel(); // existující metoda, co vrací horse level
    
        GetDesc()->Packet(&p, sizeof(p));
    }


    char_horse.cpp
    Modify this function like this:
    Code:
    void CHARACTER::SetHorseLevel(int iLevel)
    {
    	CHorseRider::SetHorseLevel(iLevel);
    	SetSkillLevel(SKILL_HORSE, GetHorseLevel());
    	SendHorseLevel();
    }


    input_login.cpp:
    At the end of this function:
    Code:
    void CInputLogin::Entergame(LPDESC d, const char * data)
    add before }:
    Code:
    ch->SendHorseLevel();


    Client-side:
    Packet.h:
    Search:
    Code:
    HEADER_GC_AUTH_SUCCESS_OPENID	= 154,
    Add:
    Code:
    HEADER_GC_HORSE_LEVEL			= 160,


    Search:
    Code:
    #pragma pack()
    Add over:
    Code:
    typedef struct SPacketHorseLevel
    {
        BYTE header;
        BYTE level;
    } TPacketHorseLevel;


    PythonNetworkStreamPhaseGame.cpp:
    Search:
    Code:
    default:
    	ret = RecvDefaultPacket(header);
    	break;
    }
    Add before:
    Code:
    case HEADER_GC_HORSE_LEVEL:
    	ret = RecvHorseLevel();
    	break;


    Add this on the end:
    Code:
    bool CPythonNetworkStream::RecvHorseLevel()
    {
    	TPacketHorseLevel kPacket;
    
    	if (!Recv(sizeof(kPacket), &kPacket))
    		return false;
    
    	CPythonPlayer::Instance().SetHorseLevel(kPacket.level);
    
    	return true;
    }


    PythonNetworkStream.h:
    Add:
    Code:
    bool RecvHorseLevel();
    PythonPlayer.h:
    add in public:
    Code:
    void SetHorseLevel(int level) { m_iHorseLevel = level; }
    int  GetHorseLevel() const { return m_iHorseLevel; }


    PythonPlayer.cpp:
    In this funcs:
    Code:
    void CPythonPlayer::Clear()
    and
    Code:
    CPythonPlayer::CPythonPlayer(void)
    add:
    m_iHorseLevel = 0;

    instancebase.cpp:
    And modify start the function GetLevel like this:
    Code:
    UINT CInstanceBase::SHORSE::GetLevel()
    {
    	if (m_pkActor)
    	{
    		 int horseLevel = CPythonPlayer::Instance().GetHorseLevel();
            if (horseLevel >= 11 && horseLevel < 20)
                return 2;
            else if (horseLevel >= 21)
                return 3;

    Înapoi la “Probleme rezolvate”

    Discord ID copiat: