#ifdef FULL_YANG_OWN
ChangeGold(-price);
#else
PointChange(POINT_GOLD, -price);
#endif
if (days != 0)
{
CShopManager::instance().CreateOfflineShop(this, m_stShopSign.c_str(), map_shop, id);
m_stShopSign.clear();
return;
}
TPacketGCShopSign p;
p.bHeader = HEADER_GC_SHOP_SIGN;
p.dwVID = GetVID();
strlcpy(p.szSign, m_stShopSign.c_str(), sizeof(p.szSign));
PacketAround(&p, sizeof(TPacketGCShopSign));
m_pkMyShop = CShopManager::instance().CreatePCShop(this, pTable, bItemCount);
if (!m_pkMyShop)
{
sys_err("Cannot open normal shop %s %s", GetName(), m_stShopSign.c_str());
return;
}
if (IsPolymorphed() == true)
{
RemoveAffect(AFFECT_POLYMORPH);
}
if (GetHorse())
{
HorseSummon(false, true);
}
else if (GetMountVnum())
{
RemoveAffect(AFFECT_MOUNT);
RemoveAffect(AFFECT_MOUNT_BONUS);
}
SetPolymorph(30000, true);
}
void CHARACTER::SetShopSign(const char * name)
{
m_stShopSign = name;
TPacketGCShopSign p;
p.bHeader = HEADER_GC_SHOP_SIGN;
p.dwVID = GetVID();
strlcpy(p.szSign, m_stShopSign.c_str(), sizeof(p.szSign));
PacketAround(&p, sizeof(TPacketGCShopSign));
}
TPrivShop CHARACTER::GetPrivShopTable(DWORD id)
{
TPrivShop shop;
memset(&shop, 0, sizeof(TPrivShop));
PSHOP_MAP::iterator it = m_mapshops.find(id);
if (it != m_mapshops.end())
return it->second;
return shop;
}
void CHARACTER::UpdatePrivShopTable(DWORD id, TPrivShop shop)
{
if (m_mapshops.find(id) != m_mapshops.end())
m_mapshops[id]=shop;
SendShops();
}
void CHARACTER::RemovePrivShopTable(DWORD id)
{
if (m_mapshops.find(id) != m_mapshops.end())
m_mapshops.erase(m_mapshops.find(id));
SendShops();
}
void CHARACTER::UpdateShopItems()
{
LPSHOP npcshop = GetMyShop();
LPCHARACTER owner = CHARACTER_MANAGER::instance().FindByPID(GetPrivShopOwner());
if (!npcshop || !IsPrivShop())
return;
npcshop->RemoveGuests(owner);
npcshop->SetLocked(true);
npcshop->ClearItems();
std::vector<TShopItemTable *> map_shop;
char szSockets[1024] = { '\0' };
char *tempSockets = szSockets;
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
{
tempSockets += sprintf(tempSockets, "socket%d", i);
if (i<ITEM_SOCKET_MAX_NUM - 1)
tempSockets += sprintf(tempSockets, ",");
}
char szAttrs[1024] = { '\0' };
char *tempAttrs = szAttrs;
for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; i++)
{
if (i < 7)
tempAttrs += sprintf(tempAttrs, "attrtype%d,attrvalue%d", i, i);
else
tempAttrs += sprintf(tempAttrs, "applytype%d,applyvalue%d", i - 7, i - 7);
if (i<ITEM_ATTRIBUTE_MAX_NUM - 1)
tempAttrs += sprintf(tempAttrs, ",");
}
SQLMsg * Msg(DBManager::instance().DirectQuery("SELECT id,vnum,count,display_pos,price,%s,%s from player_shop_items where shop_id='%d'",szSockets,szAttrs, GetPrivShop()));
SQLResult * Res = Msg->Get();
if (Res->uiNumRows > 0)
{
MYSQL_ROW row;
while ((row = mysql_fetch_row(Res->pSQLResult)) != NULL)
{
int col = 0;
TShopItemTable *shop = new TShopItemTable;
memset(shop, 0, sizeof(TShopItemTable));
DWORD id;
shop->pos.window_type = INVENTORY;
str_to_number(id, row[col++]);
str_to_number(shop->vnum, row[col++]);
str_to_number(shop->count, row[col++]);
str_to_number(shop->display_pos, row[col++]);
//col++;
str_to_number(shop->price, row[col++]);
const TItemTable * item_table = ITEM_MANAGER::instance().GetTable(shop->vnum);
if (!item_table)
{
sys_err("Shop: no item table by item vnum #%d", shop->vnum);
continue;
}
for (int i = 0; i < INVENTORY_MAX_NUM; ++i)
{
if (NULL != GetInventoryItem(i) && GetInventoryItem(i)->GetRealID() == id)
GetInventoryItem(i)->RemoveFromCharacter();
}
LPITEM item = ITEM_MANAGER::instance().CreateItem(shop->vnum, shop->count, id, false, -1, true);
if (-1 == (shop->pos.cell = GetEmptyInventory(item_table->bSize)))
{
sys_err("no empty position in npc inventory");
return;
}
if (item)
{
item->ClearAttribute();
item->SetRealID(id);
for (int s = 0;s<ITEM_SOCKET_MAX_NUM;s++)
{
DWORD soc;
str_to_number(soc, row[col++]);
item->SetSocket(s, soc, false);
}
for (int at = 0;at<ITEM_ATTRIBUTE_MAX_NUM;at++)
{
DWORD attr;
long val;
str_to_number(attr, row[col++]);
str_to_number(val, row[col++]);
item->SetForceAttribute(at, attr, val);
}
item->AddToCharacter(this, shop->pos);
}
else
{
sys_err("%d is not item", shop->vnum);
continue;
}
map_shop.push_back(shop);
}
}
if (map_shop.size() == 0 || map_shop.size() > SHOP_HOST_ITEM_MAX_NUM)
{
DeleteMyShop();
return;
}
npcshop->SetPrivShopItems(map_shop);
npcshop->SetLocked(false);
for (int i = 0;i < SHOP_HOST_ITEM_MAX_NUM;i++)
npcshop->BroadcastUpdateItem(i);
if (owner)
{
owner->LoadPrivShops();
owner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("SHOP_EDIT_SUCCESS"));
}
}
void CHARACTER::LoadPrivShops()
{
m_mapshops.clear();
#ifndef FULL_YANG
SQLMsg * pkMsg(DBManager::instance().DirectQuery("SELECT id,shop_vid,replace(replace(name,' ','\\\\'),'#','_'),IFNULL((select sum(count) from player_gift where `from` like concat('%%#',player_shop.id) and status = 'WAIT'),0),item_count,(select count(id) from player_shop_items where shop_id=player_shop.id),DATEDIFF(date_close,now()) AS days,UNIX_TIMESTAMP(date_close) from player_shop WHERE player_id=%d", GetPlayerID()));
#else
SQLMsg * pkMsg(DBManager::instance().DirectQuery("SELECT id,shop_vid,replace(replace(name,' ','\\\\'),'#','_'),gold,item_count,(select count(id) from player_shop_items where shop_id=player_shop.id),DATEDIFF(date_close,now()) AS days,UNIX_TIMESTAMP(date_close) from player_shop WHERE player_id=%d", GetPlayerID()));
#endif
SQLResult * pRes = pkMsg->Get();
if (pRes->uiNumRows>0)
{
MYSQL_ROW row;
while ((row = mysql_fetch_row(pRes->pSQLResult)) != NULL)
{
int col = 0;
TPrivShop shop;
memset(&shop, 0, sizeof(TPrivShop));
str_to_number(shop.shop_id, row[col++]);
str_to_number(shop.shop_vid, row[col++]);
strlcpy(shop.szSign, row[col++], sizeof(shop.szSign));
str_to_number(shop.gold, row[col++]);
str_to_number(shop.item_count, row[col++]);
str_to_number(shop.rest_count, row[col++]);
str_to_number(shop.days, row[col++]);
str_to_number(shop.date_close, row[col++]);
m_mapshops.insert(std::make_pair(shop.shop_id, shop));
}
}
SendShops();
}
void CHARACTER::SendShops(bool isGm)
{
ChatPacket(CHAT_TYPE_COMMAND, "shop_clear");
PSHOP_MAP::iterator it = m_mapshops.begin();
while (it != m_mapshops.end())
{
ChatPacket(CHAT_TYPE_COMMAND, "shop_add %d %d %s %lld %d %d %d %d", it->second.shop_id, it->second.shop_vid, it->second.szSign, it->second.gold, it->second.item_count, it->second.rest_count, it->second.days, it->second.date_close);
it++;
}
}
void CHARACTER::SendShopCost()
{
extern std::map<int, TShopCost> g_ShopCosts;
ChatPacket(CHAT_TYPE_COMMAND, "shop_cost_clear");
std::map<int, TShopCost>::iterator it = g_ShopCosts.begin();
while (it != g_ShopCosts.end())
{
ChatPacket(CHAT_TYPE_COMMAND, "shop_cost %d %d %d %lld", it->first,it->second.days, it->second.time, it->second.price);
it++;
}
}
void CHARACTER::OpenShop(DWORD id, const char *name, bool onboot)
{
if (GetMyShop())
{
CloseMyShop();
return;
}
if (IsPC())
return;
char szSockets[1024] = { '\0' };
char *tempSockets = szSockets;
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
{
tempSockets += sprintf(tempSockets, "socket%d", i);
if (i<ITEM_SOCKET_MAX_NUM - 1)
tempSockets += sprintf(tempSockets, ",");
}
char szAttrs[1024] = { '\0' };
char *tempAttrs = szAttrs;
for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; i++)
{
if (i < 7)
tempAttrs += sprintf(tempAttrs, "attrtype%d,attrvalue%d", i, i);
else
tempAttrs += sprintf(tempAttrs, "applytype%d,applyvalue%d", i - 7, i - 7);
if (i<ITEM_ATTRIBUTE_MAX_NUM - 1)
tempAttrs += sprintf(tempAttrs, ",");
}
SQLMsg * pkMsg(DBManager::instance().DirectQuery("SELECT id,vnum,count,display_pos,price,%s,%s from player_shop_items where shop_id='%d'",szSockets,szAttrs, id));
SQLResult * pRes = pkMsg->Get();
BYTE bItemCount = pRes->uiNumRows;
TShopItemTable * m_pShopTable = new TShopItemTable[bItemCount];
memset(&m_pShopTable[0], 0, sizeof(TShopItemTable) * bItemCount);
std::vector<TShopItemTable *> map_shop;
if (bItemCount>0)
{
bItemCount = 0;
MYSQL_ROW row;
int c = 0;
while ((row = mysql_fetch_row(pRes->pSQLResult)) != NULL)
{
int col = 0;
TShopItemTable *shop = new TShopItemTable;
memset(shop, 0, sizeof(TShopItemTable));
DWORD id;
shop->pos.window_type = INVENTORY;
str_to_number(id, row[col++]);
str_to_number(shop->vnum, row[col++]);
str_to_number(shop->count, row[col++]);
str_to_number(shop->display_pos, row[col++]);
//col++;
str_to_number(shop->price, row[col++]);
const TItemTable * item_table = ITEM_MANAGER::instance().GetTable(shop->vnum);
if (!item_table)
{
sys_err("Shop: no item table by item vnum #%d", shop->vnum);
continue;
}
if (-1 == (shop->pos.cell = GetEmptyInventory(item_table->bSize)))
{
sys_err("no empty position in npc inventory");
return;
}
LPITEM item = ITEM_MANAGER::instance().CreateItem(shop->vnum, shop->count, 0, false, -1, true);
if (item)
{
item->ClearAttribute();
item->SetSkipSave(true);
item->SetRealID(id);
for (int s = 0;s<ITEM_SOCKET_MAX_NUM;s++)
{
DWORD soc;
str_to_number(soc, row[col++]);
item->SetSocket(s, soc, false);
}
for (int at = 0;at<ITEM_ATTRIBUTE_MAX_NUM;at++)
{
DWORD attr;
long val;
str_to_number(attr, row[col++]);
str_to_number(val, row[col++]);
item->SetForceAttribute(at, attr, val);
}
item->AddToCharacter(this, shop->pos);
}
else
{
sys_err("%d is not item", shop->vnum);
continue;
}
map_shop.push_back(shop);
++bItemCount;
}
}
if (bItemCount == 0 && !onboot || bItemCount > SHOP_HOST_ITEM_MAX_NUM)
return;
m_stShopSign = name;
if (m_stShopSign.length()>30)
m_stShopSign.resize(30);
if (m_stShopSign.length() == 0)
return;
TPacketGCShopSign p;
p.bHeader = HEADER_GC_SHOP_SIGN;
p.dwVID = GetVID();
strlcpy(p.szSign, m_stShopSign.c_str(), sizeof(p.szSign));
PacketAround(&p, sizeof(TPacketGCShopSign));
m_pkMyShop = CShopManager::instance().CreateNPCShop(this, map_shop);
}
void CHARACTER::DeleteMyShop()
{
if (GetMyShop())
{
LPCHARACTER owner = CHARACTER_MANAGER::instance().FindByPID(GetPrivShopOwner());
if(get_global_time() - GetShopEditModeTick() < 20)
{
if (owner)
{
owner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "SHOP_SUCCESS_TOO_FAST"));
}else{
TPacketShopClose packet;
packet.shop_id = GetPrivShop();
packet.pid = GetPrivShopOwner();
packet.error = true;
db_clientdesc->DBPacket(HEADER_GD_SHOP_CLOSE, 0, &packet, sizeof(packet));
}
return;
}
SQLMsg * pkMsg(DBManager::instance().DirectQuery("SELECT gold FROM player_shop where id='%d'", GetPrivShop()));
SQLResult * pRes = pkMsg->Get();
if (pRes->uiNumRows>0)
{
MYSQL_ROW row;
while ((row = mysql_fetch_row(pRes->pSQLResult)) != NULL)
{
long long gold;
str_to_number(gold, row[0]);
if (gold>0)
{
char query[1024];
sprintf(query, "INSERT INTO player_gift SET \
owner_id=%d,vnum=1,count='%s',reason=\"%s\",`from`=replace(\"%s\",' ','_'),status='WAIT',date_add=NOW()",
GetPrivShopOwner(), row[0], LC_TEXT("SHOP_REASON"), GetName());
DBManager::instance().DirectQuery(query);
}
}
GetMyShop()->GetItems();
if (owner)
{
#ifdef GIFT_SYSTEM
owner->RefreshGift();
#endif
owner->RemovePrivShopTable(GetPrivShop());
owner->SendShops();
owner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "SHOP_SUCCESS_CLOSE"));
}
else{
TPacketShopClose packet;
packet.shop_id = GetPrivShop();
packet.pid = GetPrivShopOwner();
db_clientdesc->DBPacket(HEADER_GD_SHOP_CLOSE, 0, &packet, sizeof(packet));
}
DBManager::instance().DirectQuery("delete from player_shop where id='%d'", GetPrivShop());
CloseMyShop();
}
return;
}
M2_DESTROY_CHARACTER(this);
}
EVENTFUNC(RefreshShopEvent)
{
char_event_info* info = dynamic_cast<char_event_info*>(event->info);
if (info == NULL)
{
sys_err("ishop_refresh_event> <Factor> Null pointer");
return 0;
}
LPCHARACTER ch = info->ch;
if (NULL == ch)
return 0;
ch->SendShops();
ch->SendShopCost();
if (ch->GetGiftPages()>0)
ch->ChatPacket(CHAT_TYPE_COMMAND, "gift_info %d", ch->GetGiftPages());
return PASSES_PER_SEC(10);
}
void CHARACTER::StartRefreshShopEvent()
{
if (m_pkRefreshShopEvent)
return;
char_event_info* info = AllocEventInfo<char_event_info>();
info->ch = this;
m_pkRefreshShopEvent = event_create(RefreshShopEvent, info, PASSES_PER_SEC(1)); // 1o?
}
EVENTFUNC(ShopEditModeEvent)
{
char_event_info* info = dynamic_cast<char_event_info*>(event->info);
if (info == NULL)
{
sys_err("ShopEditModeEvent> <Factor> Null pointer");
return 0;
}
LPCHARACTER ch = info->ch;
if (NULL == ch)
return 0;
if(!ch->GetMyShop() || !ch->IsPrivShop())
return 0;
if(ch->GetShopEditMode() && get_global_time() - ch->GetShopEditModeTick() > 5)
ch->SetShopEditMode(false);
return PASSES_PER_SEC(6);
}
void CHARACTER::SetShopEditMode(bool val)
{
m_bShopEditMode = val;
GetMyShop()->SetLocked(val);
if(val)
GetMyShop()->RemoveGuests(this);
else
UpdateShopItems();
DBManager::Instance().DirectQuery("UPDATE player_shop SET edit_mode=%d WHERE id=%d", val, GetPrivShop());
}
void CHARACTER::SetShopEditModeTick()
{
m_dwShopEditModeTick = get_global_time();
}
void CHARACTER::StartShopEditModeEvent()
{
if (m_pkEditShopEvent)
return;
char_event_info* info = AllocEventInfo<char_event_info>();
info->ch = this;
m_pkEditShopEvent = event_create(ShopEditModeEvent, info, PASSES_PER_SEC(1)); // 1o?
}
#endif
#ifdef ENABLE_CHANGE_CHANNEL
void CHARACTER::ChangeChannel(DWORD channelId){
long lAddr;
long lMapIndex;
WORD wPort;
long x = this->GetX();
long y = this->GetY();
if (!CMapLocation::instance().Get(x, y, lMapIndex, lAddr, wPort)){
sys_err("cannot find
map location index %d x %d y %d name %s", lMapIndex, x, y, GetName());
return;
}
if(lMapIndex >= 10000){
this->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't change channel in private
map."));
return;
}
Stop();
Save();
if(GetSectree()){
GetSectree()->RemoveEntity(this);
ViewCleanup();
EncodeRemovePacket(this);
}
TPacketGCWarp p;
p.bHeader = HEADER_GC_WARP;
p.lX = x;
p.lY = y;
p.lAddr = lAddr;
p.wPort = (wPort - 100*(g_bChannel-1) + 100*(channelId-1));
GetDesc()->Packet(&p, sizeof(TPacketGCWarp));
}
#endif
void CHARACTER::ban(char* reason2, unsigned int myid2)
{
DWORD myself = GetAID();
char * query = (char*) malloc(sizeof(*query));
snprintf(query, 1024, "UPDATE account.account SET status='BLOCK' WHERE id='%u'", myself);
SQLMsg * msg = DBManager::instance().DirectQuery(query);
if(!msg) {
sys_err("cmd_ban: MySQL Query failed!");
}
free(query);
char * query2 = (char*) malloc(sizeof(*query2));
snprintf(query2, 1024, "INSERT INTO account.ban_list (account, reason, source, date, action) VALUES('%u', '%s', '%u', NOW(), 'ban')", myself, reason2, myid2);
//const char * query2 = "INSERT INTO account.ban_list (account, reason, source) VALUES('%d', '%d', '%s')", GetAID(), myid2, reason2;
SQLMsg * msg2 = DBManager::instance().DirectQuery(query2);
if(!msg2) {
sys_err("cmd_ban: MySQL Query2 failed!");
}
free(query2);
M2_DELETE(query);
M2_DELETE(query2);
M2_DELETE(msg);
M2_DELETE(msg2);
char * resulttxt = (char*) malloc(sizeof(*query2));
snprintf(resulttxt, 1024, "%s %s", LC_TEXT("You were banned! Reason:"), reason2);
ChatPacket(CHAT_TYPE_INFO, resulttxt);
GetDesc()->DelayedDisconnect(3);
M2_DELETE(resulttxt);
}
#ifdef ENABLE_EXTEND_INVEN_SYSTEM
bool CHARACTER::Update_Inven()
{
if (Inven_Point() >= INVENTORY_LOCK_COVER_COUNT) return false;
std::vector<int> needkeys;
for (int i = INVENTORY_NEED_KEY_START; i <= (INVENTORY_LOCKED_PAGE_COUNT*INVENTORY_NEED_KEY_INCREASE)+1; i++)
for (int j = 0; j < 3; j++)
needkeys.push_back(i);
int needkey = needkeys[Inven_Point()];
int keycount = CountSpecifyItem(INVENTORY_OPEN_KEY_VNUM) + CountSpecifyItem(INVENTORY_OPEN_KEY_VNUM2);
if (keycount >= needkey) {
int willdelete = INVENTORY_START_DELETE_VNUM;
while (needkey) {
if (!CountSpecifyItem(willdelete))
willdelete = INVENTORY_START_DELETE_VNUM == INVENTORY_OPEN_KEY_VNUM ? INVENTORY_OPEN_KEY_VNUM2 : INVENTORY_OPEN_KEY_VNUM;
RemoveSpecifyItem(willdelete);
needkey--;
}
}
else {
ChatPacket(CHAT_TYPE_COMMAND, "ExInvenItemUseMsg %d", needkey - keycount);
return false;
}
PointChange(POINT_INVEN, 1, false);
return true;
}
#endif
void CHARACTER::unban(char* name)
{
char * query = (char*) malloc(sizeof(*query));
snprintf(query, 1024, "UPDATE account.account INNER JOIN player.player ON player.account_id=account.id SET status='OK' WHERE player.name='%s'", name);
//snprintf(query, 1024, "UPDATE account.account SET status='OK' WHERE id='%u'", GetAID());
SQLMsg * msg = DBManager::instance().DirectQuery(query);
if(!msg) {
sys_err("cmd_unban: MySQL Query failed!");
}
free(query);
char * query2 = (char*) malloc(sizeof(*query));
snprintf(query2, 1024, "INSERT INTO account.ban_list (account, reason, source, date, action) VALUES(0, '%s', '%u', NOW(), 'unban')", name, GetPlayerID());
//snprintf(query, 1024, "UPDATE account.account SET status='OK' WHERE id='%u'", GetAID());
SQLMsg * msg2 = DBManager::instance().DirectQuery(query2);
if(!msg2) {
sys_err("cmd_unban: MySQL Query failed!");
}
free(query2);
M2_DELETE(query2);
M2_DELETE(msg2);
M2_DELETE(query);
M2_DELETE(msg);
}
#ifdef __HIDE_COSTUME_SYSTEM__
void CHARACTER::SetBodyCostumeHidden(bool hidden)
{
m_bHideBodyCostume = hidden;
ChatPacket(CHAT_TYPE_COMMAND, "SetBodyCostumeHidden %d", m_bHideBodyCostume ? 1 : 0);
SetQuestFlag("costume_option.hide_body", m_bHideBodyCostume ? 1 : 0);
}
void CHARACTER::SetHairCostumeHidden(bool hidden)
{
m_bHideHairCostume = hidden;
ChatPacket(CHAT_TYPE_COMMAND, "SetHairCostumeHidden %d", m_bHideHairCostume ? 1 : 0);
SetQuestFlag("costume_option.hide_hair", m_bHideHairCostume ? 1 : 0);
}
#ifdef __WEAPON_COSTUME_SYSTEM__
void CHARACTER::SetWeaponCostumeHidden(bool hidden)
{
m_bHideWeaponCostume = hidden;
ChatPacket(CHAT_TYPE_COMMAND, "SetWeaponCostumeHidden %d", m_bHideWeaponCostume ? 1 : 0);
SetQuestFlag("costume_option.hide_weapon", m_bHideWeaponCostume ? 1 : 0);
}
#endif
#endif