summaryrefslogblamecommitdiff
path: root/src/map/clif.t.hpp
blob: 1789ee8d618e62a19afe8d24dcff33e54a87f31a (plain) (tree)
1
            




















                                                                           
                  
 
                  
 
                             
 
                             
 
                              
 

                            

 

              













































































                                                                                 














                                                                    


























































































                                                           
     
                                    
      



















































































                                     
     



                                     
      







                                       
     
                                       

      
                                       

      
                                       
      
                                       
     
                                       

      
                                       
      
 
     
                                       

      
                                       
      


                                       
     
                                       

      
                                       
      
                                       
     
                                       

      
                                       

      
                                       
      
                                       
     
                                       

      
                                       

      
                                       

      
                                       

      
                                       
      
                                       
     
                                       

      
                                       

      
                                       

      
                                       

      
                                       
      
 
     
                                       

      
                                       

      
                                       

      
                                       

      
                                       
      
 
     
                                       

      
                                       

      
                                       

      
                                       

      
                                       

      
                                       

      
                                       
      

                                       
     
                                       

      
                                       

      
                                       

      
                                       
      

                                       
     
                                       

      
                                       

      
                                       
      
 
     
                                       
      



                                       
     
                                       
      





















































































































                                                                                          













                                                    
                                                            






















                                                                             
                                                          










                                                                             
 










                                                    
                                                            






















                                                                             
                                                          







































                                                                             
                   
#pragma once
//    clif.t.hpp - Network interface to the client.
//
//    Copyright © ????-2004 Athena Dev Teams
//    Copyright © 2004-2011 The Mana World Development Team
//    Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com>
//
//    This file is part of The Mana World (Athena server)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "fwd.hpp"

#include <cstdint>

#include "../ints/little.hpp"

#include "../compat/iter.hpp"

#include "../generic/enum.hpp"

#include "../mmo/consts.hpp"
#include "../mmo/enums.hpp"


namespace tmwa
{
namespace e
{
// [Fate] status.option properties.  These are persistent status changes.
// IDs that are not listed are not used in the code (to the best of my knowledge)
enum class Option : uint16_t
{
    ZERO            = 0x0000,

    // [Fate] This is the GM `@hide' flag
    HIDE            = 0x0040,
    // [Fate] Complete invisibility to other clients
    INVISIBILITY    = 0x1000,

    // ?
    REAL_ANY_HIDE   = HIDE,
};
enum class Opt1 : uint16_t
{
    ZERO            = 0,
    _stone1         = 1,
    _freeze         = 2,
    _stan           = 3,
    _sleep          = 4,
    _stone6         = 6,
};
enum class Opt2 : uint16_t
{
    ZERO            = 0x0000,
    _poison         = 0x0001,
    _curse          = 0x0002,
    _silence        = 0x0004,
    BLIND           = 0x0010,
    _speedpotion0   = 0x0020,
    _signumcrucis   = 0x0040,
    _atkpot         = 0x0080,
    _heal           = 0x0100,
    _slowpoison     = 0x0200,
};
enum class Opt3 : uint16_t
{
    ZERO            = 0x0000,
    _concentration  = 0x0001,
    _overthrust     = 0x0002,
    _energycoat     = 0x0004,
    _explosionspirits = 0x0008,
    _steelbody      = 0x0010,
    _berserk        = 0x0080,

    _marionette     = 0x0400,
    _assumptio      = 0x0800,
};

ENUM_BITWISE_OPERATORS(Option)
ENUM_BITWISE_OPERATORS(Opt2)
ENUM_BITWISE_OPERATORS(Opt3)
}
using e::Option;
using e::Opt1;
using e::Opt2;
using e::Opt3;


enum class ItemType : uint8_t
{
    USE     = 0,    // in eA, healing only
    _1      = 1,    // unused
    _2      = 2,    // in eA, other usable items
    JUNK    = 3,    // "useless" items (e.g. quests)
    WEAPON  = 4,    // all weapons
    ARMOR   = 5,    // all other equipment
    _6      = 6,    // in eA, card
    _7      = 7,    // in eA, pet egg
    _8      = 8,    // in eA, pet equipment
    _9      = 9,    // unused
    ARROW   = 10,   // ammo
    _11     = 11,   // in eA, delayed use (special script)
};

enum class BeingRemoveWhy : uint8_t
{
    // general disappearance
    GONE = 0,
    // only case handled specially in client
    DEAD = 1,
    QUIT = 2,
    WARPED = 3,
    // handled specially in clif_clearchar - sent as 0 over network
    DISGUISE = 9,

