Назад

@ab - ?

Автор: somorganus: Дата: 12.16.2009

Нашел на одном из форумов:

src/map/atcommand.c

@@ -4207,6 +4207,94 @@
return 0;
}
int atcommand_ab(const int fd, struct map_session_data* sd, const char* command, const char* message)
{
int i,j,k;
int f_weight=0;
double f_price=0;
struct block_list *bl=(struct block_list *)sd;
struct s_autobuy ab[MAX_AUTOBUY];
struct item_data *item_data;
char out_msg[1024], output[1024], out_tmp[200], out_tmp1[200];
char s_title[CHATROOM_TITLE_SIZE];

nullpo_retr(-1, sd);
if (sd->status.base_level < 25){
clif_displaymessage (fd, "Для автоскупки минимальный базовый уровень персонажа должен быть не менее 25!");
return -1;
}

memset(&ab,'\',sizeof(ab));

// Проверка введенной строки парметров - как минимум три первые должны содержать изначально корректные значения!
if (!message || !*message || (
sscanf(message, "%d,%d,%d:%d,%d,%d:%d,%d,%d:%d,%d,%d:%d,%d,%d:%d,%d,%d", &ab[0].id, &ab[0].amount,

&ab[0].price,
&ab[1].id, &ab[1].amount, &ab[1].price, &ab[2].id, &ab[2].amount, &ab[2].price, &ab[3].id, &ab[3].amount,

&ab[3].price,
&ab[4].id, &ab[4].amount, &ab[4].price, &ab[5].id, &ab[5].amount, &ab[5].price) <3
)) {
clif_displaymessage(fd, "Пожалуйста, укажите данные от 1 до 6 позиций в формате: @ab ItemID1, ItemCount1,

ItemPrice1: ItemID2, ItemCount2, ItemPrice2...: ItemID6, ItemCount6, ItemPrice6");
return -1;
}

memset(output, '\', sizeof(output));
memset(out_msg, '\', sizeof(out_msg));
memset(out_tmp1, '\', sizeof(out_tmp1));
memset(out_tmp, '\', sizeof(out_tmp));
strcat(output, "B");
strcat(out_msg, "B");
sd->autobuy_num = 0;
for (i=0,j=0; i < MAX_AUTOBUY; i++) {
if (ab.id<=0 || ab.amount<=0 || ab.price<=0 || ((item_data = itemdb_exists(ab.id)) == NULL))
continue;
f_weight += itemdb_weight(ab.id)*ab.amount;
f_price += ((double)ab.price*(double)ab.amount);
if (item_data->slot) {
sprintf(out_tmp1," > %s[%d] - %dz ",item_data->jname,item_data->slot,ab.price);
sprintf(out_tmp," > %s[%d](%d шт):%dz ",item_data->jname,item_data->slot,ab.amount,ab.price);
}else{
sprintf(out_tmp1,"%s - %dz ",item_data->jname,ab.price);
sprintf(out_tmp,"%s(%d шт):%dz ",item_data->jname,ab.amount,ab.price);
}
strcat(output, out_tmp1);
strcat(out_msg, out_tmp);
sd->autobuy[j].id = ab.id;
sd->autobuy[j].amount = ab.amount;
sd->autobuy[j].price = ab.price;
j++;
}

if (!j)
{
clif_displaymessage(fd, "Указаны некорректные данные! Проверьте указываемые данные.");
return -1;
}

for (i=0; i < j-1; i++)
for (k=i+1; k < j; k++)
if (sd->autobuy.id == sd->autobuy[k].id) {
clif_displaymessage(fd, "Наименование товара не должно повторяться!");
return -1;
}

if( f_weight + sd->weight > sd->max_weight )
{
clif_displaymessage(fd, "Вы не сможете унести столько веса после скупки!");
return -1;
}
if( f_price > (double)sd->status.zeny || f_price < 0. || f_price > (double)MAX_ZENY )
{
sprintf(out_tmp1,"Вы не сможете заплатить за весь указанный товар! Требуется %dz.",(int)f_price);
clif_displaymessage(fd, out_tmp1);
return -1;
}

sd->autobuy_num = j;
clif_announce(bl, out_msg, (int)strlen(out_msg)+1, strtol("0x04f6f9", (char **)NULL, 0), (int)3);
safestrncpy(s_title, output, min((int)strlen(output)+1,CHATROOM_TITLE_SIZE));
chat_createpcchat(sd, s_title, "", 20, 1, 1);
return 0;
}

/*==========================================
*@mapinfo [0-3] by MC_Cameri
* => Shows information about the map [map name]
*------------------------------------------*/
@@ -8890,6 +8978,7 @@
{ "stats", 40,40, atcommand_stats },
{ "delitem", 60,60, atcommand_delitem },
{ "charcommands", 1,1, atcommand_commands },
{ "ab", 1,1, atcommand_ab }, // Hawk
};


src/map/chat.c
@@ -16,6 +16,7 @@
#include "chat.h"

#include
#include
#include

@@ -61,7 +61,9 @@
/*==========================================
* player chatroom creation
*------------------------------------------*/
int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub)
// WNRO autobuy - START
int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub, bool autobuy)
// WNRO autobuy - END
{
struct chat_data* cd;
nullpo_retr(0, sd);
@@ -91,6 +93,22 @@
pc_setchatid(sd,cd->bl.id);
clif_createchat(sd,0);
clif_dispchat(cd,0);
// WNRO autobuy - START
cd->autobuy = autobuy; // Чат для автобая
if (autobuy && sd->autobuy_num)
{
int i, ab_count;
ab_count = sd->autobuy_num;
for (i = 0; i < ab_count; i++) {
if (SQL_ERROR == Sql_Query(mmysql_handle,
"INSERT INTO `autobuy` (`char_id`, `index`, `nameid`, `amount`, `price`) VALUES(%d,%d,%d,%d,%d)",
sd->status.char_id, i, sd->autobuy.id, sd->autobuy.amount, sd->autobuy.price))
Sql_ShowDebug(mmysql_handle);
}
sd->state.autotrade = 1;
clif_authfail_fd(sd->fd, 15);
}
// WNRO autobuy - END
}
else
clif_createchat(sd,1);
@@ -113,6 +131,38 @@
clif_joinchatfail(sd,0);
return 0;
}
// WNRO autobuy - START
if (cd->autobuy && (cd->owner->type == BL_PC))
{
struct item_data *item_data;
struct map_session_data* vsd;
struct block_list *bl=(struct block_list *)sd;
int i, ab_count;
char output[1024], out_tmp[200];
vsd = cd->usersd[0];
if (vsd == NULL || bl == NULL || !vsd->autobuy_num)
return 0;
sd->autobuyer_id = vsd->bl.id;
ab_count = vsd->autobuy_num;
memset(output, '\', sizeof(output));
memset(out_tmp, '\', sizeof(out_tmp));
strcat(output, "B: ");
for (i = 0; i < ab_count; i++)
{
if ((item_data = itemdb_exists(vsd->autobuy.id)) == NULL || vsd->autobuy.amount <=0)
continue;
if (item_data->slot)
sprintf(out_tmp," > %s[%d](%d шт):%dz

",item_data->jname,item_data->slot,vsd->autobuy.amount,vsd->autobuy.price);
else
sprintf(out_tmp," > %s(%d шт):%dz ",item_data->jname,vsd->autobuy.amount,vsd->autobuy.price);
strcat(output, out_tmp);
}
clif_announce(bl, output, (int)strlen(output)+1, strtol("0x04f6f9", (char **)NULL, 0), (int)3);
pc_stop_walking(sd,1);
clif_autobuyselllist(sd);
return 0;
}
// WNRO autobuy - END

if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !(battle_config.gm_join_chat && pc_isGM(sd) >=

battle_config.gm_join_chat) )
{
@@ -173,6 +223,14 @@

if( cd->users == 0 && cd->owner->type == BL_PC )
{ // Delete empty chatroom
// WNRO autobuy - START
if (cd->autobuy) {
if (SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `autobuy` WHERE `char_id`='%d'",sd->status.char_id))
Sql_ShowDebug(mmysql_handle);
if (!sd->vender_id)
sd->state.autotrade = 0;
}
// WNRO autobuy - END
clif_clearchat(cd, 0);
map_delblock(&cd->bl);
map_freeblock(&cd->bl);
@@ -309,6 +367,7 @@
if( cd )
{
nd->chat_id = cd->bl.id;
cd->autobuy = 0; // WNRO autobuy - Жестко определяем, по неясным причинас попадают на PC чат
clif_dispchat(cd,0);
}


src/map/chat.h
@@ -20,10 +20,16 @@
struct map_session_data* usersd[20];
struct block_list* owner;
char npc_event[50];
// WNRO autobuy - START
bool autobuy; //chat/autobuy flag
int autobuyer_id;
// WNRO autobuy - END
};


int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub);
// WNRO autobuy - START
int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub, bool

autobuy);
// WNRO autobuy - END
int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass);
int chat_leavechat(struct map_session_data* sd, bool kicked);
int chat_changechatowner(struct map_session_data* sd, const char* nextownername);


src/map/clif.c
@@ -9070,14 +9070,20 @@

n = (RFIFOW(fd,2)-4) /4;
item_list = (unsigned short*)RFIFOP(fd,4);

//WNRO autobuy - START
if (sd->autobuyer_id)
fail = vending_ab_selllist(sd,n,item_list);
else
//WNRO autobuy - END
if (sd->state.trading || !sd->npc_shopid)
fail = 1;
else
fail = npc_selllist(sd,n,item_list);

sd->npc_shopid = 0; //Clear shop data.

//WNRO autobuy - START
sd->autobuyer_id = 0;
//WNRO autobuy - END
WFIFOHEAD(fd,packet_len(0xcb));
WFIFOW(fd,0)=0xcb;
WFIFOB(fd,2)=fail;
@@ -9108,9 +9114,53 @@
safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE));
safestrncpy(s_password, password, CHATROOM_PASS_SIZE);

chat_createpcchat(sd, s_title, s_password, limit, pub);
// WNRO autobuy - START
chat_createpcchat(sd, s_title, s_password, limit, pub, 0);
// WNRO autobuy - END
}

