- Rewrote/cleaned up trade.c for a more clean trading implementation.
- Added @request commands, sends a request to all connected GMs of lowest_gm_level or above as a whisper message. Defaults to gm level 20 users. - Made SC_COMBO status start delay attackabletime and walkdelay by sc's duration regardless of skill used (previously it was only for TK kicks, now it's for both those and Monk combos) git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@6542 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
0b8b0ffa96
commit
e2eadf7bb2
@ -4,6 +4,11 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
|
|||||||
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
|
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
|
||||||
|
|
||||||
2006/05/09
|
2006/05/09
|
||||||
|
* Rewrote/cleaned up trade.c for a more clean trading implementation.
|
||||||
|
[Skotlex]
|
||||||
|
* Added @request commands, sends a request to all connected GMs of
|
||||||
|
lowest_gm_level or above as a whisper message. Defaults to gm level 20
|
||||||
|
users (UNTESTED). [Skotlex]
|
||||||
* Modified @commands to use Meruru's code which is faster and does a fair
|
* Modified @commands to use Meruru's code which is faster and does a fair
|
||||||
attempt at tabulating the commands presented. [Skotlex]
|
attempt at tabulating the commands presented. [Skotlex]
|
||||||
* Updated SKA to return a random value between 0 and 99 each time
|
* Updated SKA to return a random value between 0 and 99 each time
|
||||||
|
@ -181,6 +181,9 @@ gmotd: 20
|
|||||||
// follow a player (including warping to them)
|
// follow a player (including warping to them)
|
||||||
follow: 20
|
follow: 20
|
||||||
|
|
||||||
|
// Sends a request to all connected GMs (via the gm whisper system)
|
||||||
|
request: 20
|
||||||
|
|
||||||
// Disconnects a user from the server (1 command + right click menu for GM "(name) force to quit").
|
// Disconnects a user from the server (1 command + right click menu for GM "(name) force to quit").
|
||||||
kick: 20
|
kick: 20
|
||||||
|
|
||||||
|
@ -284,7 +284,9 @@
|
|||||||
272: You can't trade on this map
|
272: You can't trade on this map
|
||||||
273: Commands available:
|
273: Commands available:
|
||||||
274: %d commands found.
|
274: %d commands found.
|
||||||
275: No commands found.
|
275: Usage: @request <petition/message to online GMs>.
|
||||||
|
276: (@request): %s
|
||||||
|
277: @request sent.
|
||||||
// Guild Castles Number
|
// Guild Castles Number
|
||||||
// --------------------
|
// --------------------
|
||||||
299: ?? Castles
|
299: ?? Castles
|
||||||
|
@ -295,6 +295,7 @@ ACMD_FUNC(clone); // [Valaris]
|
|||||||
ACMD_FUNC(tonpc); // LuzZza
|
ACMD_FUNC(tonpc); // LuzZza
|
||||||
ACMD_FUNC(commands); // [Skotlex]
|
ACMD_FUNC(commands); // [Skotlex]
|
||||||
ACMD_FUNC(noask); //LuzZza
|
ACMD_FUNC(noask); //LuzZza
|
||||||
|
ACMD_FUNC(request); //LuzZza
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
*AtCommandInfo atcommand_info[]<EFBFBD>\‘¢‘̂̒è‹`
|
*AtCommandInfo atcommand_info[]<EFBFBD>\‘¢‘̂̒è‹`
|
||||||
@ -611,6 +612,7 @@ static AtCommandInfo atcommand_info[] = {
|
|||||||
{ AtCommand_ToNPC, "@tonpc", 40, atcommand_tonpc }, // LuzZza
|
{ AtCommand_ToNPC, "@tonpc", 40, atcommand_tonpc }, // LuzZza
|
||||||
{ AtCommand_Commands, "@commands", 1, atcommand_commands }, // [Skotlex]
|
{ AtCommand_Commands, "@commands", 1, atcommand_commands }, // [Skotlex]
|
||||||
{ AtCommand_NoAsk, "@noask", 1, atcommand_noask }, // [LuzZza]
|
{ AtCommand_NoAsk, "@noask", 1, atcommand_noask }, // [LuzZza]
|
||||||
|
{ AtCommand_Request, "@request", 20, atcommand_request }, // [LuzZza]
|
||||||
|
|
||||||
// add new commands before this line
|
// add new commands before this line
|
||||||
{ AtCommand_Unknown, NULL, 1, NULL }
|
{ AtCommand_Unknown, NULL, 1, NULL }
|
||||||
@ -10273,6 +10275,27 @@ int atcommand_noask(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*=====================================
|
||||||
|
* Send a @request message to all GMs of lowest_gm_level.
|
||||||
|
* Usage: @request <petition>
|
||||||
|
*-------------------------------------
|
||||||
|
*/
|
||||||
|
int atcommand_request(
|
||||||
|
const int fd, struct map_session_data* sd,
|
||||||
|
const char* command, const char* message)
|
||||||
|
{
|
||||||
|
if (!message || !*message) {
|
||||||
|
clif_displaymessage(sd->fd,msg_txt(275));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(atcmd_output, msg_txt(276), message);
|
||||||
|
intif_wis_message_to_gm(sd->status.name, lowest_gm_level, atcmd_output);
|
||||||
|
clif_disp_onlyself(sd, atcmd_output, strlen(atcmd_output));
|
||||||
|
clif_displaymessage(sd->fd,msg_txt(277));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void do_init_atcommand() {
|
void do_init_atcommand() {
|
||||||
users_db = db_alloc(__FILE__,__LINE__,DB_UINT,DB_OPT_BASE,sizeof(int));
|
users_db = db_alloc(__FILE__,__LINE__,DB_UINT,DB_OPT_BASE,sizeof(int));
|
||||||
duel_count = 0;
|
duel_count = 0;
|
||||||
|
@ -270,7 +270,7 @@ enum AtCommandType {
|
|||||||
AtCommand_ToNPC, // LuzZza
|
AtCommand_ToNPC, // LuzZza
|
||||||
AtCommand_Commands, // [Skotlex]
|
AtCommand_Commands, // [Skotlex]
|
||||||
AtCommand_NoAsk, // [LuzZza]
|
AtCommand_NoAsk, // [LuzZza]
|
||||||
|
AtCommand_Request, // [Skotlex], supposedly taken from Freya (heard the command was there, but I haven't seen the code yet)
|
||||||
// end <- Ahem, guys, don't place AtCommands after AtCommand_Unknown! [Skotlex]
|
// end <- Ahem, guys, don't place AtCommands after AtCommand_Unknown! [Skotlex]
|
||||||
AtCommand_Unknown,
|
AtCommand_Unknown,
|
||||||
AtCommand_MAX
|
AtCommand_MAX
|
||||||
|
@ -1821,8 +1821,6 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
|
|||||||
pc_checkskill(sd, MO_CHAINCOMBO) > 0)
|
pc_checkskill(sd, MO_CHAINCOMBO) > 0)
|
||||||
delay += 300 * battle_config.combo_delay_rate / 100;
|
delay += 300 * battle_config.combo_delay_rate / 100;
|
||||||
sc_start4(src,SC_COMBO,100,MO_TRIPLEATTACK,skilllv,0,0,delay);
|
sc_start4(src,SC_COMBO,100,MO_TRIPLEATTACK,skilllv,0,0,delay);
|
||||||
sd->ud.attackabletime = tick + delay;
|
|
||||||
unit_set_walkdelay(src, tick, delay, 1);
|
|
||||||
clif_combo_delay(src, delay);
|
clif_combo_delay(src, delay);
|
||||||
|
|
||||||
if (sd->status.party_id>0) //bonus from SG_FRIEND [Komurka]
|
if (sd->status.party_id>0) //bonus from SG_FRIEND [Komurka]
|
||||||
@ -1836,8 +1834,6 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
|
|||||||
(pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0))
|
(pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0))
|
||||||
delay += 300 * battle_config.combo_delay_rate /100;
|
delay += 300 * battle_config.combo_delay_rate /100;
|
||||||
sc_start4(src,SC_COMBO,100,MO_CHAINCOMBO,skilllv,0,0,delay);
|
sc_start4(src,SC_COMBO,100,MO_CHAINCOMBO,skilllv,0,0,delay);
|
||||||
sd->ud.attackabletime = tick + delay;
|
|
||||||
unit_set_walkdelay(src, tick, delay, 1);
|
|
||||||
clif_combo_delay(src,delay);
|
clif_combo_delay(src,delay);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1852,8 +1848,6 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
|
|||||||
))
|
))
|
||||||
delay += 300 * battle_config.combo_delay_rate /100;
|
delay += 300 * battle_config.combo_delay_rate /100;
|
||||||
sc_start4(src,SC_COMBO,100,MO_COMBOFINISH,skilllv,0,0,delay);
|
sc_start4(src,SC_COMBO,100,MO_COMBOFINISH,skilllv,0,0,delay);
|
||||||
sd->ud.attackabletime = tick + delay;
|
|
||||||
unit_set_walkdelay(src, tick, delay, 1);
|
|
||||||
clif_combo_delay(src,delay);
|
clif_combo_delay(src,delay);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1867,8 +1861,6 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
|
|||||||
))
|
))
|
||||||
delay += 300 * battle_config.combo_delay_rate /100;
|
delay += 300 * battle_config.combo_delay_rate /100;
|
||||||
sc_start4(src,SC_COMBO,100,CH_TIGERFIST,skilllv,0,0,delay);
|
sc_start4(src,SC_COMBO,100,CH_TIGERFIST,skilllv,0,0,delay);
|
||||||
sd->ud.attackabletime = tick + delay;
|
|
||||||
unit_set_walkdelay(src, tick, delay, 1);
|
|
||||||
clif_combo_delay(src,delay);
|
clif_combo_delay(src,delay);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1878,8 +1870,6 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
|
|||||||
if(damage < status_get_hp(bl))
|
if(damage < status_get_hp(bl))
|
||||||
delay += 300 * battle_config.combo_delay_rate /100;
|
delay += 300 * battle_config.combo_delay_rate /100;
|
||||||
sc_start4(src,SC_COMBO,100,CH_CHAINCRUSH,skilllv,0,0,delay);
|
sc_start4(src,SC_COMBO,100,CH_CHAINCRUSH,skilllv,0,0,delay);
|
||||||
sd->ud.attackabletime = tick + delay;
|
|
||||||
unit_set_walkdelay(src, tick, delay, 1);
|
|
||||||
clif_combo_delay(src,delay);
|
clif_combo_delay(src,delay);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4452,21 +4452,21 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
|
|||||||
switch (val1) { //Val1 contains the skill id
|
switch (val1) { //Val1 contains the skill id
|
||||||
case TK_STORMKICK:
|
case TK_STORMKICK:
|
||||||
clif_skill_nodamage(bl,bl,TK_READYSTORM,1,1);
|
clif_skill_nodamage(bl,bl,TK_READYSTORM,1,1);
|
||||||
if (ud) ud->attackabletime = gettick()+tick;
|
|
||||||
break;
|
break;
|
||||||
case TK_DOWNKICK:
|
case TK_DOWNKICK:
|
||||||
clif_skill_nodamage(bl,bl,TK_READYDOWN,1,1);
|
clif_skill_nodamage(bl,bl,TK_READYDOWN,1,1);
|
||||||
if (ud) ud->attackabletime = gettick()+tick;
|
|
||||||
break;
|
break;
|
||||||
case TK_TURNKICK:
|
case TK_TURNKICK:
|
||||||
clif_skill_nodamage(bl,bl,TK_READYTURN,1,1);
|
clif_skill_nodamage(bl,bl,TK_READYTURN,1,1);
|
||||||
if (ud) ud->attackabletime = gettick()+tick;
|
|
||||||
break;
|
break;
|
||||||
case TK_COUNTER:
|
case TK_COUNTER:
|
||||||
clif_skill_nodamage(bl,bl,TK_READYCOUNTER,1,1);
|
clif_skill_nodamage(bl,bl,TK_READYCOUNTER,1,1);
|
||||||
if (ud) ud->attackabletime = gettick()+tick;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (ud) {
|
||||||
|
ud->attackabletime = gettick()+tick;
|
||||||
|
unit_set_walkdelay(bl, gettick(), tick, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SC_TKREST:
|
case SC_TKREST:
|
||||||
|
653
src/map/trade.c
653
src/map/trade.c
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
* 取引要請を相手に送る
|
* Initiates a trade request.
|
||||||
*------------------------------------------
|
*------------------------------------------
|
||||||
*/
|
*/
|
||||||
void trade_traderequest(struct map_session_data *sd, int target_id) {
|
void trade_traderequest(struct map_session_data *sd, int target_id) {
|
||||||
@ -34,73 +34,89 @@ void trade_traderequest(struct map_session_data *sd, int target_id) {
|
|||||||
return; //Can't trade in notrade mapflag maps.
|
return; //Can't trade in notrade mapflag maps.
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((target_sd = map_id2sd(target_id)) != NULL) {
|
if ((target_sd = map_id2sd(target_id)) == NULL || sd == target_sd) {
|
||||||
if (!battle_config.invite_request_check) {
|
|
||||||
if (target_sd->guild_invite > 0 || target_sd->party_invite > 0) {
|
|
||||||
clif_tradestart(sd, 2); // 相手はPT要請中かGuild要請中
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
level = pc_isGM(sd);
|
|
||||||
if ( pc_can_give_items(level) || pc_can_give_items(pc_isGM(target_sd)) ) //check if both GMs are allowed to trade
|
|
||||||
{
|
|
||||||
clif_displaymessage(sd->fd, msg_txt(246));
|
|
||||||
trade_tradecancel(sd); // GM is not allowed to trade
|
|
||||||
} else if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0)) {
|
|
||||||
trade_tradecancel(sd); // person is in another trade
|
|
||||||
} else {
|
|
||||||
//Fixed. Only real GMs can request trade from far away! [Lupus]
|
|
||||||
if (level < lowest_gm_level && (sd->bl.m != target_sd->bl.m ||
|
|
||||||
(sd->bl.x - target_sd->bl.x <= -5 || sd->bl.x - target_sd->bl.x >= 5) ||
|
|
||||||
(sd->bl.y - target_sd->bl.y <= -5 || sd->bl.y - target_sd->bl.y >= 5))) {
|
|
||||||
clif_tradestart(sd, 0); // too far
|
|
||||||
} else if (sd != target_sd) {
|
|
||||||
target_sd->trade_partner = sd->status.account_id;
|
|
||||||
sd->trade_partner = target_sd->status.account_id;
|
|
||||||
clif_traderequest(target_sd, sd->status.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
clif_tradestart(sd, 1); // character does not exist
|
clif_tradestart(sd, 1); // character does not exist
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!battle_config.invite_request_check) {
|
||||||
|
if (target_sd->guild_invite > 0 || target_sd->party_invite > 0) {
|
||||||
|
clif_tradestart(sd, 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0)) {
|
||||||
|
trade_tradecancel(sd); // person is in another trade
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
level = pc_isGM(sd);
|
||||||
|
if ( pc_can_give_items(level) || pc_can_give_items(pc_isGM(target_sd)) ) //check if both GMs are allowed to trade
|
||||||
|
{
|
||||||
|
clif_displaymessage(sd->fd, msg_txt(246));
|
||||||
|
trade_tradecancel(sd); // GM is not allowed to trade
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fixed. Only real GMs can request trade from far away! [Lupus]
|
||||||
|
if (level < lowest_gm_level && (sd->bl.m != target_sd->bl.m ||
|
||||||
|
(sd->bl.x - target_sd->bl.x <= -5 || sd->bl.x - target_sd->bl.x >= 5) ||
|
||||||
|
(sd->bl.y - target_sd->bl.y <= -5 || sd->bl.y - target_sd->bl.y >= 5))) {
|
||||||
|
clif_tradestart(sd, 0); // too far
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_sd->trade_partner = sd->status.account_id;
|
||||||
|
sd->trade_partner = target_sd->status.account_id;
|
||||||
|
clif_traderequest(target_sd, sd->status.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
* 取引要請
|
* Reply to a trade-request.
|
||||||
*------------------------------------------
|
*------------------------------------------
|
||||||
*/
|
*/
|
||||||
void trade_tradeack(struct map_session_data *sd, int type) {
|
void trade_tradeack(struct map_session_data *sd, int type) {
|
||||||
struct map_session_data *target_sd;
|
struct map_session_data *target_sd;
|
||||||
nullpo_retv(sd);
|
nullpo_retv(sd);
|
||||||
|
|
||||||
if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) {
|
if (sd->state.trading || !sd->trade_partner)
|
||||||
clif_tradestart(target_sd, type);
|
return; //Already trading or no partner set.
|
||||||
clif_tradestart(sd, type);
|
|
||||||
if (type == 4) { // Cancel
|
|
||||||
sd->state.deal_locked = 0;
|
|
||||||
sd->trade_partner = 0;
|
|
||||||
target_sd->state.deal_locked = 0;
|
|
||||||
target_sd->trade_partner = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == 3) { //Initiate trade
|
if ((target_sd = map_id2sd(sd->trade_partner)) == NULL) {
|
||||||
sd->state.trading = 1;
|
sd->trade_partner=0;
|
||||||
target_sd->state.trading = 1;
|
return;
|
||||||
memset(&sd->deal, 0, sizeof(sd->deal));
|
|
||||||
memset(&target_sd->deal, 0, sizeof(target_sd->deal));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sd->npc_id != 0)
|
|
||||||
npc_event_dequeue(sd);
|
|
||||||
if (target_sd->npc_id != 0)
|
|
||||||
npc_event_dequeue(target_sd);
|
|
||||||
|
|
||||||
//close STORAGE window if it's open. It protects from spooffing packets [Lupus]
|
|
||||||
if (sd->state.storage_flag == 1)
|
|
||||||
storage_storageclose(sd);
|
|
||||||
else if (sd->state.storage_flag == 2)
|
|
||||||
storage_guild_storageclose(sd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clif_tradestart(target_sd, type);
|
||||||
|
clif_tradestart(sd, type);
|
||||||
|
if (type == 4) { // Cancel
|
||||||
|
sd->state.deal_locked = 0;
|
||||||
|
sd->trade_partner = 0;
|
||||||
|
target_sd->state.deal_locked = 0;
|
||||||
|
target_sd->trade_partner = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == 3) { //Initiate trade
|
||||||
|
sd->state.trading = 1;
|
||||||
|
target_sd->state.trading = 1;
|
||||||
|
memset(&sd->deal, 0, sizeof(sd->deal));
|
||||||
|
memset(&target_sd->deal, 0, sizeof(target_sd->deal));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sd->npc_id)
|
||||||
|
npc_event_dequeue(sd);
|
||||||
|
if (target_sd->npc_id)
|
||||||
|
npc_event_dequeue(target_sd);
|
||||||
|
|
||||||
|
/* Why? It should be allowed to bring items from storage to inventory for trading, but not the other way around
|
||||||
|
* (this is blocked on clif.c) [Skotlex]
|
||||||
|
//close STORAGE window if it's open. It protects from spooffing packets [Lupus]
|
||||||
|
if (sd->state.storage_flag == 1)
|
||||||
|
storage_storageclose(sd);
|
||||||
|
else if (sd->state.storage_flag == 2)
|
||||||
|
storage_guild_storageclose(sd);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
@ -133,56 +149,55 @@ int impossible_trade_check(struct map_session_data *sd) {
|
|||||||
memset(&inventory[i], 0, sizeof(struct item));
|
memset(&inventory[i], 0, sizeof(struct item));
|
||||||
|
|
||||||
// check items in player inventory
|
// check items in player inventory
|
||||||
for(i = 0; i < 10; i++)
|
for(i = 0; i < 10; i++) {
|
||||||
if (sd->deal.item[i].amount < 0) { // negativ? -> hack
|
if (!sd->deal.item[i].amount)
|
||||||
// printf("Negativ amount in trade, by hack!\n"); // normal client send cancel when we type negativ amount
|
continue;
|
||||||
return -1;
|
index = sd->deal.item[i].index;
|
||||||
} else if (sd->deal.item[i].amount > 0) {
|
if (inventory[index].amount < sd->deal.item[i].amount)
|
||||||
index = sd->deal.item[i].index;
|
{ // if more than the player have -> hack
|
||||||
inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory
|
sprintf(message_to_gm, msg_txt(538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has.
|
||||||
// printf("%d items left\n", inventory[index].amount);
|
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm);
|
||||||
if (inventory[index].amount < 0) { // if more than the player have -> hack
|
sprintf(message_to_gm, msg_txt(539), sd->status.inventory[index].amount, sd->status.inventory[index].nameid, sd->deal.item[i].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them.
|
||||||
// printf("A player try to trade more items that he has: hack!\n");
|
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm);
|
||||||
sprintf(message_to_gm, msg_txt(538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has.
|
// if we block people
|
||||||
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm);
|
if (battle_config.ban_hack_trade < 0) {
|
||||||
sprintf(message_to_gm, msg_txt(539), sd->status.inventory[index].amount, sd->status.inventory[index].nameid, sd->status.inventory[index].amount - inventory[index].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them.
|
chrif_char_ask_name(-1, sd->status.name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
|
||||||
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm);
|
clif_setwaitclose(sd->fd); // forced to disconnect because of the hack
|
||||||
// if we block people
|
// message about the ban
|
||||||
if (battle_config.ban_hack_trade < 0) {
|
sprintf(message_to_gm, msg_txt(540), battle_config.ban_spoof_namer); // This player has been definitivly blocked.
|
||||||
chrif_char_ask_name(-1, sd->status.name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
|
// if we ban people
|
||||||
clif_setwaitclose(sd->fd); // forced to disconnect because of the hack
|
} else if (battle_config.ban_hack_trade > 0) {
|
||||||
// message about the ban
|
chrif_char_ask_name(-1, sd->status.name, 2, 0, 0, 0, 0, battle_config.ban_hack_trade, 0); // type: 2 - ban (year, month, day, hour, minute, second)
|
||||||
sprintf(message_to_gm, msg_txt(540), battle_config.ban_spoof_namer); // This player has been definitivly blocked.
|
clif_setwaitclose(sd->fd); // forced to disconnect because of the hack
|
||||||
// if we ban people
|
// message about the ban
|
||||||
} else if (battle_config.ban_hack_trade > 0) {
|
sprintf(message_to_gm, msg_txt(507), battle_config.ban_spoof_namer); // This player has been banned for %d minute(s).
|
||||||
chrif_char_ask_name(-1, sd->status.name, 2, 0, 0, 0, 0, battle_config.ban_hack_trade, 0); // type: 2 - ban (year, month, day, hour, minute, second)
|
} else
|
||||||
clif_setwaitclose(sd->fd); // forced to disconnect because of the hack
|
// message about the ban
|
||||||
// message about the ban
|
sprintf(message_to_gm, msg_txt(508)); // This player hasn't been banned (Ban option is disabled).
|
||||||
sprintf(message_to_gm, msg_txt(507), battle_config.ban_spoof_namer); // This player has been banned for %d minute(s).
|
|
||||||
} else {
|
|
||||||
// message about the ban
|
|
||||||
sprintf(message_to_gm, msg_txt(508)); // This player hasn't been banned (Ban option is disabled).
|
|
||||||
}
|
|
||||||
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
* Check here if we can add item in inventory (against full inventory)
|
* Checks if trade is possible (against zeny limits, inventory limits, etc)
|
||||||
*------------------------------------------
|
*------------------------------------------
|
||||||
*/
|
*/
|
||||||
int trade_check(struct map_session_data *sd) {
|
int trade_check(struct map_session_data *sd, struct map_session_data *target_sd) {
|
||||||
struct item inventory[MAX_INVENTORY];
|
struct item inventory[MAX_INVENTORY];
|
||||||
struct item inventory2[MAX_INVENTORY];
|
struct item inventory2[MAX_INVENTORY];
|
||||||
struct item_data *data;
|
struct item_data *data;
|
||||||
struct map_session_data *target_sd;
|
int trade_i, i, amount, n;
|
||||||
int trade_i, i, amount;
|
|
||||||
|
|
||||||
target_sd = map_id2sd(sd->trade_partner);
|
// check zenys value against hackers (Zeny was already checked on time of adding, but you never know when you lost some zeny since then.
|
||||||
|
if(sd->deal.zeny > sd->status.zeny || (target_sd->status.zeny + sd->deal.zeny) > MAX_ZENY)
|
||||||
|
return 0;
|
||||||
|
if(target_sd->deal.zeny > target_sd->status.zeny || (sd->status.zeny + target_sd->deal.zeny) > MAX_ZENY)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// get inventory of player
|
// get inventory of player
|
||||||
memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY);
|
memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY);
|
||||||
@ -191,85 +206,72 @@ int trade_check(struct map_session_data *sd) {
|
|||||||
// check free slot in both inventory
|
// check free slot in both inventory
|
||||||
for(trade_i = 0; trade_i < 10; trade_i++) {
|
for(trade_i = 0; trade_i < 10; trade_i++) {
|
||||||
amount = sd->deal.item[trade_i].amount;
|
amount = sd->deal.item[trade_i].amount;
|
||||||
if (amount > 0) {
|
if (amount) {
|
||||||
int n = sd->deal.item[trade_i].index;
|
n = sd->deal.item[trade_i].index;
|
||||||
// check quantity
|
|
||||||
if (amount > inventory[n].amount)
|
if (amount > inventory[n].amount)
|
||||||
amount = inventory[n].amount;
|
return 0; //qty Exploit?
|
||||||
if (amount > 0) {
|
|
||||||
data = itemdb_search(inventory[n].nameid);
|
data = itemdb_search(inventory[n].nameid);
|
||||||
i = MAX_INVENTORY;
|
i = MAX_INVENTORY;
|
||||||
// check for non-equipement item
|
if (!itemdb_isequip2(data)) { //Stackable item.
|
||||||
if (!itemdb_isequip2(data)) {
|
for(i = 0; i < MAX_INVENTORY; i++)
|
||||||
for(i = 0; i < MAX_INVENTORY; i++)
|
if (inventory2[i].nameid == inventory[n].nameid &&
|
||||||
if (inventory2[i].nameid == inventory[n].nameid &&
|
inventory2[i].card[0] == inventory[n].card[0] && inventory2[i].card[1] == inventory[n].card[1] &&
|
||||||
inventory2[i].card[0] == inventory[n].card[0] && inventory2[i].card[1] == inventory[n].card[1] &&
|
inventory2[i].card[2] == inventory[n].card[2] && inventory2[i].card[3] == inventory[n].card[3]) {
|
||||||
inventory2[i].card[2] == inventory[n].card[2] && inventory2[i].card[3] == inventory[n].card[3]) {
|
if (inventory2[i].amount + amount > MAX_AMOUNT)
|
||||||
if (inventory2[i].amount + amount > MAX_AMOUNT)
|
return 0;
|
||||||
return 0;
|
inventory2[i].amount += amount;
|
||||||
inventory2[i].amount += amount;
|
inventory[n].amount -= amount;
|
||||||
inventory[n].amount -= amount;
|
//let's not make room, as pc_additem is done before pc_delitem, so it could lead to problems depending on order.
|
||||||
if (inventory[n].amount <= 0)
|
// if (!inventory[n].amount)
|
||||||
memset(&inventory[n], 0, sizeof(struct item));
|
// memset(&inventory[n], 0, sizeof(struct item));
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
// check for equipement
|
|
||||||
if (i == MAX_INVENTORY) {
|
|
||||||
for(i = 0; i < MAX_INVENTORY; i++) {
|
|
||||||
if (inventory2[i].nameid == 0) {
|
|
||||||
memcpy(&inventory2[i], &inventory[n], sizeof(struct item));
|
|
||||||
inventory2[i].amount = amount;
|
|
||||||
inventory[n].amount -= amount;
|
|
||||||
if (inventory[n].amount <= 0)
|
|
||||||
memset(&inventory[n], 0, sizeof(struct item));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (i == MAX_INVENTORY)
|
}
|
||||||
return 0;
|
|
||||||
}
|
if (i == MAX_INVENTORY) {// look for an empty slot.
|
||||||
|
for(i = 0; i < MAX_INVENTORY && inventory2[i].nameid; i++);
|
||||||
|
if (i == MAX_INVENTORY)
|
||||||
|
return 0;
|
||||||
|
memcpy(&inventory2[i], &inventory[n], sizeof(struct item));
|
||||||
|
inventory2[i].amount = amount;
|
||||||
|
inventory[n].amount -= amount;
|
||||||
|
// if (!inventory[n].amount)
|
||||||
|
// memset(&inventory[n], 0, sizeof(struct item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
amount = target_sd->deal.item[trade_i].amount;
|
amount = target_sd->deal.item[trade_i].amount;
|
||||||
if (amount > 0) {
|
if (!amount)
|
||||||
int n = target_sd->deal.item[trade_i].index;
|
continue;
|
||||||
// check quantity
|
n = target_sd->deal.item[trade_i].index;
|
||||||
if (amount > inventory2[n].amount)
|
if (amount > inventory2[n].amount)
|
||||||
amount = inventory2[n].amount;
|
return 0;
|
||||||
if (amount > 0) {
|
// search if it's possible to add item (for full inventory)
|
||||||
// search if it's possible to add item (for full inventory)
|
data = itemdb_search(inventory2[n].nameid);
|
||||||
data = itemdb_search(inventory2[n].nameid);
|
i = MAX_INVENTORY;
|
||||||
i = MAX_INVENTORY;
|
if (!itemdb_isequip2(data)) {
|
||||||
if (!itemdb_isequip2(data)) {
|
for(i = 0; i < MAX_INVENTORY; i++)
|
||||||
for(i = 0; i < MAX_INVENTORY; i++)
|
if (inventory[i].nameid == inventory2[n].nameid &&
|
||||||
if (inventory[i].nameid == inventory2[n].nameid &&
|
inventory[i].card[0] == inventory2[n].card[0] && inventory[i].card[1] == inventory2[n].card[1] &&
|
||||||
inventory[i].card[0] == inventory2[n].card[0] && inventory[i].card[1] == inventory2[n].card[1] &&
|
inventory[i].card[2] == inventory2[n].card[2] && inventory[i].card[3] == inventory2[n].card[3]) {
|
||||||
inventory[i].card[2] == inventory2[n].card[2] && inventory[i].card[3] == inventory2[n].card[3]) {
|
if (inventory[i].amount + amount > MAX_AMOUNT)
|
||||||
if (inventory[i].amount + amount > MAX_AMOUNT)
|
|
||||||
return 0;
|
|
||||||
inventory[i].amount += amount;
|
|
||||||
inventory2[n].amount -= amount;
|
|
||||||
if (inventory2[n].amount <= 0)
|
|
||||||
memset(&inventory2[n], 0, sizeof(struct item));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == MAX_INVENTORY) {
|
|
||||||
for(i = 0; i < MAX_INVENTORY; i++) {
|
|
||||||
if (inventory[i].nameid == 0) {
|
|
||||||
memcpy(&inventory[i], &inventory2[n], sizeof(struct item));
|
|
||||||
inventory[i].amount = amount;
|
|
||||||
inventory2[n].amount -= amount;
|
|
||||||
if (inventory2[n].amount <= 0)
|
|
||||||
memset(&inventory2[n], 0, sizeof(struct item));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == MAX_INVENTORY)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
inventory[i].amount += amount;
|
||||||
|
inventory2[n].amount -= amount;
|
||||||
|
// if (!inventory2[n].amount)
|
||||||
|
// memset(&inventory2[n], 0, sizeof(struct item));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (i == MAX_INVENTORY) {
|
||||||
|
for(i = 0; i < MAX_INVENTORY && inventory[i].nameid; i++);
|
||||||
|
if (i == MAX_INVENTORY)
|
||||||
|
return 0;
|
||||||
|
memcpy(&inventory[i], &inventory2[n], sizeof(struct item));
|
||||||
|
inventory[i].amount = amount;
|
||||||
|
inventory2[n].amount -= amount;
|
||||||
|
// if (!inventory2[n].amount)
|
||||||
|
// memset(&inventory2[n], 0, sizeof(struct item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,9 +287,14 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount) {
|
|||||||
int trade_i, trade_weight, nameid;
|
int trade_i, trade_weight, nameid;
|
||||||
|
|
||||||
nullpo_retv(sd);
|
nullpo_retv(sd);
|
||||||
if (!sd->state.trading || (target_sd = map_id2sd(sd->trade_partner)) == NULL || sd->state.deal_locked > 0)
|
if (!sd->state.trading || sd->state.deal_locked > 0)
|
||||||
return; //Can't add stuff.
|
return; //Can't add stuff.
|
||||||
|
|
||||||
|
if ((target_sd = map_id2sd(sd->trade_partner)) == NULL) {
|
||||||
|
trade_tradecancel(sd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
{ //Adding Zeny
|
{ //Adding Zeny
|
||||||
if (amount >= 0 && amount <= MAX_ZENY && amount <= sd->status.zeny && // check amount
|
if (amount >= 0 && amount <= MAX_ZENY && amount <= sd->status.zeny && // check amount
|
||||||
@ -296,7 +303,7 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount) {
|
|||||||
sd->deal.zeny = amount;
|
sd->deal.zeny = amount;
|
||||||
clif_tradeadditem(sd, target_sd, 0, amount);
|
clif_tradeadditem(sd, target_sd, 0, amount);
|
||||||
} else //Cancel Transaction
|
} else //Cancel Transaction
|
||||||
trade_tradecancel(sd);
|
clif_tradeitemok(sd, 0, 1); //Send overweight when trying to add too much zeny? Hope they get the idea...
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//Add an Item
|
//Add an Item
|
||||||
@ -328,7 +335,7 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount) {
|
|||||||
trade_weight = sd->inventory_data[index]->weight * amount;
|
trade_weight = sd->inventory_data[index]->weight * amount;
|
||||||
if (target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight)
|
if (target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight)
|
||||||
{ //fail to add item -- the player was over weighted.
|
{ //fail to add item -- the player was over weighted.
|
||||||
clif_tradeitemok(sd, index, 1);
|
clif_tradeitemok(sd, index+2, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,96 +353,78 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount) {
|
|||||||
}
|
}
|
||||||
sd->deal.weight += trade_weight;
|
sd->deal.weight += trade_weight;
|
||||||
|
|
||||||
if (impossible_trade_check(sd))
|
|
||||||
{ // check exploit (trade more items that you have)
|
|
||||||
trade_tradecancel(sd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
clif_tradeitemok(sd, index+2, 0); // Return the index as it was received
|
clif_tradeitemok(sd, index+2, 0); // Return the index as it was received
|
||||||
clif_tradeadditem(sd, target_sd, index+2, amount); //index fix
|
clif_tradeadditem(sd, target_sd, index+2, amount); //index fix
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
* アイテム追加完了(ok押し)
|
* 'Ok' button on the trade window is pressed.
|
||||||
*------------------------------------------
|
*------------------------------------------
|
||||||
*/
|
*/
|
||||||
void trade_tradeok(struct map_session_data *sd) {
|
void trade_tradeok(struct map_session_data *sd) {
|
||||||
struct map_session_data *target_sd;
|
struct map_session_data *target_sd;
|
||||||
int trade_i;
|
|
||||||
|
|
||||||
nullpo_retv(sd);
|
if(sd->state.deal_locked || !sd->state.trading)
|
||||||
|
return;
|
||||||
|
|
||||||
// check items
|
if ((target_sd = map_id2sd(sd->trade_partner)) == NULL) {
|
||||||
for(trade_i = 0; trade_i < 10; trade_i++) {
|
|
||||||
if ((((sd->deal.item[trade_i].index) >= 0) &&
|
|
||||||
(sd->deal.item[trade_i].amount > sd->status.inventory[sd->deal.item[trade_i].index].amount)) ||
|
|
||||||
(sd->deal.item[trade_i].amount < 0)) {
|
|
||||||
trade_tradecancel(sd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check exploit (trade more items that you have)
|
|
||||||
if (impossible_trade_check(sd)) {
|
|
||||||
trade_tradecancel(sd);
|
trade_tradecancel(sd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
sd->state.deal_locked = 1;
|
||||||
// check zeny
|
clif_tradeitemok(sd, 0, 0);
|
||||||
if (sd->deal.zeny < 0 || sd->deal.zeny > MAX_ZENY || sd->deal.zeny > sd->status.zeny) { // check amount
|
clif_tradedeal_lock(sd, 0);
|
||||||
trade_tradecancel(sd);
|
clif_tradedeal_lock(target_sd, 1);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) {
|
|
||||||
sd->state.deal_locked = 1;
|
|
||||||
clif_tradeitemok(sd, 0, 0);
|
|
||||||
clif_tradedeal_lock(sd, 0);
|
|
||||||
clif_tradedeal_lock(target_sd, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
* 取引キャンセル
|
* 'Cancel' is pressed. (or trade was force-cancelled by the code)
|
||||||
*------------------------------------------
|
*------------------------------------------
|
||||||
*/
|
*/
|
||||||
void trade_tradecancel(struct map_session_data *sd) {
|
void trade_tradecancel(struct map_session_data *sd) {
|
||||||
struct map_session_data *target_sd;
|
struct map_session_data *target_sd;
|
||||||
int trade_i;
|
int trade_i;
|
||||||
|
|
||||||
nullpo_retv(sd);
|
if(!sd->state.trading)
|
||||||
|
return;
|
||||||
|
|
||||||
if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) {
|
for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual)
|
||||||
for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual)
|
if (!sd->deal.item[trade_i].amount)
|
||||||
if (sd->deal.item[trade_i].amount != 0) {
|
continue;
|
||||||
clif_additem(sd, sd->deal.item[trade_i].index, sd->deal.item[trade_i].amount, 0);
|
clif_additem(sd, sd->deal.item[trade_i].index, sd->deal.item[trade_i].amount, 0);
|
||||||
sd->deal.item[trade_i].index = 0;
|
sd->deal.item[trade_i].index = 0;
|
||||||
sd->deal.item[trade_i].amount = 0;
|
sd->deal.item[trade_i].amount = 0;
|
||||||
}
|
|
||||||
if (target_sd->deal.item[trade_i].amount != 0) {
|
|
||||||
clif_additem(target_sd, target_sd->deal.item[trade_i].index, target_sd->deal.item[trade_i].amount, 0);
|
|
||||||
target_sd->deal.item[trade_i].index = 0;
|
|
||||||
target_sd->deal.item[trade_i].amount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sd->deal.zeny) {
|
|
||||||
clif_updatestatus(sd, SP_ZENY);
|
|
||||||
sd->deal.zeny = 0;
|
|
||||||
}
|
|
||||||
if (target_sd->deal.zeny) {
|
|
||||||
clif_updatestatus(target_sd, SP_ZENY);
|
|
||||||
target_sd->deal.zeny = 0;
|
|
||||||
}
|
|
||||||
sd->state.deal_locked = 0;
|
|
||||||
sd->trade_partner = 0;
|
|
||||||
sd->state.trading = 0;
|
|
||||||
target_sd->state.deal_locked = 0;
|
|
||||||
target_sd->trade_partner = 0;
|
|
||||||
target_sd->state.trading = 0;
|
|
||||||
clif_tradecancelled(sd);
|
|
||||||
clif_tradecancelled(target_sd);
|
|
||||||
}
|
}
|
||||||
|
if (sd->deal.zeny) {
|
||||||
|
clif_updatestatus(sd, SP_ZENY);
|
||||||
|
sd->deal.zeny = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_sd = map_id2sd(sd->trade_partner);
|
||||||
|
sd->state.deal_locked = 0;
|
||||||
|
sd->state.trading = 0;
|
||||||
|
sd->trade_partner = 0;
|
||||||
|
clif_tradecancelled(sd);
|
||||||
|
|
||||||
|
if (!target_sd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual)
|
||||||
|
if (!target_sd->deal.item[trade_i].amount)
|
||||||
|
continue;
|
||||||
|
clif_additem(target_sd, target_sd->deal.item[trade_i].index, target_sd->deal.item[trade_i].amount, 0);
|
||||||
|
target_sd->deal.item[trade_i].index = 0;
|
||||||
|
target_sd->deal.item[trade_i].amount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target_sd->deal.zeny) {
|
||||||
|
clif_updatestatus(target_sd, SP_ZENY);
|
||||||
|
target_sd->deal.zeny = 0;
|
||||||
|
}
|
||||||
|
target_sd->state.deal_locked = 0;
|
||||||
|
target_sd->trade_partner = 0;
|
||||||
|
target_sd->state.trading = 0;
|
||||||
|
clif_tradecancelled(target_sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
@ -443,122 +432,106 @@ void trade_tradecancel(struct map_session_data *sd) {
|
|||||||
*------------------------------------------
|
*------------------------------------------
|
||||||
*/
|
*/
|
||||||
void trade_tradecommit(struct map_session_data *sd) {
|
void trade_tradecommit(struct map_session_data *sd) {
|
||||||
struct map_session_data *target_sd;
|
struct map_session_data *tsd;
|
||||||
int trade_i;
|
int trade_i;
|
||||||
int flag;
|
int flag;
|
||||||
|
|
||||||
nullpo_retv(sd);
|
if (!sd->state.trading || !sd->state.deal_locked) //Locked should be 1 (pressed ok) before you can press trade.
|
||||||
|
return;
|
||||||
|
|
||||||
if (sd->state.trading && (target_sd = map_id2sd(sd->trade_partner)) != NULL) {
|
if ((tsd = map_id2sd(sd->trade_partner)) == NULL) {
|
||||||
if ((sd->state.deal_locked >= 1) && (target_sd->state.deal_locked >= 1)) { // both have pressed 'ok'
|
trade_tradecancel(sd);
|
||||||
if (sd->state.deal_locked < 2) { // set locked to 2
|
return;
|
||||||
sd->state.deal_locked = 2;
|
}
|
||||||
}
|
|
||||||
if (target_sd->state.deal_locked == 2) { // the other one pressed 'trade' too
|
|
||||||
// check exploit (trade more items that you have)
|
|
||||||
if (impossible_trade_check(sd)) {
|
|
||||||
trade_tradecancel(sd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// check exploit (trade more items that you have)
|
|
||||||
if (impossible_trade_check(target_sd)) {
|
|
||||||
trade_tradecancel(target_sd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// check zenys value against hackers
|
|
||||||
if (sd->deal.zeny >= 0 && sd->deal.zeny <= MAX_ZENY && sd->deal.zeny <= sd->status.zeny && // check amount
|
|
||||||
(target_sd->status.zeny + sd->deal.zeny) <= MAX_ZENY && // fix positiv overflow
|
|
||||||
target_sd->deal.zeny >= 0 && target_sd->deal.zeny <= MAX_ZENY && target_sd->deal.zeny <= target_sd->status.zeny && // check amount
|
|
||||||
(sd->status.zeny + target_sd->deal.zeny) <= MAX_ZENY) { // fix positiv overflow
|
|
||||||
|
|
||||||
// check for full inventory (can not add traded items)
|
sd->state.deal_locked = 2;
|
||||||
if (!trade_check(sd)) { // check the both players
|
|
||||||
trade_tradecancel(sd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// trade is accepted
|
if (sd->state.deal_locked < 2 || tsd->state.deal_locked < 2)
|
||||||
for(trade_i = 0; trade_i < 10; trade_i++) {
|
return; //Not yet time for trading.
|
||||||
if (sd->deal.item[trade_i].amount != 0) {
|
|
||||||
int n = sd->deal.item[trade_i].index;
|
|
||||||
|
|
||||||
if (sd->status.inventory[n].amount < sd->deal.item[trade_i].amount)
|
//Now is a good time (to save on resources) to check that the trade can indeed be made and it's not exploitable.
|
||||||
sd->deal.item[trade_i].amount = sd->status.inventory[n].amount;
|
// check exploit (trade more items that you have)
|
||||||
|
if (impossible_trade_check(sd)) {
|
||||||
|
trade_tradecancel(sd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// check exploit (trade more items that you have)
|
||||||
|
if (impossible_trade_check(tsd)) {
|
||||||
|
trade_tradecancel(tsd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// check for full inventory (can not add traded items)
|
||||||
|
if (!trade_check(sd,tsd)) { // check the both players
|
||||||
|
trade_tradecancel(sd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
flag = pc_additem(target_sd, &sd->status.inventory[n], sd->deal.item[trade_i].amount);
|
// trade is accepted and correct.
|
||||||
if (flag == 0) {
|
for(trade_i = 0; trade_i < 10; trade_i++) {
|
||||||
//Logs (T)rade [Lupus]
|
int n;
|
||||||
if(log_config.pick > 0 )
|
if (sd->deal.item[trade_i].amount) {
|
||||||
log_pick(sd, "T", 0, sd->status.inventory[n].nameid, -(sd->deal.item[trade_i].amount), &sd->status.inventory[n]);
|
n = sd->deal.item[trade_i].index;
|
||||||
log_pick(target_sd, "T", 0, sd->status.inventory[n].nameid, sd->deal.item[trade_i].amount, &sd->status.inventory[n]);
|
|
||||||
//Logs
|
|
||||||
pc_delitem(sd, n, sd->deal.item[trade_i].amount, 1);
|
|
||||||
} else {
|
|
||||||
clif_additem(sd, n, sd->deal.item[trade_i].amount, 0);
|
|
||||||
}
|
|
||||||
sd->deal.item[trade_i].index = 0;
|
|
||||||
sd->deal.item[trade_i].amount = 0;
|
|
||||||
|
|
||||||
}
|
flag = pc_additem(tsd, &sd->status.inventory[n], sd->deal.item[trade_i].amount);
|
||||||
if (target_sd->deal.item[trade_i].amount != 0) {
|
if (flag == 0) {
|
||||||
int n = target_sd->deal.item[trade_i].index;
|
//Logs (T)rade [Lupus]
|
||||||
|
if(log_config.pick > 0 )
|
||||||
|
log_pick(sd, "T", 0, sd->status.inventory[n].nameid, -(sd->deal.item[trade_i].amount), &sd->status.inventory[n]);
|
||||||
|
log_pick(tsd, "T", 0, sd->status.inventory[n].nameid, sd->deal.item[trade_i].amount, &sd->status.inventory[n]);
|
||||||
|
//Logs
|
||||||
|
pc_delitem(sd, n, sd->deal.item[trade_i].amount, 1);
|
||||||
|
} else
|
||||||
|
clif_additem(sd, n, sd->deal.item[trade_i].amount, 0);
|
||||||
|
sd->deal.item[trade_i].index = 0;
|
||||||
|
sd->deal.item[trade_i].amount = 0;
|
||||||
|
}
|
||||||
|
if (tsd->deal.item[trade_i].amount) {
|
||||||
|
n = tsd->deal.item[trade_i].index;
|
||||||
|
|
||||||
if (target_sd->status.inventory[n].amount < target_sd->deal.item[trade_i].amount)
|
flag = pc_additem(sd, &tsd->status.inventory[n], tsd->deal.item[trade_i].amount);
|
||||||
target_sd->deal.item[trade_i].amount = target_sd->status.inventory[n].amount;
|
if (flag == 0) {
|
||||||
|
//Logs (T)rade [Lupus]
|
||||||
flag = pc_additem(sd, &target_sd->status.inventory[n], target_sd->deal.item[trade_i].amount);
|
if(log_config.pick > 0 )
|
||||||
if (flag == 0) {
|
log_pick(tsd, "T", 0, tsd->status.inventory[n].nameid, -(tsd->deal.item[trade_i].amount), &tsd->status.inventory[n]);
|
||||||
//Logs (T)rade [Lupus]
|
log_pick(sd, "T", 0, tsd->status.inventory[n].nameid, tsd->deal.item[trade_i].amount, &tsd->status.inventory[n]);
|
||||||
if(log_config.pick > 0 )
|
//Logs
|
||||||
log_pick(target_sd, "T", 0, target_sd->status.inventory[n].nameid, -(target_sd->deal.item[trade_i].amount), &target_sd->status.inventory[n]);
|
pc_delitem(tsd, n, tsd->deal.item[trade_i].amount, 1);
|
||||||
log_pick(sd, "T", 0, target_sd->status.inventory[n].nameid, target_sd->deal.item[trade_i].amount, &target_sd->status.inventory[n]);
|
} else
|
||||||
//Logs
|
clif_additem(tsd, n, tsd->deal.item[trade_i].amount, 0);
|
||||||
pc_delitem(target_sd, n, target_sd->deal.item[trade_i].amount, 1);
|
tsd->deal.item[trade_i].index = 0;
|
||||||
} else {
|
tsd->deal.item[trade_i].amount = 0;
|
||||||
clif_additem(target_sd, n, target_sd->deal.item[trade_i].amount, 0);
|
|
||||||
}
|
|
||||||
target_sd->deal.item[trade_i].index = 0;
|
|
||||||
target_sd->deal.item[trade_i].amount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sd->deal.zeny) {
|
|
||||||
//Logs Zeny (T)rade [Lupus]
|
|
||||||
if(log_config.zeny > 0 )
|
|
||||||
log_zeny(target_sd, "T", sd, sd->deal.zeny);
|
|
||||||
//Logs
|
|
||||||
sd->status.zeny -= sd->deal.zeny;
|
|
||||||
target_sd->status.zeny += sd->deal.zeny;
|
|
||||||
}
|
|
||||||
if (target_sd->deal.zeny) {
|
|
||||||
//Logs Zeny (T)rade [Lupus]
|
|
||||||
if(log_config.zeny > 0 )
|
|
||||||
log_zeny(sd, "T", target_sd, target_sd->deal.zeny);
|
|
||||||
//Logs
|
|
||||||
target_sd->status.zeny -= target_sd->deal.zeny;
|
|
||||||
sd->status.zeny += target_sd->deal.zeny;
|
|
||||||
}
|
|
||||||
if (sd->deal.zeny || target_sd->deal.zeny) {
|
|
||||||
clif_updatestatus(sd, SP_ZENY);
|
|
||||||
sd->deal.zeny = 0;
|
|
||||||
clif_updatestatus(target_sd, SP_ZENY);
|
|
||||||
target_sd->deal.zeny = 0;
|
|
||||||
}
|
|
||||||
sd->state.deal_locked = 0;
|
|
||||||
sd->trade_partner = 0;
|
|
||||||
sd->state.trading = 0;
|
|
||||||
target_sd->state.deal_locked = 0;
|
|
||||||
target_sd->trade_partner = 0;
|
|
||||||
target_sd->state.trading = 0;
|
|
||||||
clif_tradecompleted(sd, 0);
|
|
||||||
clif_tradecompleted(target_sd, 0);
|
|
||||||
// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
|
|
||||||
chrif_save(sd,0); // do pc_makesavestatus and save storage too
|
|
||||||
chrif_save(target_sd,0); // do pc_makesavestatus and save storage too
|
|
||||||
// zeny value was modified!!!! hacker with packet modified
|
|
||||||
} else {
|
|
||||||
trade_tradecancel(sd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sd->deal.zeny || tsd->deal.zeny) {
|
||||||
|
if (sd->deal.zeny) {
|
||||||
|
sd->status.zeny -= sd->deal.zeny;
|
||||||
|
tsd->status.zeny += sd->deal.zeny;
|
||||||
|
if (log_config.zeny)
|
||||||
|
log_zeny(tsd, "T", sd, sd->deal.zeny);//Logs Zeny (T)rade [Lupus]
|
||||||
|
sd->deal.zeny = 0;
|
||||||
|
}
|
||||||
|
if (tsd->deal.zeny) {
|
||||||
|
tsd->status.zeny -= tsd->deal.zeny;
|
||||||
|
sd->status.zeny += tsd->deal.zeny;
|
||||||
|
if (log_config.zeny)
|
||||||
|
log_zeny(sd, "T", tsd, tsd->deal.zeny);//Logs Zeny (T)rade [Lupus]
|
||||||
|
tsd->deal.zeny = 0;
|
||||||
|
}
|
||||||
|
clif_updatestatus(sd, SP_ZENY);
|
||||||
|
clif_updatestatus(tsd, SP_ZENY);
|
||||||
|
}
|
||||||
|
|
||||||
|
sd->state.deal_locked = 0;
|
||||||
|
sd->trade_partner = 0;
|
||||||
|
sd->state.trading = 0;
|
||||||
|
|
||||||
|
tsd->state.deal_locked = 0;
|
||||||
|
tsd->trade_partner = 0;
|
||||||
|
tsd->state.trading = 0;
|
||||||
|
|
||||||
|
clif_tradecompleted(sd, 0);
|
||||||
|
clif_tradecompleted(tsd, 0);
|
||||||
|
// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
|
||||||
|
chrif_save(sd,0); // do pc_makesavestatus and save storage too
|
||||||
|
chrif_save(tsd,0); // do pc_makesavestatus and save storage too
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user