    // handled speciall in mob_warp - not actually sent over network
    NEGATIVE1 = 0xff,
};

enum class PickupFail : uint8_t
{
    OKAY        = 0,
    BAD_ITEM    = 1,
    TOO_HEAVY   = 2,
    TOO_FAR     = 3,
    INV_FULL    = 4,
    STACK_FULL  = 5,
    DROP_STEAL  = 6,
};

// this is used for both input and output
// different values are valid in 0x0089 vs 0x008a
enum class DamageType : uint8_t
{
    NORMAL      = 0x00,
    TAKEITEM    = 0x01,
    SIT         = 0x02,
    STAND       = 0x03,
    RETURNED    = 0x04,
    CONTINUOUS  = 0x07,
    DOUBLED     = 0x08,
    CRITICAL    = 0x0a,
    FLEE2       = 0x0b,
};

enum class LOOK : uint8_t
{
    BASE            = 0,
    HAIR            = 1,
    WEAPON          = 2,
    HEAD_BOTTOM     = 3,
    HEAD_TOP        = 4,
    HEAD_MID        = 5,
    HAIR_COLOR      = 6,
    CLOTHES_COLOR   = 7,
    SHIELD          = 8,
    SHOES           = 9,
    GLOVES          = 10,
    CAPE            = 11,
    MISC1           = 12,
    MISC2           = 13,

    COUNT,
};

// Note: there is also a typedef by this name in <dirent.h>
// but we should be fine since we never include it.
// (in the long term we should still rename this though)
enum class DIR : uint8_t
{
    S   = 0,
    SW  = 1,
    W   = 2,
    NW  = 3,
    N   = 4,
    NE  = 5,
    E   = 6,
    SE  = 7,

    COUNT,
};

constexpr
earray<int, DIR, DIR::COUNT> dirx //=
{{
    0, -1, -1, -1, 0, 1, 1, 1,
}}, diry //=
{{
    1, 1, 0, -1, -1, -1, 0, 1,
}};

constexpr
bool dir_is_diagonal(DIR d)
{
    return static_cast<uint8_t>(d) & 1;
}


enum class SP : uint16_t
{
    // sent to client
    SPEED                       = 0,

    // when used as "no stat"
    ZERO = 0,

    // sent to client
    BASEEXP                     = 1,
    // sent to client
    JOBEXP                      = 2,
#if 0
    KARMA                       = 3,
#endif

    // sent to client
    HP                          = 5,
    // sent to client
    MAXHP                       = 6,
    // sent to client
    SP                          = 7,
    // sent to client
    MAXSP                       = 8,
    // sent to client
    STATUSPOINT                 = 9,

    // sent to client
    BASELEVEL                   = 11,
    // sent to client
    SKILLPOINT                  = 12,
    // sent to client
    STR                         = 13,
    // sent to client
    AGI                         = 14,
    // sent to client
    VIT                         = 15,
    // sent to client
    INT                         = 16,
    // sent to client
    DEX                         = 17,
    // sent to client
    LUK                         = 18,
    CLASS                       = 19,
    // sent to client
    ZENY                        = 20,
    SEX                         = 21,
    // sent to client
    NEXTBASEEXP                 = 22,
    // sent to client
    NEXTJOBEXP                  = 23,
    // sent to client
    WEIGHT                      = 24,
    // sent to client
    MAXWEIGHT                   = 25,

    // sent to client
    USTR                        = 32,
    // sent to client
    UAGI                        = 33,
    // sent to client
    UVIT                        = 34,
    // sent to client
    UINT                        = 35,
    // sent to client
    UDEX                        = 36,
    // sent to client
    ULUK                        = 37,