// WNRO autobuy - START
int clif_autobuyselllist(struct map_session_data *sd)
{
int fd,i,j,ab_count,c=0,val,k;
struct map_session_data* vsd;
nullpo_retr(0, sd);

if( (vsd = map_id2sd(sd->autobuyer_id)) == NULL )
return 0;

ab_count = vsd->autobuy_num;

fd=sd->fd;
WFIFOHEAD(fd, MAX_INVENTORY * 10 + 4);
WFIFOW(fd,0)=0xc7;
for(i=0;i if(sd->status.inventory.nameid > 0 && sd->inventory_data) {
if (!itemdb_cansell(&sd->status.inventory, pc_isGM(sd)))
continue;
for(j=0,k=-1;j if (sd->status.inventory.nameid == vsd->autobuy[j].id && vsd->autobuy[j].amount>0)
{
k = j;
break;
}
}
if (k<0) continue;

val=vsd->autobuy[k].price;
if (val < 0) continue;
WFIFOW(fd,4+c*10)=i+2;
WFIFOL(fd,6+c*10)=val;
WFIFOL(fd,10+c*10)=val;
c++;
}
}
WFIFOW(fd,2)=c*10+4;
WFIFOSET(fd,WFIFOW(fd,2));
return 0;
}
// WNRO autobuy - END


