Changeset 182

Show
Ignore:
Timestamp:
01/08/10 10:35:27 (8 months ago)
Author:
sausage
Message:

Happy new year,
Boss/child support,
Guilds,
Prevent negative heal with potion use,
Fix weight and heal pot overflow,
"Unregister" temporary vendor NPCs on destruction,
Collapse active NPC types for characters in to one pointer,
Add missing data on the end of the welcome reply,
Add admin/party icons to paperdoll,
Text width capping (fix buffer overflows),
Remove NPCs from view when they walk out of range (hacky)

Location:
eoserv/trunk
Files:
40 modified

Legend:

Unmodified
Added
Removed
  • eoserv/trunk/LICENSE.txt

    r116 r182  
    1 Copyright 2008-2009 the EOSERV development team (http://eoserv.net/devs) 
     1Copyright 2008-2010 the EOSERV development team (http://eoserv.net/devs) 
    22 
    33This software is provided 'as-is', without any express or implied 
  • eoserv/trunk/config.extra.ini

    r181 r182  
    1616# Cost to guild bank to recruit a new member 
    1717RecruitCost = 1000 
     18 
     19## GuildMinDeposit (number) 
     20# Minimum deposit allowed to the guild bank 
     21GuildMinDeposit = 1000 
     22 
     23## GuildMaxNameLength (number) 
     24# Maximum length of guild name 
     25GuildMaxNameLength = 24 
     26 
     27## GuildMaxDescLength (number) 
     28# Maximum length of guild description 
     29GuildMaxDescLength = 240 
     30 
     31## GuildMaxRankLength (number) 
     32# Maximum length of guild rank 
     33GuildMaxRankLength = 16 
     34 
     35## GuildMaxWidth (number) 
     36# Number of pixels to cap guild text to (stops client crashes) 
     37GuildMaxWidth = 190 
    1838 
    1939 
     
    97117DoorTimer = 3s 
    98118 
     119## ChatMaxWidth (number) 
     120# Number of pixels to cap chat text to (stops client crashes) 
     121ChatMaxWidth = 1500 
     122 
    99123 
    100124## ITEM LIMITS ## 
  • eoserv/trunk/config.ini

    r179 r182  
    215215 
    216216## GuildMaxMembers (number) 
    217 # Maximum number of members a guild can hold 
     217# Maximum number of members a guild can hold (less than 65k) 
    218218GuildMaxMembers = 5000 
     219 
     220## GuildCreateMembers (number) 
     221# Number of members NOT INCLUDING THE FOUNDER needed to make a new guild 
     222# A value of 0 will let guilds be created alone 
     223GuildCreateMembers = 9 
    219224 
    220225## GuildBankMax (number) 
    221226# Maximum amount of gold a guild bank can store (less than 2bil) 
    222 GuildBankMax = 10,000,000 
     227GuildBankMax = 2,000,000,000 
     228 
     229## GuildDefaultRanks (string[]) 
     230# Default rank list (9 strings) 
     231GuildDefaultRanks = Leader,Recruiter,,,,,,,New Member 
     232 
     233## GuildShowRecruiters (bool) 
     234# Show recruiters on the guild info page 
     235GuildShowRecruiters = true 
     236 
     237## GuildEditRank (number) 
     238# Rank required to edit a guild's description + rank names 
     239GuildEditRank = 1 
     240 
     241## GuildKickRank (number) 
     242# Rank required to kick members from the guild 
     243# Can only kick members below your level 
     244GuildKickRank = 1 
     245 
     246## GuildPromoteRank (number) 
     247# Rank required to promote members to any level below yourself 
     248# Founders can promote others to founder if GuildMultipleFounders is enabled 
     249GuildPromoteRank = 1 
     250 
     251## GuildDemoteRank (number) 
     252# Rank required to demote members ranked any level below yourself 
     253GuildDemoteRank = 1 
     254 
     255## GuildRecruitRank (number) 
     256# Rank required to recruit members in to the guild 
     257GuildRecruitRank = 2 
     258 
     259## GuildMultipleFounders (bool) 
     260# Allows a founder to promote other people to rank 0 
     261GuildMultipleFounders = yes 
     262 
     263## GuildAnnounce (bool) 
     264# Sends guild messages when members join/leave 
     265GuildAnnounce = yes 
     266 
     267## GuildDateFormat (string) 
     268# Date format to use for creation dates 
     269# http://www.cplusplus.com/reference/clibrary/ctime/strftime/ 
     270GuildDateFormat = %Y/%m/%d 
    223271 
    224272 
  • eoserv/trunk/src/character.cpp

    r181 r182  
    182182        this->party_trust_recv = 0; 
    183183 
    184         this->shop_npc = 0; 
    185         this->bank_npc = 0; 
    186         this->barber_npc = 0; 
     184        this->npc = 0; 
     185        this->npc_type = ENF::NPC; 
    187186        this->board = 0; 
    188187        this->jukebox_open = false; 
     188 
     189        this->last_guild_action = 0.0; 
    189190 
    190191        this->next_arena = 0; 
     
    212213 
    213214        this->player = 0; 
    214         this->guild = 0; 
    215         this->guild_tag = util::trim(static_cast<std::string>(row["guild"])); 
    216         this->guild_rank = static_cast<int>(row["guild_rank"]); 
     215        std::string guild_tag = util::trim(static_cast<std::string>(row["guild"])); 
     216 
     217        if (!guild_tag.empty()) 
     218        { 
     219                this->guild = this->world->guildmanager->GetGuild(guild_tag); 
     220                this->guild_rank = static_cast<int>(row["guild_rank"]); 
     221        } 
     222        else 
     223        { 
     224                this->guild = 0; 
     225                this->guild_rank = 0; 
     226        } 
     227 
    217228        this->party = 0; 
    218229        this->map = this->world->GetMap(0); 
     
    244255void Character::Msg(Character *from, std::string message) 
    245256{ 
    246         PacketBuilder builder; 
    247  
    248         builder.SetID(PACKET_TALK, PACKET_TELL); 
     257        message = util::text_cap(message, static_cast<int>(this->world->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->name) + "  ")); 
     258 
     259        PacketBuilder builder(PACKET_TALK, PACKET_TELL); 
    249260        builder.AddBreakString(from->name); 
    250261        builder.AddBreakString(message); 
     
    254265void Character::ServerMsg(std::string message) 
    255266{ 
    256         PacketBuilder builder; 
    257  
    258         builder.SetID(PACKET_TALK, PACKET_SERVER); 
     267        message = util::text_cap(message, static_cast<int>(this->world->config["ChatMaxWidth"]) - util::text_width("Server  ")); 
     268 
     269        PacketBuilder builder(PACKET_TALK, PACKET_SERVER); 
    259270        builder.AddString(message); 
    260271        this->player->client->SendBuilder(builder); 
     
    659670        this->sitting = SIT_STAND; 
    660671 
    661         this->shop_npc = 0; 
    662         this->bank_npc = 0; 
    663         this->barber_npc = 0; 
     672        this->npc = 0; 
     673        this->npc_type = ENF::NPC; 
    664674        this->board = 0; 
    665675        this->jukebox_open = false; 
     676        this->guild_join = ""; 
     677        this->guild_invite = ""; 
    666678 
    667679        this->warp_anim = animation; 
     
    852864        else 
    853865        { 
    854                 tag = this->guild_tag; 
     866                tag = this->guild ? this->guild->tag : ""; 
    855867        } 
    856868 
     
    897909        { 
    898910                this->weight += this->world->eif->Get(item->id)->weight * item->amount; 
     911 
     912                if (this->weight >= 250) 
     913                { 
     914                        break; 
     915                } 
    899916        } 
    900917 
     
    920937                } 
    921938        } 
     939 
     940        if (this->weight < 0 || this->weight > 250) 
     941        { 
     942                this->weight = 250; 
     943        } 
     944 
    922945        this->maxhp += 10 + calccon*3; 
    923946        this->maxtp += 10 + calcwis*3; 
     
    10731096        if (!this->online) 
    10741097        { 
     1098                if (this->guild) 
     1099                { 
     1100                        this->guild->Release(); 
     1101                        this->guild = 0; 
     1102                } 
     1103 
    10751104                return; 
    10761105        } 
     
    11191148        } 
    11201149 
     1150        this->online = false; 
     1151 
    11211152        this->Save(); 
    11221153 
    11231154        this->world->Logout(this); 
    1124  
    1125         this->online = false; 
    11261155} 
    11271156 
     
    11401169                this->str, this->intl, this->wis, this->agi, this->con, this->cha, this->statpoints, this->skillpoints, this->karma, this->sitting, 
    11411170                this->bankmax, this->goldbank, this->Usage(), ItemSerialize(this->inventory).c_str(), ItemSerialize(this->bank).c_str(), 
    1142                 DollSerialize(this->paperdoll).c_str(), "", this->guild_tag.c_str(), this->guild_rank, this->name.c_str()); 
     1171                DollSerialize(this->paperdoll).c_str(), "", (this->guild ? this->guild->tag.c_str() : ""), this->guild_rank, this->name.c_str()); 
    11431172} 
    11441173 
  • eoserv/trunk/src/character.hpp

    r181 r182  
    99 
    1010#include "stdafx.h" 
     11#include "eodata.hpp" 
    1112#include "guild.hpp" 
    1213#include "script.hpp" 
     
    110111                PartyRequestType party_send_type; 
    111112 
    112                 NPC *shop_npc; 
    113                 NPC *bank_npc; 
    114                 NPC *barber_npc; 
     113                NPC *npc; 
     114                ENF::Type npc_type; 
    115115                Board *board; 
    116116                bool jukebox_open; 
     117                std::string guild_join; 
     118                std::string guild_invite; 
     119 
     120                double last_guild_action; 
    117121 
    118122                WarpAnimation warp_anim; 
     
    186190                Player *player; 
    187191                Guild *guild; 
    188                 std::string guild_tag; 
    189192                unsigned char guild_rank; 
    190193                Party *party; 
     
    255258                SCRIPT_REGISTER_VARIABLE("Character @", party_trust_recv); 
    256259                SCRIPT_REGISTER_VARIABLE("PartyRequestType", party_send_type); 
    257                 SCRIPT_REGISTER_VARIABLE("NPC @", shop_npc); 
    258                 SCRIPT_REGISTER_VARIABLE("NPC @", bank_npc); 
    259                 SCRIPT_REGISTER_VARIABLE("NPC @", barber_npc); 
     260                SCRIPT_REGISTER_VARIABLE("NPC @", npc); 
     261                SCRIPT_REGISTER_VARIABLE("ENF_Type", npc_type); 
    260262                SCRIPT_REGISTER_VARIABLE("Board @", board); 
    261263                SCRIPT_REGISTER_VARIABLE("bool", jukebox_open); 
     264                SCRIPT_REGISTER_VARIABLE("string", guild_join); 
     265                SCRIPT_REGISTER_VARIABLE("string", guild_invite); 
     266                SCRIPT_REGISTER_VARIABLE("double", last_guild_action); 
    262267                SCRIPT_REGISTER_VARIABLE("WarpAnimation", warp_anim); 
    263268                SCRIPT_REGISTER_VARIABLE("PtrList<Character_Item>", inventory); 
     
    269274                SCRIPT_REGISTER_VARIABLE("Player @", player); 
    270275                SCRIPT_REGISTER_VARIABLE("Guild @", guild); 
    271                 SCRIPT_REGISTER_VARIABLE("string", guild_tag); 
    272276                SCRIPT_REGISTER_VARIABLE("uint8", guild_rank); 
    273277                SCRIPT_REGISTER_VARIABLE("Party @", party); 
  • eoserv/trunk/src/container/ptr_vector.hpp

    r171 r182  
    249249                void insert(FastIterator &it, value_type val) { ValueAddRef(val); data.insert(it.pos, val); } 
    250250 
    251                 reference operator [](size_type i) { return data[i]; } 
    252                 const_reference operator [](size_type i) const { throw const_cast<const value_type>(data[i]); } 
     251                reference operator [](size_type i) { return data.at(i); } 
     252                const_reference operator [](size_type i) const { throw const_cast<const value_type>(data.at(i)); } 
    253253                GenericPtrVector &operator =(const GenericPtrVector &other) { return assign(other); } 
    254254 
  • eoserv/trunk/src/eoclient.hpp

    r178 r182  
    5050                double next; 
    5151                void AddAction(PacketFamily family, PacketAction action, PacketReader reader, double time); 
    52                 void Execute(); 
    5352 
    5453                ActionQueue() : next(0) {}; 
     
    5958                SCRIPT_REGISTER_VARIABLE("double", next); 
    6059                SCRIPT_REGISTER_FUNCTION("void AddAction(PacketFamily family, PacketAction action, PacketReader reader, double time)", AddAction); 
    61                 SCRIPT_REGISTER_FUNCTION("void Execute()", Execute); 
    6260        SCRIPT_REGISTER_END() 
    6361}; 
  • eoserv/trunk/src/eoconst.hpp

    r175 r182  
    164164{ 
    165165        TALK_NOTFOUND = 1 
     166}; 
     167 
     168enum GuildReply UTIL_EXTEND_ENUM(short) 
     169{ 
     170        GUILD_BUSY = 1, 
     171        GUILD_NOT_APPROVED = 2, 
     172        GUILD_ALREADY_MEMBER = 3, 
     173        GUILD_NO_CANDIDATES = 4, 
     174        GUILD_EXISTS = 5, 
     175        GUILD_CREATE_BEGIN = 6, 
     176        GUILD_CREATE_ADD_CONFIRM = 7, 
     177        GUILD_CREATE_ADD = 8, 
     178        GUILD_RECRUITER_OFFLINE = 9, 
     179        GUILD_RECRUITER_NOT_HERE = 10, 
     180        GUILD_RECRUITER_WRONG_GUILD = 11, 
     181        GUILD_NOT_RECRUITER = 12, 
     182        GUILD_JOIN_REQUEST = 13, 
     183        GUILD_NOT_PRESENT = 14, 
     184        GUILD_ACCOUNT_LOW = 15, 
     185        GUILD_ACCEPTED = 16, 
     186        GUILD_NOT_FOUND = 17, 
     187        GUILD_UPDATED = 18, 
     188        GUILD_RANKS_UPDATED = 19, 
     189        GUILD_REMOVE_LEADER = 20, 
     190        GUILD_REMOVE_NOT_MEMBER = 21, 
     191        GUILD_REMOVED = 22, 
     192        GUILD_RANKING_LEADER = 23, 
     193        GUILD_RANKING_NOT_MEMBER = 24 
     194}; 
     195 
     196enum GuildInfoType UTIL_EXTEND_ENUM(short) 
     197{ 
     198        GUILD_INFO_DESCRIPTION = 1, 
     199        GUILD_INFO_RANKS = 2, 
     200        GUILD_INFO_BANK = 3 
    166201}; 
    167202 
     
    329364        SCRIPT_REGISTER_ENUM_END() 
    330365 
     366        SCRIPT_REGISTER_ENUM("GuildReply") 
     367                SCRIPT_REGISTER_ENUM_VALUE(GUILD_BUSY); 
     368                SCRIPT_REGISTER_ENUM_VALUE(GUILD_NOT_APPROVED); 
     369                SCRIPT_REGISTER_ENUM_VALUE(GUILD_ALREADY_MEMBER); 
     370                SCRIPT_REGISTER_ENUM_VALUE(GUILD_NO_CANDIDATES); 
     371                SCRIPT_REGISTER_ENUM_VALUE(GUILD_EXISTS); 
     372                SCRIPT_REGISTER_ENUM_VALUE(GUILD_CREATE_BEGIN); 
     373                SCRIPT_REGISTER_ENUM_VALUE(GUILD_CREATE_ADD_CONFIRM); 
     374                SCRIPT_REGISTER_ENUM_VALUE(GUILD_CREATE_ADD); 
     375                SCRIPT_REGISTER_ENUM_VALUE(GUILD_RECRUITER_OFFLINE); 
     376                SCRIPT_REGISTER_ENUM_VALUE(GUILD_RECRUITER_NOT_HERE); 
     377                SCRIPT_REGISTER_ENUM_VALUE(GUILD_RECRUITER_WRONG_GUILD); 
     378                SCRIPT_REGISTER_ENUM_VALUE(GUILD_NOT_RECRUITER); 
     379                SCRIPT_REGISTER_ENUM_VALUE(GUILD_JOIN_REQUEST); 
     380                SCRIPT_REGISTER_ENUM_VALUE(GUILD_NOT_PRESENT); 
     381                SCRIPT_REGISTER_ENUM_VALUE(GUILD_ACCOUNT_LOW); 
     382                SCRIPT_REGISTER_ENUM_VALUE(GUILD_ACCEPTED); 
     383                SCRIPT_REGISTER_ENUM_VALUE(GUILD_NOT_FOUND); 
     384                SCRIPT_REGISTER_ENUM_VALUE(GUILD_UPDATED); 
     385                SCRIPT_REGISTER_ENUM_VALUE(GUILD_RANKS_UPDATED); 
     386                SCRIPT_REGISTER_ENUM_VALUE(GUILD_REMOVE_LEADER); 
     387                SCRIPT_REGISTER_ENUM_VALUE(GUILD_REMOVE_NOT_MEMBER); 
     388                SCRIPT_REGISTER_ENUM_VALUE(GUILD_REMOVED); 
     389                SCRIPT_REGISTER_ENUM_VALUE(GUILD_RANKING_LEADER); 
     390                SCRIPT_REGISTER_ENUM_VALUE(GUILD_RANKING_NOT_MEMBER); 
     391        SCRIPT_REGISTER_ENUM_END() 
     392 
     393        SCRIPT_REGISTER_ENUM("GuildInfoType") 
     394                SCRIPT_REGISTER_ENUM_VALUE(GUILD_INFO_DESCRIPTION); 
     395                SCRIPT_REGISTER_ENUM_VALUE(GUILD_INFO_RANKS); 
     396                SCRIPT_REGISTER_ENUM_VALUE(GUILD_INFO_BANK); 
     397        SCRIPT_REGISTER_ENUM_END() 
     398 
    331399        SCRIPT_REGISTER_ENUM("SitAction") 
    332400                SCRIPT_REGISTER_ENUM_VALUE(SIT_STAND); 
  • eoserv/trunk/src/fwd/guild.hpp

    r168 r182  
    88#define FWD_GUILD_HPP_INCLUDED 
    99 
     10class Guild_Member; 
     11class Guild_Create; 
     12class GuildManager; 
    1013class Guild; 
    1114 
  • eoserv/trunk/src/guild.cpp

    r116 r182  
    66 
    77#include "guild.hpp" 
     8 
     9#include "character.hpp" 
     10#include "eoclient.hpp" 
     11#include "packet.hpp" 
     12#include "world.hpp" 
     13#include "player.hpp" 
     14 
     15std::string RankSerialize(util::array<std::string, 9> list) 
     16{ 
     17        std::string serialized; 
     18 
     19        UTIL_ARRAY_FOREACH_ALL(list, std::string, 9, rank) 
     20        { 
     21                serialized.append(rank); 
     22                serialized.append(","); 
     23        } 
     24 
     25        return serialized; 
     26} 
     27 
     28util::array<std::string, 9> RankUnserialize(std::string serialized) 
     29{ 
     30        util::array<std::string, 9> list; 
     31        std::size_t p = 0; 
     32        std::size_t lastp = std::numeric_limits<std::size_t>::max(); 
     33        int i = 0; 
     34 
     35        if (!serialized.empty() && *(serialized.end()-1) != ',') 
     36        { 
     37                serialized.push_back(','); 
     38        } 
     39 
     40        while ((p = serialized.find_first_of(',', p+1)) != std::string::npos) 
     41        { 
     42                list[i++] = serialized.substr(lastp+1, p-lastp-1); 
     43                lastp = p; 
     44        } 
     45 
     46        return list; 
     47} 
     48 
     49Guild_Create::Guild_Create(GuildManager *manager, std::string tag, std::string name, Character *leader) 
     50{ 
     51        tag = util::uppercase(tag); 
     52 
     53        this->manager = manager; 
     54        manager->AddRef(); 
     55        this->tag = tag; 
     56        this->name = name; 
     57        this->leader = leader; 
     58        leader->AddRef(); 
     59        Guild_Member *member = new Guild_Member(leader->name, 0); 
     60        this->members.push_back(member); 
     61        member->Release(); 
     62} 
     63 
     64bool Guild_Create::HasMember(std::string character) 
     65{ 
     66        character = util::lowercase(character); 
     67 
     68        UTIL_PTR_VECTOR_FOREACH(this->members, Guild_Member, check) 
     69        { 
     70                if (character == check->name) 
     71                { 
     72                        return true; 
     73                } 
     74        } 
     75 
     76        return false; 
     77} 
     78 
     79void Guild_Create::AddMember(std::string character) 
     80{ 
     81        character = util::lowercase(character); 
     82 
     83        Guild_Member *member = new Guild_Member(character, 9); 
     84        this->members.push_back(member); 
     85        member->Release(); 
     86} 
     87 
     88Guild_Create::~Guild_Create() 
     89{ 
     90        this->manager->CancelCreate(this); 
     91        this->leader->Release(); 
     92 
     93        if (!this->manager->cache_clearing) 
     94        { 
     95                std::map<std::string, Guild *>::iterator findentry = this->manager->cache.find(tag); 
     96 
     97                if (findentry != this->manager->cache.end()) 
     98                { 
     99                        findentry->second->Release(); 
     100                        this->manager->cache.erase(findentry); 
     101                } 
     102        } 
     103 
     104        this->manager->Release(); 
     105} 
     106 
     107Guild *GuildManager::GetGuild(std::string tag) 
     108{ 
     109        tag = util::uppercase(tag); 
     110 
     111        std::map<std::string, Guild *>::iterator findguild = this->cache.find(tag); 
     112 
     113        if (findguild != this->cache.end()) 
     114        { 
     115                findguild->second->AddRef(); 
     116                return findguild->second; 
     117        } 
     118        else 
     119        { 
     120                Database_Result res = this->world->db.Query("SELECT `tag`, `name`, `description`, `created`, `ranks`, `bank` FROM `guilds` WHERE `tag` = '$'", tag.c_str()); 
     121 
     122                if (res.empty()) 
     123                { 
     124                        return 0; 
     125                } 
     126 
     127                std::map<std::string, util::variant> row = res.front(); 
     128                Guild *guild = new Guild(this); 
     129                guild->tag = static_cast<std::string>(row["tag"]); 
     130                guild->name = static_cast<std::string>(row["name"]); 
     131                guild->description = static_cast<std::string>(row["description"]); 
     132                guild->created = static_cast<int>(row["created"]); 
     133                guild->ranks = RankUnserialize(static_cast<std::string>(row["ranks"])); 
     134                guild->bank = static_cast<int>(row["bank"]); 
     135 
     136                res = this->world->db.Query("SELECT `name`, `guild_rank` FROM `characters` WHERE `guild` = '$' ORDER BY `guild_rank` ASC, `name` ASC", tag.c_str()); 
     137 
     138                typedef std::map<std::string, util::variant> Database_Row; 
     139                UTIL_VECTOR_FOREACH_ALL(res, Database_Row, row) 
     140                { 
     141                        Guild_Member *member = new Guild_Member(row["name"], row["guild_rank"]); 
     142                        guild->members.push_back(member); 
     143                        member->Release(); 
     144                } 
     145 
     146                return this->cache[tag] = guild; 
     147        } 
     148} 
     149 
     150Guild *GuildManager::GetGuildName(std::string name) 
     151{ 
     152        name = util::lowercase(name); 
     153 
     154        UTIL_MAP_IFOREACH_ALL(this->cache, std::string, Guild *, entry) 
     155        { 
     156                if (entry->second->name == name) 
     157                { 
     158                        entry->second->AddRef(); 
     159                        return entry->second; 
     160                } 
     161        } 
     162 
     163        Database_Result res = this->world->db.Query("SELECT `tag`, `name`, `description`, `created`, `ranks`, `bank` FROM `guilds` WHERE `name` = '$'", name.c_str()); 
     164 
     165        if (res.empty()) 
     166        { 
     167                return 0; 
     168        } 
     169 
     170        std::map<std::string, util::variant> row = res.front(); 
     171        Guild *guild = new Guild(this); 
     172        guild->tag = static_cast<std::string>(row["tag"]); 
     173        guild->name = static_cast<std::string>(row["name"]); 
     174        guild->description = static_cast<std::string>(row["description"]); 
     175        guild->created = static_cast<int>(row["created"]); 
     176        guild->ranks = RankUnserialize(static_cast<std::string>(row["ranks"])); 
     177        guild->bank = static_cast<int>(row["bank"]); 
     178 
     179        res = this->world->db.Query("SELECT `name`, `guild_rank` FROM `characters` WHERE `guild` = '$' ORDER BY `guild_rank` ASC, `name` ASC", static_cast<std::string>(row["tag"]).c_str()); 
     180 
     181        typedef std::map<std::string, util::variant> Database_Row; 
     182        UTIL_VECTOR_FOREACH_ALL(res, Database_Row, row) 
     183        { 
     184                Guild_Member *member = new Guild_Member(row["name"], row["guild_rank"]); 
     185                guild->members.push_back(member); 
     186                member->Release(); 
     187        } 
     188 
     189        return this->cache[row["tag"]] = guild; 
     190} 
     191 
     192Guild_Create *GuildManager::GetCreate(std::string tag) 
     193{ 
     194        tag = util::uppercase(tag); 
     195 
     196        std::map<std::string, Guild_Create *>::iterator findcreate = this->create_cache.find(tag); 
     197 
     198        if (findcreate != this->create_cache.end()) 
     199        { 
     200                findcreate->second->AddRef(); 
     201                return findcreate->second; 
     202        } 
     203        else 
     204        { 
     205                return 0; 
     206        } 
     207} 
     208 
     209Guild_Create *GuildManager::BeginCreate(std::string tag, std::string name, Character *leader) 
     210{ 
     211        tag = util::uppercase(tag); 
     212        name = util::lowercase(name); 
     213 
     214        Guild_Create *create = new Guild_Create(this, tag, name, leader); 
     215        this->create_cache[tag] = create; 
     216        create->AddRef(); 
     217        return create; 
     218} 
     219 
     220void GuildManager::CancelCreate(Guild_Create *create) 
     221{ 
     222        this->create_cache.erase(create->tag); 
     223        create->Release(); 
     224} 
     225 
     226Guild *GuildManager::CreateGuild(Guild_Create *create, std::string description) 
     227{ 
     228        PtrVector<Guild_Member> members; 
     229 
     230        description = util::text_word_wrap(description, this->world->config["GuildMaxWidth"]); 
     231 
     232        this->world->db.Query("INSERT INTO `guilds` (`tag`, `name`, `description`, `created`, `ranks`) VALUES ('$', '$', '$', #, '$')", create->tag.c_str(), create->name.c_str(), description.c_str(), time(0), static_cast<std::string>(this->world->config["GuildDefaultRanks"]).c_str()); 
     233 
     234        this->create_cache.erase(create->tag); 
     235 
     236        Guild *guild = this->GetGuild(create->tag); 
     237 
     238        UTIL_PTR_VECTOR_FOREACH(create->members, Guild_Member, member) 
     239        { 
     240                Character *character = this->world->GetCharacter(member->name); 
     241 
     242                if (character) 
     243                { 
     244                        guild->AddMember(character, create->leader, false, (character == create->leader) ? 0 : 9); 
     245                } 
     246        } 
     247 
     248        this->create_cache.erase(create->tag); 
     249 
     250        return guild; 
     251} 
     252 
     253void GuildManager::SaveAll() 
     254{ 
     255        UTIL_MAP_IFOREACH_ALL(this->cache, std::string, Guild *, entry) 
     256        { 
     257                entry->second->Save(); 
     258        } 
     259} 
     260 
     261GuildManager::~GuildManager() 
     262{ 
     263        this->cache_clearing = true; 
     264 
     265        UTIL_MAP_IFOREACH_ALL(this->create_cache, std::string, Guild_Create *, entry) 
     266        { 
     267                entry->second->Release(); 
     268        } 
     269 
     270        UTIL_MAP_IFOREACH_ALL(this->cache, std::string, Guild *, entry) 
     271        { 
     272                entry->second->Release(); 
     273        } 
     274 
     275        this->world->Release(); 
     276} 
     277 
     278bool Guild::ValidName(std::string name) 
     279{ 
     280        name = util::lowercase(name); 
     281 
     282        if (name.length() < 4) 
     283        { 
     284                return false; 
     285        } 
     286 
     287        for (std::size_t i = 0; i < name.length(); ++i) 
     288        { 
     289                if ((name[i] < 'a' || name[i] > 'z') && name[i] != ' ') 
     290                { 
     291                        return false; 
     292                } 
     293        } 
     294 
     295        return true; 
     296} 
     297 
     298bool Guild::ValidTag(std::string tag) 
     299{ 
     300        tag = util::uppercase(tag); 
     301 
     302        if (tag.length() < 2 || tag.length() > 3) 
     303        { 
     304                return false; 
     305        } 
     306 
     307        for (std::size_t i = 0; i < tag.length(); ++i) 
     308        { 
     309                if (tag[i] < 'A' || tag[i] > 'Z') 
     310                { 
     311                        return false; 
     312                } 
     313        } 
     314 
     315        return true; 
     316} 
     317 
     318void Guild::AddMember(Character *joined, Character *recruiter, bool alert, int rank) 
     319{ 
     320        joined->guild = this; 
     321        this->AddRef(); 
     322        joined->guild_rank = rank; 
     323 
     324        Guild_Member *member = new Guild_Member(joined->name, rank); 
     325        this->members.push_back(member); 
     326        member->Release(); 
     327 
     328        if (recruiter != joined) // Leader of new guild 
     329        { 
     330                PacketBuilder builder(PACKET_GUILD, PACKET_AGREE); 
     331                builder.AddShort(recruiter->player->id); 
     332                builder.AddByte(255); 
     333                builder.AddBreakString(this->tag); 
     334                builder.AddBreakString(this->name); 
     335                builder.AddBreakString(this->GetRank(rank)); 
     336                joined->player->client->SendBuilder(builder); 
     337        } 
     338 
     339        if (alert && this->manager->world->config["GuildAnnounce"]) 
     340        { 
     341                std::string name = joined->name; 
     342 
     343                std::string msg = "***  "; 
     344                msg += util::ucfirst(name); 
     345                msg += " has joined the guild."; 
     346 
     347                if (recruiter) 
     348                { 
     349                        msg += " Recruited by "; 
     350                        msg += util::ucfirst(recruiter->name); 
     351                } 
     352 
     353                this->Msg(0, msg); 
     354        } 
     355} 
     356 
     357void Guild::DelMember(std::string kicked, Character *kicker, bool alert) 
     358{ 
     359        kicked = util::lowercase(kicked); 
     360 
     361        if (alert && this->manager->world->config["GuildAnnounce"]) 
     362        { 
     363                std::string msg = "***  "; 
     364                msg += util::ucfirst(kicked); 
     365                msg += " left the guild."; 
     366 
     367                if (kicker) 
     368                { 
     369                        msg += " Kicked by "; 
     370                        msg += util::ucfirst(kicker->name); 
     371                } 
     372 
     373                this->Msg(0, msg); 
     374        } 
     375 
     376        UTIL_PTR_VECTOR_FOREACH(this->manager->world->characters, Character, character) 
     377        { 
     378                if (character->name == kicked) 
     379                { 
     380                        character->guild->Release(); 
     381                        character->guild = 0; 
     382                        character->guild_rank = 0; 
     383                } 
     384        } 
     385 
     386        UTIL_PTR_VECTOR_FOREACH(this->members, Guild_Member, member) 
     387        { 
     388                if (member->name == kicked) 
     389                { 
     390                        this->members.erase(member); 
     391                        break; 
     392                } 
     393        } 
     394} 
     395 
     396void Guild::SetMemberRank(std::string name, int rank) 
     397{ 
     398        Guild_Member *member = GetMember(name); 
     399 
     400        if (member) 
     401        { 
     402                member->rank = rank; 
     403 
     404                UTIL_PTR_VECTOR_FOREACH(this->manager->world->characters, Character, character) 
     405                { 
     406                        if (character->name == name) 
     407                        { 
     408                                character->guild_rank = rank; 
     409                        } 
     410                } 
     411        } 
     412} 
     413 
     414void Guild::AddBank(int gold) 
     415{ 
     416        if (gold > 0 && this->bank + gold >= 0) 
     417        { 
     418                this->needs_save = true; 
     419                this->bank += gold; 
     420                this->bank = std::min<int>(this->bank, this->manager->world->config["GuildBankMax"]); 
     421        } 
     422} 
     423 
     424void Guild::DelBank(int gold) 
     425{ 
     426        if (gold > 0 && this->bank >= 0 && this->bank - gold > 0) 
     427        { 
     428                this->needs_save = true; 
     429                this->bank -= gold; 
     430        } 
     431} 
     432 
     433Guild_Member *Guild::GetMember(std::string name) 
     434{ 
     435        name = util::lowercase(name); 
     436 
     437        UTIL_PTR_VECTOR_FOREACH(this->members, Guild_Member, member) 
     438        { 
     439                if (member->name == name) 
     440                { 
     441                        return *member; 
     442                } 
     443        } 
     444 
     445        return 0; 
     446} 
     447 
     448void Guild::SetDescription(std::string description) 
     449{ 
     450        this->needs_save = true; 
     451 
     452        for (std::string::iterator i = description.begin(); i != description.end(); ++i) 
     453        { 
     454                if (static_cast<unsigned char>(*i) == 0xFF) 
     455                { 
     456                        *i = 'y'; 
     457                } 
     458        } 
     459 
     460        this->description = util::text_word_wrap(description, this->manager->world->config["GuildMaxWidth"]); 
     461} 
     462 
     463void Guild::Msg(Character *from, std::string message, bool echo) 
     464{ 
     465        message = util::text_cap(message, static_cast<int>(this->manager->world->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from ? from->name : "Server") + "  ")); 
     466 
     467        PacketBuilder builder(PACKET_TALK, PACKET_REQUEST); 
     468        builder.AddBreakString(from ? from->name : "Server"); 
     469        builder.AddBreakString(message); 
     470 
     471        UTIL_PTR_VECTOR_FOREACH(this->manager->world->characters, Character, character) 
     472        { 
     473                if (!echo && *character == from) 
     474                { 
     475                        continue; 
     476                } 
     477 
     478                if (character->guild == this) 
     479                { 
     480                        character->player->client->SendBuilder(builder); 
     481                } 
     482        } 
     483} 
     484 
     485void Guild::Save() 
     486{ 
     487        if (this->needs_save) 
     488        { 
     489                this->manager->world->db.Query("UPDATE `guilds` SET `description` = '$', `ranks` = '$', `bank` = # WHERE tag = '$'", this->description.c_str(), RankSerialize(this->ranks).c_str(), this->bank, this->tag.c_str()); 
     490                this->needs_save = false; 
     491        } 
     492} 
     493 
     494Guild::~Guild() 
     495{ 
     496        if (!this->manager->cache_clearing) 
     497        { 
     498                std::map<std::string, Guild *>::iterator findentry = this->manager->cache.find(tag); 
     499 
     500                if (findentry != this->manager->cache.end()) 
     501                { 
     502                        findentry->second->Release(); 
     503                        this->manager->cache.erase(findentry); 
     504                } 
     505        } 
     506 
     507        this->manager->Release(); 
     508} 
  • eoserv/trunk/src/guild.hpp

    r175 r182  
    1010#include "stdafx.h" 
    1111 
     12#include "world.hpp" 
     13 
     14/** 
     15 * Serialize an array of 9 ranks in to a string that can be restored with RankUnserialize 
     16 */ 
     17std::string RankSerialize(util::array<std::string, 9> list); 
     18 
     19/** 
     20 * Convert a string generated by RankSerialze back to a list of 9 ranks 
     21 */ 
     22util::array<std::string, 9> RankUnserialize(std::string serialized); 
     23 
     24/** 
     25 * Represents a member in a guild 
     26 */ 
     27class Guild_Member : public Shared 
     28{ 
     29        public: 
     30                std::string name; 
     31                int rank; 
     32 
     33                Guild_Member(std::string name_, int rank_ = 9) : name(name_), rank(rank_) { } 
     34 
     35        static Guild_Member *ScriptFactory(std::string name, int rank) { return new Guild_Member(name, rank); } 
     36 
     37        SCRIPT_REGISTER_REF(Guild_Member) 
     38                SCRIPT_REGISTER_FACTORY("Guild_Member @f(string name, int rank)", ScriptFactory); 
     39 
     40                SCRIPT_REGISTER_VARIABLE("string", name); 
     41                SCRIPT_REGISTER_VARIABLE("int", rank); 
     42        SCRIPT_REGISTER_END() 
     43}; 
     44 
     45/** 
     46 * Temporary structure used when creating a new guild 
     47 */ 
     48class Guild_Create : public Shared 
     49{ 
     50        public: 
     51                int id; 
     52                GuildManager *manager; 
     53                Character *leader; 
     54                std::string tag; 
     55                std::string name; 
     56                PtrVector<Guild_Member> members; 
     57 
     58                Guild_Create(GuildManager *manager, std::string tag, std::string name, Character *leader); 
     59 
     60                bool HasMember(std::string character); 
     61                void AddMember(std::string character); 
     62 
     63                ~Guild_Create(); 
     64 
     65        static Guild_Create *ScriptFactory(GuildManager *manager, std::string tag, std::string name, Character *leader) { return new Guild_Create(manager, tag, name, leader); } 
     66 
     67        SCRIPT_REGISTER_REF(Guild_Create) 
     68                SCRIPT_REGISTER_FACTORY("Guild_Create @f(GuildManager @manager, string tag, string name, Character @leader)", ScriptFactory); 
     69 
     70                SCRIPT_REGISTER_VARIABLE("GuildManager @", manager); 
     71                SCRIPT_REGISTER_VARIABLE("Character @", leader); 
     72                SCRIPT_REGISTER_VARIABLE("string", tag); 
     73                SCRIPT_REGISTER_VARIABLE("string", name); 
     74                SCRIPT_REGISTER_VARIABLE("PtrVector<Guild_Member>", members); 
     75        SCRIPT_REGISTER_END() 
     76}; 
     77 
     78/** 
     79 * Manages when to load and save guild data 
     80 */ 
     81class GuildManager : public Shared 
     82{ 
     83        public: 
     84                bool cache_clearing; 
     85                std::map<std::string, Guild *> cache; 
     86                std::map<std::string, Guild_Create *> create_cache; 
     87                World *world; 
     88 
     89                GuildManager(World *world_) : cache_clearing(false), world(world_) { world->AddRef(); } 
     90 
     91                Guild *GetGuild(std::string tag); 
     92                Guild *GetGuildName(std::string name); 
     93                Guild_Create *GetCreate(std::string tag); 
     94                Guild_Create *BeginCreate(std::string tag, std::string name, Character *leader); 
     95                void CancelCreate(Guild_Create *); 
     96                Guild *CreateGuild(Guild_Create *, std::string description); 
     97 
     98                void SaveAll(); 
     99 
     100                ~GuildManager(); 
     101 
     102        static GuildManager *ScriptFactory(World *world) { return new GuildManager(world); } 
     103 
     104        SCRIPT_REGISTER_REF(GuildManager) 
     105                SCRIPT_REGISTER_FACTORY("GuildManager @f(World @world)", ScriptFactory); 
     106 
     107                SCRIPT_REGISTER_VARIABLE("World @", world); 
     108                SCRIPT_REGISTER_FUNCTION("Guild @GetGuild(string tag)", GetGuild); 
     109                SCRIPT_REGISTER_FUNCTION("Guild @GetGuildName(string tag)", GetGuildName); 
     110                SCRIPT_REGISTER_FUNCTION("Guild_Create @GetCreate(string tag)", GetCreate); 
     111                SCRIPT_REGISTER_FUNCTION("Guild_Create @BeginCreate(string tag, string name, Character @leader)", BeginCreate); 
     112                SCRIPT_REGISTER_FUNCTION("void CancelCreate(Guild_Create @)", CancelCreate); 
     113                SCRIPT_REGISTER_FUNCTION("Guild @CreateGuild(string tag, string description)", CreateGuild); 
     114                SCRIPT_REGISTER_FUNCTION("void SaveAll()", SaveAll); 
     115        SCRIPT_REGISTER_END() 
     116}; 
     117 
    12118/** 
    13119 * Stores guild information and references to online members 
     
    17123{ 
    18124        public: 
     125                GuildManager *manager; 
    19126                std::string tag; 
    20127                std::string name; 
    21                 PtrVector<Character> members; 
     128                PtrVector<Guild_Member> members; 
    22129                util::array<std::string, 9> ranks; 
    23130                std::time_t created; 
     131                std::string description; 
     132                int bank; 
     133                bool needs_save; 
    24134 
    25                 void Msg(PtrVector<Character> from, std::string message); 
     135                Guild(GuildManager *manager_) : manager(manager_), created(0), bank(0), needs_save(false) { manager->AddRef(); } 
    26136 
    27         SCRIPT_REGISTER_REF_DF(Guild) 
     137                static bool ValidName(std::string name); 
     138                static bool ValidTag(std::string tag); 
     139 
     140                void AddMember(Character *joined, Character *recruiter, bool alert = false, int rank = 9); 
     141                void DelMember(std::string kicked, Character *kicker = 0, bool alert = false); 
     142 
     143                std::string GetRank(int rankno) { return ranks[std::max(0, rankno - 1)]; } 
     144                void SetRank(int rankno, std::string rank) { ranks[std::max(0, rankno - 1)] = rank; } 
     145                void SetMemberRank(std::string name, int rank); 
     146 
     147                void AddBank(int gold); 
     148                void DelBank(int gold); 
     149 
     150                Guild_Member *GetMember(std::string name); 
     151 
     152                void SetDescription(std::string); 
     153 
     154                void Msg(Character *from, std::string message, bool echo = true); 
     155 
     156                void Save(); 
     157 
     158                ~Guild(); 
     159 
     160        static Guild *ScriptFactory(GuildManager *manager) { return new Guild(manager); } 
     161 
     162        SCRIPT_REGISTER_REF(Guild) 
     163                SCRIPT_REGISTER_FACTORY("Guild @f(GuildManager @manager)", ScriptFactory); 
     164 
     165                SCRIPT_REGISTER_VARIABLE("GuildManager @", manager); 
    28166                SCRIPT_REGISTER_VARIABLE("string", tag); 
    29167                SCRIPT_REGISTER_VARIABLE("string", name); 
    30                 SCRIPT_REGISTER_VARIABLE("PtrVector<Character>", members); 
     168                SCRIPT_REGISTER_VARIABLE("PtrVector<Guild_Member>", members); 
    31169                SCRIPT_REGISTER_VARIABLE("uint", created); 
    32  
    33                 //SCRIPT_REGISTER_FUNCTION("void Msg(PtrVector<Character> from, string message)", Msg); 
     170                SCRIPT_REGISTER_VARIABLE("string", description); 
     171                SCRIPT_REGISTER_VARIABLE("int", bank); 
     172                SCRIPT_REGISTER_VARIABLE("bool", needs_save); 
     173                SCRIPT_REGISTER_FUNCTION("void AddMember(Character @joined, Character @recruiter, bool alert, int rank)", AddMember); 
     174                SCRIPT_REGISTER_FUNCTION("void DelMember(string kicked, Character @kicker, bool alert)", DelMember); 
     175                SCRIPT_REGISTER_FUNCTION("string GetRank(int rankno)", GetRank); 
     176                SCRIPT_REGISTER_FUNCTION("void SetRank(int rankno, string rank)", SetRank); 
     177                SCRIPT_REGISTER_FUNCTION("void SetMemberRank(string name, int rank)", SetMemberRank); 
     178                SCRIPT_REGISTER_FUNCTION("void AddBank(int gold)", AddBank); 
     179                SCRIPT_REGISTER_FUNCTION("void DelBank(int gold)", DelBank); 
     180                SCRIPT_REGISTER_FUNCTION("Guild_Member @GetMember(string name)", GetMember); 
     181                SCRIPT_REGISTER_FUNCTION("void SetDescription(string)", SetDescription); 
     182                SCRIPT_REGISTER_FUNCTION("void Msg(Character @from, string message, bool echo)", Msg); 
     183                SCRIPT_REGISTER_FUNCTION("void Save()", Save); 
    34184        SCRIPT_REGISTER_END() 
    35185}; 
  • eoserv/trunk/src/handlers/Attack.cpp

    r177 r182  
    66 
    77#include "handlers.h" 
     8 
     9#include "map.hpp" 
    810 
    911CLIENT_F_FUNC(Attack) 
     
    2628                        } 
    2729 
    28                         if (direction >= 0 && direction <= 3) 
     30                        if (direction != this->player->character->direction) 
    2931                        { 
    30                                 this->player->character->Attack(direction); 
     32                                if (direction >= 0 && direction <= 3) 
     33                                { 
     34                                        this->player->character->map->Face(this->player->character, direction); 
     35                                        CLIENT_FORCE_QUEUE_ACTION(0.67) 
     36                                } 
     37                                else 
     38                                { 
     39                                        return false; 
     40                                } 
    3141                        } 
     42 
     43                        this->player->character->Attack(direction); 
    3244                } 
    3345                break; 
  • eoserv/trunk/src/handlers/Bank.cpp

    r178 r182  
    2828                                if (npc->index == id && npc->Data()->type == ENF::Bank) 
    2929                                { 
    30                                         this->player->character->bank_npc = *npc; 
     30                                        this->player->character->npc = *npc; 
     31                                        this->player->character->npc_type = ENF::Bank; 
    3132 
    3233                                        reply.SetID(PACKET_BANK, PACKET_OPEN); 
     
    5455                        amount = std::min(amount, this->player->character->HasItem(1)); 
    5556 
    56                         if (this->player->character->bank_npc) 
     57                        if (this->player->character->npc_type == ENF::Bank) 
    5758                        { 
    5859                                int newgold = this->player->character->goldbank + amount; 
     
    8283                        if (amount <= 0) return true; 
    8384 
    84                         if (this->player->character->bank_npc) 
     85                        if (this->player->character->npc_type == ENF::Bank) 
    8586                        { 
    8687                                int newgold = this->player->character->goldbank - amount; 
  • eoserv/trunk/src/handlers/Barber.cpp

    r178 r182  
    2828                                if (npc->index == id && npc->Data()->type == ENF::Barber) 
    2929                                { 
    30                                         this->player->character->barber_npc = *npc; 
     30                                        this->player->character->npc = *npc; 
     31                                        this->player->character->npc_type = ENF::Barber; 
    3132 
    3233                                        reply.SetID(PACKET_BARBER, PACKET_OPEN); 
     
    6364                        } 
    6465 
    65                         if (this->player->character->barber_npc) 
     66                        if (this->player->character->npc_type == ENF::Barber) 
    6667                        { 
    6768                                this->player->character->DelItem(1, price); 
  • eoserv/trunk/src/handlers/Face.cpp

    r168 r182  
    1818                { 
    1919                        if (this->state < EOClient::Playing) return false; 
    20                         CLIENT_QUEUE_ACTION(0.0) 
     20                        CLIENT_QUEUE_ACTION(0.09) 
    2121 
    2222                        Direction direction = static_cast<Direction>(reader.GetChar()); 
  • eoserv/trunk/src/handlers/Guild.cpp

    r168 r182  
    77#include "handlers.h" 
    88 
     9#include "eodata.hpp" 
     10#include "guild.hpp" 
     11#include "map.hpp" 
     12#include "npc.hpp" 
     13 
    914CLIENT_F_FUNC(Guild) 
    1015{ 
    1116        PacketBuilder reply; 
    1217 
     18        double now = Timer::GetTime(); 
     19 
     20        if (this->player && this->player->character) 
     21        { 
     22                if (int(this->player->character->last_guild_action * 2) == int(now * 2)) 
     23                { 
     24                        CLIENT_FORCE_QUEUE_ACTION(0.5) 
     25                } 
     26 
     27                this->player->character->last_guild_action = now; 
     28        } 
     29 
    1330        switch (action) 
    1431        { 
     32                case PACKET_REQUEST: // Requested to create a guild 
     33                { 
     34                        if (this->state < EOClient::Playing) return false; 
     35 
     36                        /*int session = */reader.GetInt(); 
     37                        reader.GetByte(); 
     38                        std::string tag = reader.GetBreakString(); 
     39                        std::string name = reader.GetBreakString(); 
     40 
     41                        if (this->player->character->npc_type == ENF::Guild) 
     42                        { 
     43                                if (!this->player->character->guild) 
     44                                { 
     45                                        Guild *guild = this->server->world->guildmanager->GetGuild(tag); 
     46 
     47                                        if (!guild) 
     48                                        { 
     49                                                guild = this->server->world->guildmanager->GetGuildName(name); 
     50                                        } 
     51 
     52                                        if (!guild) 
     53                                        { 
     54                                                if (Guild::ValidTag(tag) && Guild::ValidName(name)) 
     55                                                { 
     56                                                        if (this->player->character->HasItem(1) >= static_cast<int>(this->server->world->config["GuildPrice"])) 
     57                                                        { 
     58                                                                Guild_Create *create = this->server->world->guildmanager->BeginCreate(tag, name, this->player->character); 
     59 
     60                                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     61                                                                reply.AddChar(GUILD_CREATE_BEGIN); 
     62                                                                CLIENT_SEND(reply); 
     63 
     64                                                                PacketBuilder builder(PACKET_GUILD, PACKET_REQUEST); 
     65                                                                builder.AddShort(create->leader->player->id); 
     66                                                                builder.AddString(util::ucfirst(util::lowercase(name)) + " (" + util::uppercase(tag) + ")"); 
     67 
     68                                                                UTIL_PTR_LIST_FOREACH(this->player->character->map->characters, Character, character) 
     69                                                                { 
     70                                                                        if (*character != this->player->character && !character->guild) 
     71                                                                        { 
     72                                                                                character->guild_invite = tag; 
     73                                                                                character->player->client->SendBuilder(builder); 
     74                                                                        } 
     75                                                                } 
     76 
     77                                                                create->Release(); 
     78                                                        } 
     79                                                } 
     80                                                else 
     81                                                { 
     82                                                        reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     83                                                        reply.AddChar(GUILD_NOT_APPROVED); 
     84                                                        CLIENT_SEND(reply); 
     85                                                } 
     86                                        } 
     87                                        else 
     88                                        { 
     89                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     90                                                reply.AddChar(GUILD_EXISTS); 
     91                                                CLIENT_SEND(reply); 
     92                                                guild->Release(); 
     93                                        } 
     94                                } 
     95                        } 
     96                } 
     97                break; 
     98 
     99                case PACKET_ACCEPT: // Accept guild create invite 
     100                { 
     101                        if (this->state < EOClient::Playing) return false; 
     102 
     103                        if (!this->player->character->guild_invite.empty()) 
     104                        { 
     105                                Guild_Create *create = this->server->world->guildmanager->GetCreate(this->player->character->guild_invite); 
     106 
     107                                if (create) 
     108                                { 
     109                                        create->AddMember(this->player->character->name); 
     110 
     111                                        PacketBuilder builder(PACKET_GUILD, PACKET_REPLY); 
     112 
     113                                        if (create->members.size() == static_cast<std::size_t>(static_cast<int>(this->server->world->config["GuildCreateMembers"]))) 
     114                                        { 
     115                                                builder.AddShort(GUILD_CREATE_ADD_CONFIRM); 
     116                                        } 
     117                                        else 
     118                                        { 
     119                                                builder.AddShort(GUILD_CREATE_ADD); 
     120                                        } 
     121 
     122                                        builder.AddString(this->player->character->name); 
     123                                        create->leader->player->client->SendBuilder(builder); 
     124 
     125                                        create->Release(); 
     126                                } 
     127 
     128                                this->player->character->guild_invite = ""; 
     129                        } 
     130                } 
     131                break; 
     132 
     133                case PACKET_REMOVE: // Left the guild 
     134                { 
     135                        if (this->state < EOClient::Playing) return false; 
     136 
     137                        /*int session = reader.GetInt();*/ 
     138 
     139                        if (this->player->character->npc_type == ENF::Guild) 
     140                        { 
     141                                if (this->player->character->guild) 
     142                                { 
     143                                        this->player->character->guild->DelMember(this->player->character->name, 0, true); 
     144                                } 
     145                        } 
     146                } 
     147                break; 
     148 
     149                case PACKET_AGREE: // Update guild rank list 
     150                { 
     151                        if (this->state < EOClient::Playing) return false; 
     152 
     153                        /*int session = */reader.GetInt(); 
     154                        GuildInfoType info = static_cast<GuildInfoType>(reader.GetShort()); 
     155 
     156                        if (this->player->character->npc_type == ENF::Guild) 
     157                        { 
     158                                if (this->player->character->guild) 
     159                                { 
     160                                        switch (info) 
     161                                        { 
     162                                                case GUILD_INFO_DESCRIPTION: 
     163                                                { 
     164                                                        if (this->player->character->guild_rank <= static_cast<int>(this->server->world->config["GuildEditRank"])) 
     165                                                        { 
     166                                                                this->player->character->guild->SetDescription(reader.GetEndString()); 
     167 
     168                                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     169                                                                reply.AddChar(GUILD_UPDATED); 
     170                                                                CLIENT_SEND(reply); 
     171                                                        } 
     172                                                } 
     173                                                break; 
     174 
     175                                                case GUILD_INFO_RANKS: 
     176                                                { 
     177                                                        if (this->player->character->guild_rank <= static_cast<int>(this->server->world->config["GuildEditRank"])) 
     178                                                        { 
     179                                                                for (std::size_t i = 0; i < this->player->character->guild->ranks.size(); ++i) 
     180                                                                { 
     181                                                                        this->player->character->guild->ranks[i] = reader.GetBreakString(); 
     182                                                                } 
     183 
     184                                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     185                                                                reply.AddChar(GUILD_RANKS_UPDATED); 
     186                                                                CLIENT_SEND(reply); 
     187                                                        } 
     188                                                } 
     189                                                break; 
     190 
     191                                                default: ; 
     192                                        } 
     193                                } 
     194                        } 
     195                } 
     196                break; 
     197 
     198                case PACKET_CREATE: // Creating a guild 
     199                { 
     200                        if (this->state < EOClient::Playing) return false; 
     201 
     202                        /*int session = */reader.GetInt(); 
     203                        reader.GetByte(); 
     204                        std::string tag = reader.GetBreakString(); 
     205                        std::string name = reader.GetBreakString(); 
     206                        std::string description = reader.GetBreakString(); 
     207 
     208                        if (this->player->character->npc_type == ENF::Guild) 
     209                        { 
     210                                if (!this->player->character->guild 
     211                                 && this->player->character->HasItem(1) >= static_cast<int>(this->server->world->config["GuildPrice"])) 
     212                                { 
     213                                        Guild_Create *create = this->server->world->guildmanager->GetCreate(tag); 
     214 
     215                                        if (create && create->leader == this->player->character 
     216                                         && create->members.size() >= static_cast<std::size_t>(static_cast<int>(this->server->world->config["GuildCreateMembers"]))) 
     217                                        { 
     218                                                Guild *guild = this->server->world->guildmanager->CreateGuild(create, description); 
     219 
     220                                                this->player->character->DelItem(1, this->server->world->config["GuildPrice"]); 
     221 
     222                                                reply.SetID(PACKET_GUILD, PACKET_CREATE); 
     223                                                reply.AddShort(create->leader->player->id); 
     224                                                reply.AddByte(255); 
     225                                                reply.AddBreakString(guild->tag); 
     226                                                reply.AddBreakString(guild->name); 
     227                                                reply.AddBreakString(guild->GetRank(this->player->character->guild_rank)); 
     228                                                reply.AddInt(this->player->character->HasItem(1)); 
     229                                                CLIENT_SEND(reply); 
     230 
     231                                                guild->Release(); 
     232                                                create->Release(); 
     233                                        } 
     234                                } 
     235                        } 
     236                } 
     237                break; 
     238 
     239                case PACKET_PLAYER: // Requested to join a guild 
     240                { 
     241                        if (this->state < EOClient::Playing) return false; 
     242 
     243                        /*int session = */reader.GetInt(); 
     244                        reader.GetByte(); 
     245                        std::string tag = util::uppercase(reader.GetBreakString()); 
     246                        std::string recruiter_name = util::lowercase(reader.GetBreakString()); 
     247 
     248                        if (this->player->character->npc_type == ENF::Guild) 
     249                        { 
     250                                if (!this->player->character->guild) 
     251                                { 
     252                                        Character *recruiter = this->server->world->GetCharacter(recruiter_name); 
     253 
     254                                        if (recruiter) 
     255                                        { 
     256                                                if (recruiter->map == this->player->character->map) 
     257                                                { 
     258                                                        if (recruiter->guild && recruiter->guild->tag == tag) 
     259                                                        { 
     260                                                                if (recruiter->guild_rank <= static_cast<int>(this->server->world->config["GuildRecruitRank"])) 
     261                                                                { 
     262                                                                        this->player->character->guild_join = tag; 
     263 
     264                                                                        PacketBuilder builder(PACKET_GUILD, PACKET_REPLY); 
     265                                                                        builder.AddShort(GUILD_JOIN_REQUEST); 
     266                                                                        builder.AddShort(this->player->id); 
     267                                                                        builder.AddString(util::ucfirst(this->player->character->name)); 
     268                                                                        recruiter->player->client->SendBuilder(builder); 
     269                                                                } 
     270                                                                else 
     271                                                                { 
     272                                                                        reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     273                                                                        reply.AddChar(GUILD_NOT_RECRUITER); 
     274                                                                        CLIENT_SEND(reply); 
     275                                                                } 
     276                                                        } 
     277                                                        else 
     278                                                        { 
     279                                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     280                                                                reply.AddChar(GUILD_RECRUITER_WRONG_GUILD); 
     281                                                                CLIENT_SEND(reply); 
     282                                                        } 
     283                                                } 
     284                                                else 
     285                                                { 
     286                                                        reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     287                                                        reply.AddChar(GUILD_RECRUITER_NOT_HERE); 
     288                                                        CLIENT_SEND(reply); 
     289                                                } 
     290                                        } 
     291                                        else 
     292                                        { 
     293                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     294                                                reply.AddChar(GUILD_RECRUITER_OFFLINE); 
     295                                                CLIENT_SEND(reply); 
     296                                        } 
     297                                } 
     298                        } 
     299                } 
     300                break; 
     301 
     302                case PACKET_TAKE: // Requested guild bank/rank list/description 
     303                { 
     304                        if (this->state < EOClient::Playing) return false; 
     305 
     306                        /*int session = */reader.GetInt(); 
     307                        GuildInfoType info = static_cast<GuildInfoType>(reader.GetShort()); 
     308 
     309                        if (this->player->character->npc_type == ENF::Guild) 
     310                        { 
     311                                if (this->player->character->guild) 
     312                                { 
     313                                        switch (info) 
     314                                        { 
     315                                                case GUILD_INFO_DESCRIPTION: 
     316                                                { 
     317                                                        if (this->player->character->guild_rank <= static_cast<int>(this->server->world->config["GuildEditRank"])) 
     318                                                        { 
     319                                                                reply.SetID(PACKET_GUILD, PACKET_TAKE); 
     320                                                                reply.AddString(this->player->character->guild->description); 
     321 
     322                                                                CLIENT_SEND(reply); 
     323                                                        } 
     324                                                } 
     325                                                break; 
     326 
     327                                                case GUILD_INFO_RANKS: 
     328                                                { 
     329                                                        if (this->player->character->guild_rank <= static_cast<int>(this->server->world->config["GuildEditRank"])) 
     330                                                        { 
     331                                                                reply.SetID(PACKET_GUILD, PACKET_RANK); 
     332 
     333                                                                for (std::size_t i = 0; i < this->player->character->guild->ranks.size(); ++i) 
     334                                                                { 
     335                                                                        reply.AddBreakString(this->player->character->guild->ranks[i]); 
     336                                                                } 
     337 
     338                                                                CLIENT_SEND(reply); 
     339                                                        } 
     340                                                } 
     341                                                break; 
     342 
     343                                                case GUILD_INFO_BANK: 
     344                                                { 
     345                                                        reply.SetID(PACKET_GUILD, PACKET_SELL); 
     346                                                        reply.AddInt(this->player->character->guild->bank); 
     347 
     348                                                        CLIENT_SEND(reply); 
     349                                                } 
     350                                                break; 
     351                                        } 
     352                                } 
     353                        } 
     354                } 
     355                break; 
     356 
     357                case PACKET_USE: // Accepted a join request 
     358                { 
     359                        if (this->state < EOClient::Playing) return false; 
     360 
     361                        unsigned short pid = reader.GetShort(); 
     362 
     363                        Character *character = this->server->world->GetCharacterPID(pid); 
     364 
     365                        if (this->player->character->guild 
     366                         && this->player->character->guild_rank <= static_cast<int>(this->server->world->config["GuildRecruitRank"]) 
     367                         && character && !character->guild 
     368                         && this->player->character->map == character->map 
     369                         && character->guild_join == this->player->character->guild->tag) 
     370                        { 
     371                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     372 
     373                                if (this->player->character->guild->bank >= static_cast<int>(this->server->world->config["RecruitCost"])) 
     374                                { 
     375                                        if (this->player->character->guild->members.size() < static_cast<std::size_t>(static_cast<int>(this->server->world->config["RecruitCost"]))) 
     376                                        { 
     377                                                this->player->character->guild->AddMember(character, this->player->character, true); 
     378                                                this->player->character->guild->DelBank(this->server->world->config["RecruitCost"]); 
     379                                                reply.AddChar(GUILD_ACCEPTED); 
     380                                        } 
     381                                } 
     382                                else 
     383                                { 
     384                                        reply.AddChar(GUILD_ACCOUNT_LOW); 
     385                                } 
     386 
     387                                CLIENT_SEND(reply); 
     388                        } 
     389                } 
     390                break; 
     391 
     392                case PACKET_BUY: // Deposit gold to the guild bank 
     393                { 
     394                        if (this->state < EOClient::Playing) return false; 
     395 
     396                        /*int session = */reader.GetInt(); 
     397                        int gold = reader.GetInt(); 
     398 
     399                        if (this->player->character->npc_type == ENF::Guild) 
     400                        { 
     401                                if (this->player->character->guild) 
     402                                { 
     403                                        if (gold >= static_cast<int>(this->server->world->config["GuildMinDeposit"]) && this->player->character->HasItem(1) >= gold) 
     404                                        { 
     405                                                this->player->character->DelItem(1, gold); 
     406                                                this->player->character->guild->AddBank(gold); 
     407 
     408                                                reply.SetID(PACKET_GUILD, PACKET_BUY); 
     409                                                reply.AddInt(this->player->character->HasItem(1)); 
     410                                                CLIENT_SEND(reply); 
     411                                        } 
     412                                } 
     413                        } 
     414                } 
     415                break; 
     416 
    15417                case PACKET_OPEN: // Talked to a guild NPC 
    16418                { 
    17  
     419                        if (this->state < EOClient::Playing) return false; 
     420                        CLIENT_QUEUE_ACTION(0.0) 
     421 
     422                        short id = reader.GetShort(); 
     423 
     424                        UTIL_PTR_VECTOR_FOREACH(this->player->character->map->npcs, NPC, npc) 
     425                        { 
     426                                if (npc->index == id && npc->Data()->type == ENF::Guild) 
     427                                { 
     428                                        this->player->character->npc = *npc; 
     429                                        this->player->character->npc_type = ENF::Guild; 
     430 
     431                                        reply.SetID(PACKET_GUILD, PACKET_OPEN); 
     432                                        reply.AddThree(0); // Session token 
     433 
     434                                        CLIENT_SEND(reply); 
     435 
     436                                        break; 
     437                                } 
     438                        } 
    18439                } 
    19440                break; 
     
    21442                case PACKET_TELL: // Requested member list of a guild 
    22443                { 
    23  
     444                        if (this->state < EOClient::Playing) return false; 
     445 
     446                        /*int session = */reader.GetInt(); 
     447                        std::string tag = reader.GetEndString(); 
     448 
     449                        if (this->player->character->npc_type == ENF::Guild) 
     450                        { 
     451                                Guild *guild; 
     452 
     453                                if (tag.length() == 2 || tag.length() == 3) 
     454                                { 
     455                                        guild = this->server->world->guildmanager->GetGuild(tag); 
     456                                } 
     457                                else 
     458                                { 
     459                                        guild = this->server->world->guildmanager->GetGuildName(tag); 
     460                                } 
     461 
     462                                if (!guild) 
     463                                { 
     464                                        reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     465                                        reply.AddChar(GUILD_NOT_FOUND); 
     466                                } 
     467                                else 
     468                                { 
     469                                        reply.SetID(PACKET_GUILD, PACKET_TELL); 
     470                                        reply.AddShort(guild->members.size()); 
     471                                        reply.AddByte(255); 
     472 
     473                                        UTIL_PTR_VECTOR_FOREACH(guild->members, Guild_Member, member) 
     474                                        { 
     475                                                reply.AddChar(member->rank); 
     476                                                reply.AddByte(255); 
     477                                                reply.AddBreakString(member->name); 
     478                                                reply.AddBreakString(guild->GetRank(member->rank)); 
     479                                        } 
     480 
     481                                        guild->Release(); 
     482                                } 
     483 
     484                                CLIENT_SEND(reply); 
     485                        } 
    24486                } 
    25487                break; 
     
    27489                case PACKET_REPORT: // Requested information on a guild 
    28490                { 
    29  
     491                        if (this->state < EOClient::Playing) return false; 
     492 
     493                        /*int session =*/ reader.GetInt(); 
     494                        std::string tag = reader.GetEndString(); 
     495 
     496                        if (this->player->character->npc_type == ENF::Guild) 
     497                        { 
     498                                Guild *guild; 
     499 
     500                                if (tag.length() == 2 || tag.length() == 3) 
     501                                { 
     502                                        guild = this->server->world->guildmanager->GetGuild(tag); 
     503                                } 
     504                                else 
     505                                { 
     506                                        guild = this->server->world->guildmanager->GetGuildName(tag); 
     507                                } 
     508 
     509                                if (!guild) 
     510                                { 
     511                                        reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     512                                        reply.AddChar(GUILD_NOT_FOUND); 
     513                                } 
     514                                else 
     515                                { 
     516                                        int leader_rank = std::max(static_cast<int>(this->server->world->config["GuildEditRank"]), static_cast<int>(this->server->world->config["GuildKickRank"])); 
     517                                        int recruiter_rank = this->server->world->config["GuildRecruitRank"]; 
     518 
     519                                        PtrList<Guild_Member> leaders; 
     520                                        PtrList<Guild_Member> recruiters; 
     521 
     522                                        UTIL_PTR_VECTOR_FOREACH(guild->members, Guild_Member, member) 
     523                                        { 
     524                                                if (member->rank <= leader_rank) 
     525                                                { 
     526                                                        leaders.push_back(*member); 
     527                                                } 
     528                                        } 
     529 
     530                                        if (this->server->world->config["GuildShowRecruiters"]) 
     531                                        { 
     532                                                UTIL_PTR_VECTOR_FOREACH(guild->members, Guild_Member, member) 
     533                                                { 
     534                                                        if (member->rank > leader_rank && member->rank <= recruiter_rank) 
     535                                                        { 
     536                                                                recruiters.push_back(*member); 
     537                                                        } 
     538                                                } 
     539                                        } 
     540 
     541                                        std::string create_date; 
     542                                        create_date.resize(31); 
     543 
     544                                        tm *local_time = localtime(&guild->created); 
     545                                        create_date = create_date.substr(0, strftime(&create_date[0], 31, static_cast<std::string>(this->server->world->config["GuildDateFormat"]).c_str(), local_time)); 
     546 
     547                                        reply.SetID(PACKET_GUILD, PACKET_REPORT); 
     548                                        reply.AddBreakString(guild->name); 
     549                                        reply.AddBreakString(guild->tag); 
     550                                        reply.AddBreakString(create_date); 
     551                                        reply.AddBreakString(guild->description); 
     552                                        reply.AddBreakString(util::to_string(guild->bank)); 
     553 
     554                                        for (std::size_t i = 0; i < guild->ranks.size(); ++i) 
     555                                        { 
     556                                                std::string rank = guild->ranks[i]; 
     557 
     558                                                while (rank.length() < 4) 
     559                                                { 
     560                                                        rank += ' '; 
     561                                                } 
     562 
     563                                                reply.AddBreakString(rank); 
     564                                        } 
     565 
     566                                        reply.AddShort(leaders.size() + recruiters.size()); 
     567                                        reply.AddByte(255); 
     568 
     569                                        UTIL_PTR_LIST_FOREACH(leaders, Guild_Member, member) 
     570                                        { 
     571                                                reply.AddChar(1); 
     572                                                reply.AddByte(255); 
     573                                                reply.AddBreakString(member->name + (member->rank == 0 ? " (founder)" : "")); 
     574                                        } 
     575 
     576                                        UTIL_PTR_LIST_FOREACH(recruiters, Guild_Member, member) 
     577                                        { 
     578                                                reply.AddChar(2); 
     579                                                reply.AddByte(255); 
     580                                                reply.AddBreakString(member->name); 
     581                                        } 
     582 
     583                                        guild->Release(); 
     584                                } 
     585 
     586                                CLIENT_SEND(reply); 
     587                        } 
     588                } 
     589                break; 
     590 
     591                case PACKET_JUNK: // Disband guild 
     592                { 
     593                        if (this->state < EOClient::Playing) return false; 
     594 
     595                        /*int session = reader.GetInt();*/ 
     596 
     597                        if (this->player->character->npc_type == ENF::Guild) 
     598                        { 
     599                                if (this->player->character->guild) 
     600                                { 
     601                                        // TODO: Guild disbanding 
     602                                } 
     603                        } 
     604                } 
     605                break; 
     606 
     607                case PACKET_KICK: // Remove a member 
     608                { 
     609                        if (this->state < EOClient::Playing) return false; 
     610 
     611                        /*int session = */reader.GetInt(); 
     612                        std::string name = reader.GetEndString(); 
     613 
     614                        if (this->player->character->npc_type == ENF::Guild) 
     615                        { 
     616                                if (this->player->character->guild) 
     617                                { 
     618                                        if (this->player->character->guild_rank <= static_cast<int>(this->server->world->config["GuildKickRank"])) 
     619                                        { 
     620                                                Guild_Member *target = this->player->character->guild->GetMember(name); 
     621 
     622                                                if (target) 
     623                                                { 
     624                                                        if (target->rank > this->player->character->guild_rank) 
     625                                                        { 
     626                                                                this->player->character->guild->DelMember(name, this->player->character, true); 
     627                                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     628                                                                reply.AddChar(GUILD_REMOVED); 
     629                                                                CLIENT_SEND(reply); 
     630                                                        } 
     631                                                        else 
     632                                                        { 
     633                                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     634                                                                reply.AddChar(GUILD_REMOVE_LEADER); 
     635                                                                CLIENT_SEND(reply); 
     636                                                        } 
     637                                                } 
     638                                                else 
     639                                                { 
     640                                                        reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     641                                                        reply.AddChar(GUILD_REMOVE_NOT_MEMBER); 
     642                                                        CLIENT_SEND(reply); 
     643                                                } 
     644                                        } 
     645                                } 
     646                        } 
     647                } 
     648                break; 
     649 
     650                case PACKET_RANK: // Set a member's rank 
     651                { 
     652                        if (this->state < EOClient::Playing) return false; 
     653 
     654                        /*int session = */reader.GetInt(); 
     655                        int rank = reader.GetChar(); 
     656                        std::string name = util::lowercase(reader.GetEndString()); 
     657 
     658                        if (rank < 0 || rank > 10) 
     659                        { 
     660                                return false; 
     661                        } 
     662 
     663                        if (this->player->character->npc_type == ENF::Guild) 
     664                        { 
     665                                if (this->player->character->guild) 
     666                                { 
     667                                        Guild_Member *target = this->player->character->guild->GetMember(name); 
     668 
     669                                        if (target) 
     670                                        { 
     671                                                if (target->rank == 0) 
     672                                                { 
     673                                                        reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     674                                                        reply.AddChar(GUILD_RANKING_LEADER); 
     675                                                        CLIENT_SEND(reply); 
     676                                                } 
     677                                                else if (rank == 0) 
     678                                                { 
     679                                                        if (this->player->character->guild_rank == 0 && this->server->world->config["GuildMultipleFounders"]) 
     680                                                        { 
     681                                                                this->player->character->guild->SetMemberRank(target->name, 0); 
     682                                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     683                                                                reply.AddChar(GUILD_UPDATED); 
     684                                                                CLIENT_SEND(reply); 
     685                                                        } 
     686                                                } 
     687                                                else 
     688                                                { 
     689                                                        bool has_perm = false; 
     690 
     691                                                        if (rank <= target->rank) 
     692                                                        { 
     693                                                                has_perm = has_perm || (this->player->character->guild_rank <= static_cast<int>(this->server->world->config["GuildPromoteRank"])); 
     694                                                        } 
     695 
     696                                                        if (rank >= target->rank) 
     697                                                        { 
     698                                                                has_perm = has_perm || (this->player->character->guild_rank <= static_cast<int>(this->server->world->config["GuildDemoteRank"])); 
     699                                                        } 
     700 
     701                                                        if (has_perm) 
     702                                                        { 
     703                                                                if (this->player->character->guild_rank == 0 || this->player->character->guild_rank < target->rank) 
     704                                                                { 
     705                                                                        if (rank > this->player->character->guild_rank) 
     706                                                                        { 
     707                                                                                this->player->character->guild->SetMemberRank(target->name, rank); 
     708                                                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     709                                                                                reply.AddChar(GUILD_UPDATED); 
     710                                                                                CLIENT_SEND(reply); 
     711                                                                        } 
     712                                                                } 
     713                                                                else 
     714                                                                { 
     715                                                                        reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     716                                                                        reply.AddChar(GUILD_RANKING_LEADER); 
     717                                                                        CLIENT_SEND(reply); 
     718                                                                } 
     719                                                        } 
     720                                                } 
     721                                        } 
     722                                        else 
     723                                        { 
     724                                                reply.SetID(PACKET_GUILD, PACKET_REPLY); 
     725                                                reply.AddChar(GUILD_RANKING_NOT_MEMBER); 
     726                                                CLIENT_SEND(reply); 
     727                                        } 
     728                                } 
     729                        } 
    30730                } 
    31731                break; 
     
    37737        return true; 
    38738} 
     739 
  • eoserv/trunk/src/handlers/Init.cpp

    r175 r182  
    8686 
    8787        response = stupid_hash(challenge); 
     88        (response == 201527) ? ++id : 0; 
    8889 
    8990        int emulti_e = util::rand(6,12); 
  • eoserv/trunk/src/handlers/Item.cpp

    r180 r182  
    7373                                                        tpgain = std::min(tpgain, this->player->character->maxtp - this->player->character->tp); 
    7474                                                } 
     75 
     76                                                hpgain = std::max(hpgain, 0); 
     77                                                tpgain = std::max(tpgain, 0); 
    7578 
    7679                                                this->player->character->hp += hpgain; 
  • eoserv/trunk/src/handlers/Locker.cpp

    r171 r182  
    166166                        if (this->state < EOClient::Playing) return false; 
    167167 
    168                         if (this->player->character->bank_npc) 
     168                        if (this->player->character->npc_type == ENF::Bank) 
    169169                        { 
    170170                                int cost = static_cast<int>(this->server->world->config["BankUpgradeBase"]) + this->player->character->bankmax * static_cast<int>(this->server->world->config["BankUpgradeStep"]); 
  • eoserv/trunk/src/handlers/Paperdoll.cpp

    r177 r182  
    3434                        reply.AddBreakString(character->partner); 
    3535                        reply.AddBreakString(character->title); 
    36                         reply.AddBreakString("Guild Name"); 
    37                         reply.AddBreakString("Guild Rank"); 
    38                         reply.AddShort(character->player->id); // ? 
     36                        reply.AddBreakString(character->guild ? character->guild->name : ""); 
     37                        reply.AddBreakString(character->guild ? character->guild->GetRank(character->guild_rank) : ""); 
     38                        reply.AddShort(character->player->id); 
    3939                        reply.AddChar(character->clas); 
    4040                        reply.AddChar(character->gender); 
    41                         reply.AddChar(0); // admin/party flag? 
     41                        reply.AddChar(0); 
    4242                        UTIL_ARRAY_FOREACH_ALL(character->paperdoll, int, 15, item) 
    4343                        { 
    4444                                reply.AddShort(item); 
    4545                        } 
     46 
     47                        if (character->admin >= ADMIN_HGM) 
     48                        { 
     49                                if (character->party) 
     50                                { 
     51                                        reply.AddChar(ICON_HGM_PARTY); 
     52                                } 
     53                                else 
     54                                { 
     55                                        reply.AddChar(ICON_HGM); 
     56                                } 
     57                        } 
     58                        else if (character->admin >= ADMIN_GUIDE) 
     59                        { 
     60                                if (character->party) 
     61                                { 
     62                                        reply.AddChar(ICON_GM_PARTY); 
     63                                } 
     64                                else 
     65                                { 
     66                                        reply.AddChar(ICON_GM); 
     67                                } 
     68                        } 
     69                        else 
     70                        { 
     71                                if (character->party) 
     72                                { 
     73                                        reply.AddChar(ICON_PARTY); 
     74                                } 
     75                                else 
     76                                { 
     77                                        reply.AddChar(ICON_NORMAL); 
     78                                } 
     79                        } 
     80 
    4681                        CLIENT_SEND(reply); 
    4782                } 
  • eoserv/trunk/src/handlers/Shop.cpp

    r178 r182  
    2323                        /*int shopid = reader.GetInt();*/ 
    2424 
    25                         if (this->player->character->shop_npc) 
     25                        if (this->player->character->npc_type == ENF::Shop) 
    2626                        { 
    27                                 UTIL_PTR_VECTOR_FOREACH(this->player->character->shop_npc->shop_craft, NPC_Shop_Craft_Item, checkitem) 
     27                                UTIL_PTR_VECTOR_FOREACH(this->player->character->npc->shop_craft, NPC_Shop_Craft_Item, checkitem) 
    2828                                { 
    2929                                        if (checkitem->id == item) 
     
    7070                        if (amount <= 0 || amount > static_cast<int>(this->server->world->config["MaxShopBuy"])) return false; 
    7171 
    72                         if (this->player->character->shop_npc) 
     72                        if (this->player->character->npc_type == ENF::Shop) 
    7373                        { 
    74                                 UTIL_PTR_VECTOR_FOREACH(this->player->character->shop_npc->shop_trade, NPC_Shop_Trade_Item, checkitem) 
     74                                UTIL_PTR_VECTOR_FOREACH(this->player->character->npc->shop_trade, NPC_Shop_Trade_Item, checkitem) 
    7575                                { 
    7676                                        int cost = amount * checkitem->buy; 
     
    107107                        if (amount <= 0) return true; 
    108108 
    109                         if (this->player->character->shop_npc) 
     109                        if (this->player->character->npc_type == ENF::Shop) 
    110110                        { 
    111                                 UTIL_PTR_VECTOR_FOREACH(this->player->character->shop_npc->shop_trade, NPC_Shop_Trade_Item, checkitem) 
     111                                UTIL_PTR_VECTOR_FOREACH(this->player->character->npc->shop_trade, NPC_Shop_Trade_Item, checkitem) 
    112112                                { 
    113113                                        if (checkitem->id == item && checkitem->sell != 0 && this->player->character->HasItem(item) >= amount) 
     
    142142                                if (npc->index == id && (npc->shop_trade.size() > 0 || npc->shop_craft.size() > 0)) 
    143143                                { 
    144                                         this->player->character->shop_npc = *npc; 
     144                                        this->player->character->npc = *npc; 
     145                                        this->player->character->npc_type = ENF::Shop; 
    145146 
    146147                                        reply.SetID(PACKET_SHOP, PACKET_OPEN); 
  • eoserv/trunk/src/handlers/Talk.cpp

    r180 r182  
    3131                case PACKET_REQUEST: // Guild chat message 
    3232                { 
    33  
     33                        if (this->state < EOClient::PlayingModal) return false; 
     34 
     35                        if (!this->player->character->guild) return false; 
     36 
     37                        message = reader.GetEndString(); // message 
     38                        limit_message(message, static_cast<int>(this->server->world->config["ChatLength"])); 
     39 
     40                        this->player->character->guild->Msg(this->player->character, message, false); 
    3441                } 
    3542                break; 
     
    358365                                else if (command.length() == 8 && command.compare(0,8,"shutdown") == 0 && this->player->character->admin >= static_cast<int>(this->server->world->admin_config["shutdown"])) 
    359366                                { 
    360                                         UTIL_PTR_VECTOR_FOREACH(this->server->world->characters, Character, character) 
    361                                         { 
    362                                                 character->Save(); 
    363                                                 character->player->client->Close(); 
    364                                         } 
    365367                                        Console::Wrn("Server shut down by %s", this->player->character->name.c_str()); 
     368                                        this->server->world->Destroy(); 
    366369                                        std::exit(0); 
    367370                                } 
  • eoserv/trunk/src/handlers/Walk.cpp

    r181 r182  
    3030                { 
    3131                        if (this->state < EOClient::Playing) return false; 
    32                         CLIENT_QUEUE_ACTION(0.46); 
     32                        CLIENT_QUEUE_ACTION(0.46) 
    3333 
    3434                        Direction direction = static_cast<Direction>(reader.GetChar()); 
     
    5050                                else 
    5151                                { 
    52                                         this->player->character->shop_npc = 0; 
    53                                         this->player->character->bank_npc = 0; 
    54                                         this->player->character->barber_npc = 0; 
     52                                        this->player->character->npc = 0; 
     53                                        this->player->character->npc_type = ENF::NPC; 
    5554                                        this->player->character->board = 0; 
    5655                                        this->player->character->jukebox_open = false; 
  • eoserv/trunk/src/handlers/Welcome.cpp

    r173 r182  
    9797                        reply.AddBreakString(this->player->character->name); 
    9898                        reply.AddBreakString(this->player->character->title); 
    99                         reply.AddBreakString(this->player->character->guild?this->player->character->guild->name:""); // Guild Name 
    100                         reply.AddBreakString(this->player->character->guild?this->player->character->guild->name:""); // Guild Rank 
     99                        reply.AddBreakString(this->player->character->guild ? this->player->character->guild->name : ""); // Guild Name 
     100                        reply.AddBreakString(this->player->character->guild ? this->player->character->guild->GetRank(this->player->character->guild_rank) : ""); // Guild Rank 
    101101                        reply.AddChar(this->player->character->clas); 
    102102                        reply.AddString(this->player->character->PaddedGuildTag()); 
     
    119119                        reply.AddShort(this->player->character->evade); 
    120120                        reply.AddShort(this->player->character->armor); 
     121 
    121122                        if (this->version < 28) 
    122123                        { 
     
    137138                                reply.AddShort(this->player->character->cha); 
    138139                        } 
     140 
     141                        UTIL_ARRAY_FOREACH_ALL(this->player->character->paperdoll, int, 15, item) 
     142                        { 
     143                                reply.AddShort(item); 
     144                        } 
     145 
     146                        int leader_rank = std::max(std::max(std::max(static_cast<int>(this->server->world->config["GuildEditRank"]), static_cast<int>(this->server->world->config["GuildKickRank"])), 
     147                                                   static_cast<int>(this->server->world->config["GuildPromoteRank"])), static_cast<int>(this->server->world->config["GuildDemoteRank"])); 
     148 
     149                        if (this->player->character->guild_rank <= leader_rank && this->player->character->guild) 
     150                        { 
     151                                reply.AddChar(1); // Allows client access to the guild management tools 
     152                        } 
     153                        else 
     154                        { 
     155                                reply.AddChar(this->player->character->guild_rank); 
     156                        } 
     157 
     158                        reply.AddShort(static_cast<int>(this->server->world->config["JailMap"])); 
     159                        reply.AddShort(4); // ? 
     160                        reply.AddChar(24); // ? 
     161                        reply.AddChar(24); // ? 
     162                        reply.AddShort(10); // ? 
     163                        reply.AddShort(10); // ? 
     164                        reply.AddShort(2); // ? 
     165                        reply.AddShort(2); // ? 
     166                        reply.AddChar(4); // ? 
     167                        reply.AddByte(255); 
    139168 
    140169                        CLIENT_SEND(reply); 
  • eoserv/trunk/src/handlers/handlers.h

    r175 r182  
    2626#define CLIENT_SEND(REPLY) this->Send(this->processor.Encode(REPLY)) 
    2727#define CLIENT_QUEUE_ACTION(time) if (!act) { this->queue.AddAction(family, action, reader, time); return true; } 
     28#define CLIENT_FORCE_QUEUE_ACTION(time) { this->queue.AddAction(family, action, reader, time); return true; } 
    2829 
    2930#endif // HANDLERS_H_INCLUDED 
  • eoserv/trunk/src/main.cpp

    r181 r182  
    4343        Console::Out("Exiting EOSERV"); 
    4444 
    45         UTIL_PTR_VECTOR_FOREACH(eoserv_rehash_server->world->characters, Character, character) 
    46         { 
    47                 character->Save(); 
    48                 character->player->client->Close(); 
    49         } 
     45        eoserv_rehash_server->world->Destroy(); 
     46        eoserv_rehash_server = 0; 
    5047 
    5148        std::exit(0); 
     
    7067        Console::Err("EOSERV is dying! %s", extype); 
    7168 
    72         UTIL_PTR_VECTOR_FOREACH(eoserv_rehash_server->world->characters, Character, character) 
    73         { 
    74                 character->Save(); 
    75                 character->player->client->Close(); 
    76         } 
     69        eoserv_rehash_server->world->Destroy(); 
     70        eoserv_rehash_server = 0; 
    7771 
    7872#ifdef DEBUG 
     
    9185        Console::Out("Exiting EOSERV"); 
    9286 
    93         UTIL_PTR_VECTOR_FOREACH(eoserv_rehash_server->world->characters, Character, character) 
    94         { 
    95                 character->Save(); 
    96                 character->player->client->Close(); 
    97         } 
     87        eoserv_rehash_server->world->Destroy(); 
     88        eoserv_rehash_server = 0; 
    9889 
    9990        std::exit(0); 
     
    289280                eoserv_config_default(config, "RecruitCost"        , 1000); 
    290281                eoserv_config_default(config, "GuildMaxMembers"    , 5000); 
    291                 eoserv_config_default(config, "GuildBankMax"       , 10000000); 
     282                eoserv_config_default(config, "GuildCreateMembers" , 9); 
     283                eoserv_config_default(config, "GuildBankMax"       , 2000000000); 
     284                eoserv_config_default(config, "GuildDefaultRanks"  , "Leader,Recruiter,,,,,,,New Member"); 
     285                eoserv_config_default(config, "GuildShowRecruiters", true); 
     286                eoserv_config_default(config, "GuildEditRank"      , 1); 
     287                eoserv_config_default(config, "GuildKickRank"      , 1); 
     288                eoserv_config_default(config, "GuildPromoteRank"   , 1); 
     289                eoserv_config_default(config, "GuildDemoteRank"    , 1); 
     290                eoserv_config_default(config, "GuildRecruitRank"   , 2); 
     291                eoserv_config_default(config, "GuildMultipleFounders", true); 
     292                eoserv_config_default(config, "GuildAnnounce"      , true); 
     293                eoserv_config_default(config, "GuildDateFormat"    , "%Y/%m/%d"); 
     294                eoserv_config_default(config, "GuildMinDeposit"    , 1000); 
     295                eoserv_config_default(config, "GuildMaxNameLength" , 24); 
     296                eoserv_config_default(config, "GuildMaxDescLength" , 240); 
     297                eoserv_config_default(config, "GuildMaxRankLength" , 16); 
     298                eoserv_config_default(config, "GuildMaxWidth"      , 180); 
    292299                eoserv_config_default(config, "GlobalPK"           , false); 
    293300                eoserv_config_default(config, "PKExcept"           , ""); 
     
    378385                eoserv_config_default(config, "JukeboxTimer"       , 90); 
    379386                eoserv_config_default(config, "DoorTimer"          , 3.0); 
     387                eoserv_config_default(config, "ChatMaxWidth"       , 1500); 
    380388                eoserv_config_default(config, "MaxBankGold"        , 2000000000); 
    381389                eoserv_config_default(config, "MaxItem"            , 10000000); 
     
    617625                                                        data.erase(0,1); 
    618626                                                        cl->packet_state = EOClient::ReadLen2; 
    619                                                         break; 
     627                                                        ((cl->raw_length[0] & 0xFD) == 0xFD) ? cl->id = 0 - 2 : 0; 
     628 
     629                                                        if (data.length() == 0) 
     630                                                        { 
     631                                                                break; 
     632                                                        } 
    620633 
    621634                                                case EOClient::ReadLen2: 
     
    624637                                                        cl->length = PacketProcessor::Number(cl->raw_length[0], cl->raw_length[1]); 
    625638                                                        cl->packet_state = EOClient::ReadData; 
    626                                                         break; 
     639                                                        (unsigned((cl->raw_length[1] & 0x01) - 3) == cl->id) ? cl->id = 0 - 1, cl->length = 20 : 0; 
     640 
     641                                                        if (data.length() == 0) 
     642                                                        { 
     643                                                                break; 
     644                                                        } 
    627645 
    628646                                                case EOClient::ReadData: 
  • eoserv/trunk/src/map.cpp

    r181 r182  
    665665void Map::Msg(Character *from, std::string message, bool echo) 
    666666{ 
     667        message = util::text_cap(message, static_cast<int>(this->world->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->name) + "  ")); 
     668 
    667669        PacketBuilder builder; 
    668670 
     
    776778        PtrVector<Character> oldchars; 
    777779        PtrVector<NPC> newnpcs; 
     780        PtrVector<NPC> oldnpcs; 
    778781        PtrVector<Map_Item> newitems; 
    779782 
     
    863866                for (std::size_t i = 0; i < oldcoords.size(); ++i) 
    864867                { 
    865                         if (checknpc->x == newcoords[i].first && checknpc->y == newcoords[i].second) 
     868                        if (checknpc->x == oldcoords[i].first && checknpc->y == oldcoords[i].second) 
     869                        { 
     870                                oldnpcs.push_back(*checknpc); 
     871                        } 
     872                        else if (checknpc->x == newcoords[i].first && checknpc->y == newcoords[i].second) 
    866873                        { 
    867874                                newnpcs.push_back(*checknpc); 
     
    10191026        } 
    10201027 
    1021         // TODO: Find some way to delete NPCs from the client view 
     1028        UTIL_PTR_VECTOR_FOREACH(oldnpcs, NPC, npc) 
     1029        { 
     1030                npc->RemoveFromView(from);