    // sent to client
    ATK1                        = 41,
    // sent to client
    ATK2                        = 42,
    // sent to client
    MATK1                       = 43,
    // sent to client
    MATK2                       = 44,
    // sent to client
    DEF1                        = 45,
    // sent to client
    DEF2                        = 46,
    // sent to client
    MDEF1                       = 47,
    // sent to client
    MDEF2                       = 48,
    // sent to client
    HIT                         = 49,
    // sent to client
    FLEE1                       = 50,
    // sent to client
    FLEE2                       = 51,
    // sent to client
    CRITICAL                    = 52,
    // sent to client
    ASPD                        = 53,

    // sent to client
    JOBLEVEL                    = 55,

#if 0
    PARTNER                     = 57,
    CART                        = 58,
    FAME                        = 59,
    UNBREAKABLE                 = 60,
#endif

    DEAF                        = 70,

    // sent to client
    GM                          = 500,

    // sent to client
    ATTACKRANGE                 = 1000,
#if 0
    ATKELE                      = 1001,
#endif
#if 0
    DEFELE                      = 1002,
#endif
#if 0
    CASTRATE                    = 1003,
#endif
    MAXHPRATE                   = 1004,
#if 0
    MAXSPRATE                   = 1005,
#endif
#if 0
    SPRATE                      = 1006,
#endif

#if 0
    ADDEFF                      = 1012,
#endif
#if 0
    RESEFF                      = 1013,
#endif
    BASE_ATK                    = 1014,
    ASPD_RATE                   = 1015,
    HP_RECOV_RATE               = 1016,
#if 0
    SP_RECOV_RATE               = 1017,
#endif
#if 0
    SPEED_RATE                  = 1018,
#endif
    CRITICAL_DEF                = 1019,
#if 0
    NEAR_ATK_DEF                = 1020,
#endif
#if 0
    LONG_ATK_DEF                = 1021,
#endif
#if 0
    DOUBLE_RATE                 = 1022,
#endif
    DOUBLE_ADD_RATE             = 1023,
#if 0
    MATK                        = 1024,
#endif
#if 0
    MATK_RATE                   = 1025,
#endif
#if 0
    IGNORE_DEF_ELE              = 1026,
#endif
#if 0
    IGNORE_DEF_RACE             = 1027,
#endif
#if 0
    ATK_RATE                    = 1028,
#endif
    SPEED_ADDRATE               = 1029,
#if 0
    ASPD_ADDRATE                = 1030,
#endif
#if 0
    MAGIC_ATK_DEF               = 1031,
#endif
#if 0
    MISC_ATK_DEF                = 1032,
#endif
#if 0
    IGNORE_MDEF_ELE             = 1033,
#endif
#if 0
    IGNORE_MDEF_RACE            = 1034,
#endif

#if 0
    PERFECT_HIT_RATE            = 1038,
#endif
#if 0
    PERFECT_HIT_ADD_RATE        = 1039,
#endif
#if 0
    CRITICAL_RATE               = 1040,
#endif
#if 0
    GET_ZENY_NUM                = 1041,
#endif
#if 0
    ADD_GET_ZENY_NUM            = 1042,
#endif

#if 0
    ADD_MONSTER_DROP_ITEM       = 1047,
#endif
#if 0
    DEF_RATIO_ATK_ELE           = 1048,
#endif
#if 0
    DEF_RATIO_ATK_RACE          = 1049,
#endif
#if 0
    ADD_SPEED                   = 1050,
#endif
#if 0
    HIT_RATE                    = 1051,
#endif
#if 0
    FLEE_RATE                   = 1052,
#endif
#if 0
    FLEE2_RATE                  = 1053,
#endif
    DEF_RATE                    = 1054,
    DEF2_RATE                   = 1055,
#if 0
    MDEF_RATE                   = 1056,
#endif
#if 0
    MDEF2_RATE                  = 1057,
#endif
#if 0
    SPLASH_RANGE                = 1058,
#endif
#if 0
    SPLASH_ADD_RANGE            = 1059,
#endif