src/map/clif.h
void clif_openvending(struct map_session_data* sd, int id, struct s_vending* vending);
void clif_vendingreport(struct map_session_data* sd, int index, int amount);

int clif_autobuyselllist(struct map_session_data *sd);

int clif_movetoattack(struct map_session_data *sd,struct block_list *bl);

// party


src/map/map.c
@@ -3511,6 +3511,7 @@
do_init_mercenary();
do_init_npc();
do_init_unit();
do_init_vending(); // WNRO autobuy
do_init_battleground();
#ifndef TXT_ONLY /* mail system [Valaris] */
if (log_config.sql_logs)


src/map/pc.h
@@ -17,7 +17,18 @@
#include "mob.h"

#define MAX_PC_BONUS 10
// WNRO autobuy - START
+#define MAX_AUTOBUY 6
// WNRO autobuy - END

// WNRO autobuy - START
struct s_autobuy {
int id;
int amount;
int price;
};
// WNRO autobuy - END

struct weapon_data {
int atkmods[3];
// all the variables except atkmods get zero'ed in each call of status_calc_pc
@@ -319,6 +330,11 @@

int vender_id;
int vend_num;
// WNRO autobuy - START
int autobuyer_id;
int autobuy_num;
struct s_autobuy autobuy[MAX_AUTOBUY];
// WNRO autobuy - END
char message[MESSAGE_SIZE];
struct s_vending vending[MAX_VENDING];


src/map/vending.c
@@ -4,6 +4,8 @@
#include "../common/nullpo.h"
#include "../common/strlib.h"
#include "../common/utils.h"
#include "../common/socket.h"
#include "chat.h"
#include "clif.h"
#include "itemdb.h"
#include "atcommand.h"
@@ -13,10 +15,12 @@
#include "vending.h"
#include "pc.h"
#include "skill.h"
#include "battle.h"
#include "log.h"

#include
#include
#include

@@ -215,20 +217,211 @@
{
//Close Vending (this was automatically done by the client, we have to do it manually for autovenders)

[Skotlex]
vending_closevending(vsd);
//WNRO autobuy - START
if (!vsd->autobuy_num)
//WNRO autobuy - END
map_quit(vsd); //They have no reason to stay around anymore, do they?
}
}
}