    HP_DRAIN_RATE               = 1061,
#if 0
    SP_DRAIN_RATE               = 1062,
#endif
#if 0
    SHORT_WEAPON_DAMAGE_RETURN  = 1063,
#endif
#if 0
    LONG_WEAPON_DAMAGE_RETURN   = 1064,
#endif

#if 0
    ADDEFF2                     = 1067,
#endif
    BREAK_WEAPON_RATE           = 1068,
    BREAK_ARMOR_RATE            = 1069,
    ADD_STEAL_RATE              = 1070,
    MAGIC_DAMAGE_RETURN         = 1071,
#if 0
    RANDOM_ATTACK_INCREASE      = 1072,
#endif
};

constexpr
SP attr_to_sp(ATTR attr)
{
    return static_cast<SP>(static_cast<uint16_t>(attr) + static_cast<uint16_t>(SP::STR));
}

constexpr
ATTR sp_to_attr(SP sp)
{
    return static_cast<ATTR>(static_cast<uint16_t>(sp) - static_cast<uint16_t>(SP::STR));
}

constexpr
SP attr_to_usp(ATTR attr)
{
    return static_cast<SP>(static_cast<uint16_t>(attr) + static_cast<uint16_t>(SP::USTR));
}

constexpr
ATTR usp_to_attr(SP sp)
{
    return static_cast<ATTR>(static_cast<uint16_t>(sp) - static_cast<uint16_t>(SP::USTR));
}

constexpr
SP sp_to_usp(SP sp)
{
    return attr_to_usp(sp_to_attr(sp));
}

constexpr
SP usp_to_sp(SP sp)
{
    return attr_to_sp(usp_to_attr(sp));
}


// xxxx xxxx  xxyy yyyy  yyyy dddd
struct NetPosition1
{
    Byte data[3];
};

struct Position1
{
    uint16_t x, y;
    DIR dir;
};

inline
bool native_to_network(NetPosition1 *network, Position1 native)
{
    uint16_t x = native.x;
    uint16_t y = native.y;
    uint8_t d = static_cast<uint8_t>(native.dir);

    uint8_t *p = reinterpret_cast<uint8_t *>(network);
    p[0] = x >> 2;
    p[1] = (x << 6) | ((y >> 4) & 0x3f);
    p[2] = y << 4 | d;

    return x < 1024 && y < 1024 && d < 16;
}

inline
bool network_to_native(Position1 *native, NetPosition1 network)
{
    const uint8_t *p = reinterpret_cast<const uint8_t *>(&network);
    native->x = (p[0] & (0x3ff >> 2)) << 2 | p[1] >> (8 - 2);
    native->y = (p[1] & (0x3ff >> 4)) << 4 | p[2] >> (8 - 4);
    uint8_t d = p[2] & 0x0f;
    native->dir = static_cast<DIR>(d);
    return d < 8;
}

// x0xx xxxx  xxy0 yyyy  yyyy x1xx  xxxx xxy1  yyyy yyyy
struct NetPosition2
{
    Byte data[5];
};

struct Position2
{
    uint16_t x0, y0;
    uint16_t x1, y1;
};

inline
bool native_to_network(NetPosition2 *network, Position2 native)
{
    uint16_t x0 = native.x0;
    uint16_t y0 = native.y0;
    uint16_t x1 = native.x1;
    uint16_t y1 = native.y1;

    uint8_t *p = reinterpret_cast<uint8_t *>(network);
    p[0] = x0 >> 2;
    p[1] = (x0 << 6) | ((y0 >> 4) & 0x3f);
    p[2] = (y0 << 4) | ((x1 >> 6) & 0x0f);
    p[3] = (x1 << 2) | ((y1 >> 8) & 0x03);
    p[4] = y1;

    return x0 < 1024 && y0 < 1024 && x1 < 1024 && y1 < 1024;
}

inline
bool network_to_native(Position2 *native, NetPosition2 network)
{
    const uint8_t *p = reinterpret_cast<const uint8_t *>(&network);
    native->x0 = (p[0] & (0x3ff >> 2)) << 2 | p[1] >> (8 - 2);
    native->y0 = (p[1] & (0x3ff >> 4)) << 4 | p[2] >> (8 - 4);
    native->x1 = (p[2] & (0x3ff >> 6)) << 6 | p[3] >> (8 - 6);
    native->y1 = (p[3] & (0x3ff >> 8)) << 8 | p[4] >> (8 - 8);
    return true;
}

struct IOff2;
struct SOff1;

struct IOff0
{
    uint16_t index;