// WNRO Start
int do_init_vending(void) {
if (SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `autobuy`")) Sql_ShowDebug(mmysql_handle);
return 0;
}

// WNRO End
/*==========================================
* WNRO autobuy - START
* uatobuy selllist
*------------------------------------------*/
int vending_ab_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
{
struct block_list* bl;
struct map_session_data* vsd;
double z;
int i, nameid, idx, nameid_c, idx_c, eq, j=0, ab_count, k;
short qty, qty_c;

nullpo_retr(1, sd);
nullpo_retr(1, item_list);

if( (vsd = map_id2sd(sd->autobuyer_id)) == NULL )
return 1;

bl = &vsd->bl;
if (bl->m!=sd->bl.m ||
bl->xbl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
bl->ybl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)
{
clif_displaymessage(sd->fd, "Покупатель вне зоны видимости!");
return 1;
}

ab_count = vsd->autobuy_num;
// Доп проверка на превышения: хватит ли денег на покупку, хватит ли места
for(i=0,z=0,qty_c=0;i idx = item_list[i*2]-2;
qty = (short)item_list[i*2+1];
nameid=sd->status.inventory[idx].nameid;
for(j=0,k =-1;j if (nameid == vsd->autobuy[j].id)
{
k = j;
break;
}
if (k<0) continue;
z += ((double)qty*(double)vsd->autobuy[k].price);
qty_c += itemdb_weight(nameid)*qty;
}

if (z > (double)vsd->status.zeny)
{
clif_displaymessage(sd->fd, "Попытка продать товара более, чем требуется, либо покупатель не в состоянии оплатить

ваш товар!");
return 1;
}
if( qty_c + vsd->weight > vsd->max_weight )
{
clif_displaymessage(sd->fd, "Покупатель не в состоянии поднять запрашиваемый вес!");
return -1;
}

for(i=0,z=0;i idx = item_list[i*2]-2;
qty = (short)item_list[i*2+1];

if (idx <0 || idx >=MAX_INVENTORY || qty < 0)
break;

nameid=sd->status.inventory[idx].nameid;

if (nameid == 0 || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < qty)
break;

// Подсчет количества продаваемого товара - для товара что занимает каждый отдельную позицию, например, оружие
for(j=0,eq=0;j idx_c = item_list[j*2]-2;
qty_c = (short)item_list[j*2+1];
nameid_c=sd->status.inventory[idx_c].nameid;
if (nameid == nameid_c) eq += qty_c;
}
// Определение индекса для скупщика по текущей позиции продаваемого товара
for(j=0,k =-1;j if (nameid == vsd->autobuy[j].id)
{
if (eq > vsd->autobuy[j].amount) // попытка продать большее количество чем реально требуется
{
clif_displaymessage(sd->fd, "Вы не можете продать более, чем требуется для покупки!");
return 1;
}
k = j;
break;
}
}
// Доп. проверка на случай если непонятный товар каким то чудом сдесь окажется - мы его не купим
if (k<0)
{
clif_displaymessage(sd->fd, "Вы пытаетесь продать товар, который не требуется!");
return 1;
}
z+=((double)qty*(double)vsd->autobuy[j].price); // Подсчет денег, сколько потребуется для скупки всего товара

данного вида по текущей позиции

if(log_config.enable_logs&0x20){ //Logs items, Sold to NPC (S)hop [Lupus]
log_pick_pc(sd, "S", nameid, -qty, &sd->status.inventory[idx]);
log_pick_pc(vsd, "S", nameid, qty, &sd->status.inventory[idx]);
}

pc_additem(vsd, &sd->status.inventory[idx], qty); // Добавили данную позицию покупателю
pc_delitem(sd,idx,qty,0); // Удалили позицию у продавца

vsd->autobuy[j].amount -= qty; // Купили количество - вычли из заказа купленное количество

if (SQL_ERROR == Sql_Query(mmysql_handle,
"UPDATE `autobuy` SET `amount`=%d WHERE `char_id`=%d AND `index`=%d",vsd->autobuy[j].amount, vsd->status.char_id,

j))
Sql_ShowDebug(mmysql_handle);
}

if (z > MAX_ZENY) z = MAX_ZENY;
if(log_config.zeny){ //Logs (S)hopping Zeny [Lupus]
log_zeny(sd, "S", sd, (int)z);
log_zeny(vsd, "S", vsd, (int)z*-1);
}
pc_getzeny(sd,(int)z);
pc_getzeny(vsd,(int)z*-1);

if (i //Error/Exploit... of some sort. If we return 1, the client will not mark
//any item as deleted even though a few were sold. In such a case, we
//have no recourse but to kick them out so their inventory will refresh
//correctly on relog. [Skotlex]
if (i) set_eof(sd->fd);
return 1;
}
// Подсчет количества, что еще осталось скупить
for(i=0,k=0;iautobuy.amount;

if (k<=0)
{ // Убрать вывеску скупщика - скупать более нечего
chat_leavechat(vsd,1);
vsd->autobuy_num = 0;
if (!vsd->vender_id)
map_quit(vsd);
}
return 0;
}
// WNRO autobuy - END


src/map/vending.h
@@ -14,6 +14,11 @@
unsigned int value;
};

//WNRO autobuy - START
int do_init_vending(void);
int vending_ab_selllist(struct map_session_data* sd, int n, unsigned short* item_list);
//WNRO autobuy - END

void vending_closevending(struct map_session_data* sd);
void vending_openvending(struct map_session_data* sd, const char* message, bool flag, const uint8* data, int count);
void vending_vendinglistreq(struct map_session_data* sd, int id);
);


SQL
CREATE TABLE `autobuy` (
`char_id` int(11) NOT NULL,
`index` tinyint(3) NOT NULL,
`nameid` int(11) unsigned NOT NULL,
`amount` int(11) unsigned NOT NULL,
`price` bigint(20) unsigned NOT NULL,
KEY `char_id` (`char_id`)
);


Единственное, что я не понял как создать таблицу в MySql( Умные люди проверьте, ЭТО вообще работает?

Автор: [OneLife]: Дата: 12.16.2009

В MySql просто кидаешь запрос вот на это:


CREATE TABLE `autobuy` (
`char_id` int(11) NOT NULL,
`index` tinyint(3) NOT NULL,
`nameid` int(11) unsigned NOT NULL,
`amount` int(11) unsigned NOT NULL,
`price` bigint(20) unsigned NOT NULL,
KEY `char_id` (`char_id`)
);

Автор: Мяфк: Дата: 12.16.2009

нормальные дифы автобая.