    bool ok() const
    { return get0() < MAX_INVENTORY; }
    uint16_t get0() const
    { return index; }
    static IOff0 from(uint16_t i)
    { return IOff0{i}; }
    static IteratorPair<ValueIterator<IOff0>> iter()
    { return {IOff0::from(0), IOff0::from(MAX_INVENTORY)}; }
    friend uint16_t convert_for_printf(IOff0 i0) { return i0.index; }

    IOff0& operator ++() { ++index; return *this; }
    friend bool operator == (IOff0 l, IOff0 r) { return l.index == r.index; }
    friend bool operator != (IOff0 l, IOff0 r) { return !(l == r); }
    IOff2 shift() const;

    IOff0() : index(0) {}
private:
    explicit IOff0(uint16_t i) : index(i) {}
};

struct SOff0
{
    uint16_t index;

    bool ok() const
    { return get0() < MAX_STORAGE; }
    uint16_t get0() const
    { return index; }
    static SOff0 from(uint16_t i)
    { return SOff0{i}; }
    static IteratorPair<ValueIterator<SOff0>> iter()
    { return {SOff0::from(0), SOff0::from(MAX_STORAGE)}; }
    friend uint16_t convert_for_printf(SOff0 s0) { return s0.index; }

    SOff0& operator ++() { ++index; return *this; }
    friend bool operator == (SOff0 l, SOff0 r) { return l.index == r.index; }
    friend bool operator != (SOff0 l, SOff0 r) { return !(l == r); }
    SOff1 shift() const;

    SOff0() : index(0) {}
private:
    explicit SOff0(uint16_t i) : index(i) {}
};

struct IOff2
{
    uint16_t index;

    bool ok() const
    { return get2() < MAX_INVENTORY; }
    uint16_t get2() const
    { return index - 2; }
    static IOff2 from(uint16_t i)
    { return IOff2{static_cast<uint16_t>(i + 2)}; }
    static IteratorPair<ValueIterator<IOff2>> iter()
    { return {IOff2::from(0), IOff2::from(MAX_INVENTORY)}; }

    IOff2& operator ++() { ++index; return *this; }
    friend bool operator == (IOff2 l, IOff2 r) { return l.index == r.index; }
    friend bool operator != (IOff2 l, IOff2 r) { return !(l == r); }
    IOff0 unshift() const
    { return IOff0::from(get2()); }

    IOff2() : index(0) {}
private:
    explicit IOff2(uint16_t i) : index(i) {}
};

struct SOff1
{
    uint16_t index;

    bool ok() const
    { return get1() < MAX_STORAGE; }
    uint16_t get1() const
    { return index - 1; }
    static SOff1 from(uint16_t i)
    { return SOff1{static_cast<uint16_t>(i + 1)}; }
    static IteratorPair<ValueIterator<SOff1>> iter()
    { return {SOff1::from(0), SOff1::from(MAX_STORAGE)}; }

    SOff1& operator ++() { ++index; return *this; }
    friend bool operator == (SOff1 l, SOff1 r) { return l.index == r.index; }
    friend bool operator != (SOff1 l, SOff1 r) { return !(l == r); }
    SOff0 unshift() const
    { return SOff0::from(get1()); }

    SOff1() : index(0) {}
private:
    explicit SOff1(uint16_t i) : index(i) {}
};

inline IOff2 IOff0::shift() const
{ return IOff2::from(get0()); }
inline SOff1 SOff0::shift() const
{ return SOff1::from(get0()); }

inline
bool native_to_network(Little16 *network, IOff2 native)
{
    return native_to_network(network, native.index);
}

inline
bool network_to_native(IOff2 *native, Little16 network)
{
    return network_to_native(&native->index, network);
}

inline
bool native_to_network(Little16 *network, SOff1 native)
{
    return native_to_network(network, native.index);
}

inline
bool network_to_native(SOff1 *native, Little16 network)
{
    return network_to_native(&native->index, network);
}
} // namespace tmwa