· 9 years ago · Jan 05, 2017, 10:04 AM
1// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
2// For more information, see LICENCE in the main folder
3
4#include "../common/cbasetypes.h"
5#include "../common/core.h" // get_svn_revision()
6#include "../common/malloc.h"
7#include "../common/nullpo.h"
8#include "../common/random.h"
9#include "../common/showmsg.h"
10#include "../common/socket.h" // session[]
11#include "../common/strlib.h" // safestrncpy()
12#include "../common/timer.h"
13#include "../common/utils.h"
14#include "../common/mmo.h" //NAME_LENGTH
15
16#include "atcommand.h" // get_atcommand_level()
17#include "map.h"
18#include "battle.h" // battle_config
19#include "battleground.h"
20#include "channel.h"
21#include "chat.h"
22#include "chrif.h"
23#include "clif.h"
24#include "date.h" // is_day_of_*()
25#include "duel.h"
26#include "intif.h"
27#include "itemdb.h"
28#include "log.h"
29#include "mail.h"
30#include "path.h"
31#include "homunculus.h"
32#include "instance.h"
33#include "mercenary.h"
34#include "elemental.h"
35#include "npc.h" // fake_nd
36#include "pet.h" // pet_unlocktarget()
37#include "party.h" // party_search()
38#include "guild.h" // guild_search(), guild_request_info()
39#include "script.h" // script_config
40#include "skill.h"
41#include "status.h" // struct status_data
42#include "storage.h"
43#include "pc.h"
44#include "pc_groups.h"
45#include "quest.h"
46#include "adelays.h"
47#include "achievement.h"
48#include "faction.h"
49#include "region.h"
50#include "storage.h"
51#include "mapreg.h"
52
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <time.h>
57#include <math.h>
58
59int pc_split_atoui(char* str, unsigned int* val, char sep, int max);
60
61#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval
62
63unsigned int stats_point_table[MAX_LEVEL+1];
64#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
65static unsigned int level_penalty[3][CLASS_MAX][MAX_LEVEL*2+1];
66#endif
67
68// h-files are for declarations, not for implementations... [Shinomori]
69struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE];
70// timer for night.day implementation
71int day_timer_tid;
72int night_timer_tid;
73
74struct fame_list smith_fame_list[MAX_FAME_LIST];
75struct fame_list chemist_fame_list[MAX_FAME_LIST];
76struct fame_list taekwon_fame_list[MAX_FAME_LIST];
77struct fame_list pvprank_fame_list[MAX_FAME_LIST];
78struct fame_list pvpevent_fame_list[MAX_FAME_LIST];
79struct fame_list bgrank_fame_list[MAX_FAME_LIST];
80struct fame_list bg_fame_list[MAX_FAME_LIST];
81
82static unsigned int equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO,EQP_SHADOW_ARMOR,EQP_SHADOW_WEAPON,EQP_SHADOW_SHIELD,EQP_SHADOW_SHOES,EQP_SHADOW_ACC_R,EQP_SHADOW_ACC_L};
83
84#define MOTD_LINE_SIZE 128
85static char motd_text[MOTD_LINE_SIZE][CHAT_SIZE_MAX]; // Message of the day buffer [Valaris]
86
87int global_size = 0;
88
89//Links related info to the sd->hate_mob[]/sd->feel_map[] entries
90const struct sg_data sg_info[MAX_PC_FEELHATE] = {
91 { SG_SUN_ANGER, SG_SUN_BLESS, SG_SUN_COMFORT, "PC_FEEL_SUN", "PC_HATE_MOB_SUN", is_day_of_sun },
92 { SG_MOON_ANGER, SG_MOON_BLESS, SG_MOON_COMFORT, "PC_FEEL_MOON", "PC_HATE_MOB_MOON", is_day_of_moon },
93 { SG_STAR_ANGER, SG_STAR_BLESS, SG_STAR_COMFORT, "PC_FEEL_STAR", "PC_HATE_MOB_STAR", is_day_of_star }
94 };
95
96/**
97 * Item Cool Down Delay Saving
98 * Struct item_cd is not a member of struct map_session_data
99 * to keep cooldowns in memory between player log-ins.
100 * All cooldowns are reset when server is restarted.
101 **/
102DBMap* itemcd_db = NULL; // char_id -> struct skill_cd
103struct item_cd {
104 unsigned int tick[MAX_ITEMDELAYS];//tick
105 short nameid[MAX_ITEMDELAYS];//skill id
106};
107
108//Converts a class to its array index for CLASS_COUNT defined arrays.
109//Note that it does not do a validity check for speed purposes, where parsing
110//player input make sure to use a pcdb_checkid first!
111int pc_class2idx(int class_) {
112 if (class_ >= JOB_NOVICE_HIGH)
113 return class_- JOB_NOVICE_HIGH+JOB_MAX_BASIC;
114 return class_;
115}
116
117// Removes invalid Cards on Items on authok
118// Send this Cards via eMail to the user
119void pc_fix_items_sub(struct item *it, struct item_data *inventory_data, struct mail_message *msg)
120{
121 struct item_data *card, *item = inventory_data;
122 int j;
123
124 if( it == NULL || it->nameid == 0 )
125 return;
126 if( item == NULL && (item = itemdb_exists(it->nameid)) == NULL )
127 return;
128 if( it->expire_time != 0 )
129 return; // Ignore Rental Items as those dont belong to player
130
131 // Check Refine
132 if( item->flag.no_refine && it->refine > 0 )
133 it->refine = 0;
134 if( it->refine > MAX_REFINE )
135 it->refine = MAX_REFINE;
136
137#ifdef NSI_UNIQUE_ID
138 if( !itemdb_isstackable2(item) && !it->unique_id )
139 it->unique_id = itemdb_unique_id(0,0);
140#endif
141
142 if( (item->type != IT_ARMOR && item->type != IT_WEAPON) || itemdb_isspecial(it->card[0]) )
143 return;
144
145 for( j = 0; j < MAX_SLOTS; j++ )
146 {
147 if( it->card[j] == 0 || (card = itemdb_exists(it->card[j])) == NULL || card->type != IT_CARD )
148 continue;
149
150 if( j < item->slot )
151 { // Equip Slots
152 if( (item->equip&card->equip) == 0 || (item->type == IT_WEAPON && card->equip == EQP_SHIELD) )
153 ; // This card don't belong here
154 else continue;
155 }
156 else if( itemdb_isenchant(it->card[j]) )
157 continue;
158
159 if( msg )
160 {
161 msg->item.nameid = it->card[j];
162 intif_Mail_send(0, msg);
163 }
164 it->card[j] = 0;
165 }
166
167 return;
168}
169
170void pc_fix_items(struct map_session_data *sd)
171{
172 struct mail_message msg;
173 int i;
174 nullpo_retv(sd);
175
176 // Prepare Base Message
177 msg.id = 0;
178 msg.send_id = 0;
179 safestrncpy(msg.send_name, "Server", NAME_LENGTH);
180 msg.dest_id = sd->status.char_id;
181 safestrncpy(msg.dest_name, sd->status.name, NAME_LENGTH);
182 safestrncpy(msg.title, "Item check system", MAIL_TITLE_LENGTH);
183 safestrncpy(msg.body, "An item had its number of slots changed. This mail contains a card removed from one of the excessive slots.", MAIL_BODY_LENGTH);
184 msg.status = MAIL_NEW;
185 msg.zeny = 0;
186 msg.timestamp = time(NULL);
187 memset(&msg.item, 0, sizeof(struct item));
188 msg.item.amount = 1;
189 msg.item.identify = 1;
190
191 for( i = 0; i < MAX_INVENTORY; i++ )
192 pc_fix_items_sub(&sd->status.inventory[i], sd->inventory_data[i], &msg);
193 for( i = 0; i < MAX_CART; i++ )
194 pc_fix_items_sub(&sd->status.cart[i], NULL, &msg);
195 for( i = 0; i < MAX_STORAGE; i++ )
196 pc_fix_items_sub(&sd->status.storage.items[i], NULL, &msg);
197 for( i = 0; i < MAX_EXTRA_STORAGE; i++ )
198 pc_fix_items_sub(&sd->status.ext_storage.items[i], NULL, &msg);
199}
200
201int pc_need_status_point2(int stat)
202{
203 if( stat >= 115 ) return 28;
204 if( stat >= 110 ) return 24;
205 if( stat >= 105 ) return 20;
206 if( stat >= 100 ) return 16;
207 return ( 1 + (stat + 9) / 10 );
208}
209
210bool pc_isPremium(struct map_session_data *sd)
211{
212 return ( battle_config.premium_group_id && sd->Premium_Tick > (int)time(NULL) );
213}
214
215static int pc_Premium_end(int tid, unsigned int tick, int id, intptr_t data)
216{
217 struct map_session_data *sd = map_id2sd(id);
218 int this_tick;
219
220 if( sd == NULL )
221 return 0;
222 if( tid != sd->Premium_timer )
223 {
224 ShowError("pc_Premium_end: invalid timer id.\n");
225 return 0;
226 }
227
228 this_tick = sd->Premium_Tick - (int)time(NULL);
229 if( this_tick > 0 )
230 { // Reannounce and continue
231 int day, hour, minute, second, next_tick;
232 char output[256];
233
234 next_tick = gettick() + (min(this_tick,3600) * 1000);
235 atcommand_expinfo_sub(this_tick, &day, &hour, &minute, &second);
236 sprintf(output, "Premium Account expire at : %d days, %02d:%02d:%02d", day, hour, minute, second);
237 clif_disp_onlyself(sd, output, strlen(output));
238
239 sd->Premium_timer = add_timer(next_tick, pc_Premium_end, sd->bl.id, 0);
240 return 1;
241 }
242
243 // Return to previous group
244 sd->group_id = sd->Premium_basegroup_id;
245 pc_group_pc_load(sd);
246 sd->Premium_timer = INVALID_TIMER;
247
248 return 1;
249}
250
251void pc_Premium_validate(struct map_session_data *sd)
252{
253 int tick = sd->Premium_Tick - (int)time(NULL);
254
255 if( tick > 0 )
256 {
257 if( sd->Premium_timer != INVALID_TIMER )
258 delete_timer(sd->Premium_timer, pc_Premium_end);
259 else
260 {
261 sd->Premium_basegroup_id = sd->group_id;
262 sd->group_id = battle_config.premium_group_id;
263 pc_group_pc_load(sd);
264 }
265
266 sd->Premium_timer = add_timer(gettick() + min(((tick + 5) * 1000),3600000), pc_Premium_end, sd->bl.id, 0);
267 }
268 else
269 {
270 if( sd->Premium_timer != INVALID_TIMER )
271 {
272 delete_timer(sd->Premium_timer, pc_Premium_end);
273 sd->group_id = sd->Premium_basegroup_id;
274 pc_group_pc_load(sd);
275 }
276
277 sd->Premium_timer = INVALID_TIMER;
278 }
279
280 return;
281}
282
283void pc_calc_playtime(struct map_session_data* sd)
284{
285 if( !sd->state.autotrade && sd->state.active )
286 {
287 sd->status.playtime += DIFF_TICK(last_tick, sd->status.last_tick);
288 sd->status.last_tick = last_tick;
289 }
290
291 return;
292}
293
294/***********************************************************
295* Update Idle PC Timer
296* Type
297* 0 = Send By Server
298* 1 = KeyBoard Action
299* 2 = Mouse Click
300* 3 = Both Hands
301***********************************************************/
302int pc_update_last_action(struct map_session_data *sd, int type)
303{
304 struct battleground_data *bg;
305 unsigned int tick = gettick();
306
307 sd->idletime = last_tick;
308
309 if( sd->bg_id && sd->state.bg_afk && (bg = bg_team_search(sd->bg_id)) != NULL && bg->g )
310 { // Battleground AFK announce
311 char output[128];
312 sprintf(output, "%s : %s is no longer away...", bg->g->name, sd->status.name);
313 clif_bg_message(bg, bg->bg_id, bg->g->name, output, strlen(output) + 1);
314 sd->state.bg_afk = 0;
315 }
316
317 switch( type )
318 {
319 case 1: // Keyboard Possible Actions (Skill Single, Potion)
320 if( battle_config.action_keyboard_limit )
321 {
322 if( DIFF_TICK(tick, sd->keyboard_action_tick) < battle_config.action_keyboard_limit )
323 return 0;
324 sd->keyboard_action_tick = tick;
325 }
326 break;
327 case 2:
328 if( battle_config.action_mouse_limit )
329 {
330 if( DIFF_TICK(tick, sd->mouse_action_tick) < battle_config.action_mouse_limit )
331 return 0;
332 sd->mouse_action_tick = tick;
333 }
334 break;
335 case 3:
336 if( battle_config.action_dual_limit )
337 {
338 unsigned int mtick = max(sd->keyboard_action_tick,sd->mouse_action_tick);
339 if( DIFF_TICK(tick,mtick) < battle_config.action_dual_limit )
340 return 0;
341 sd->keyboard_action_tick = tick;
342 sd->mouse_action_tick = tick;
343 }
344 break;
345 }
346
347 return 1;
348}
349
350inline int pc_get_group_id(struct map_session_data *sd) {
351 return pc_isPremium(sd) ? battle_config.premium_group_id : sd->group_id;
352}
353
354inline int pc_get_group_level(struct map_session_data *sd) {
355 return sd->group_level;
356}
357
358static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data)
359{
360 struct map_session_data *sd;
361
362 if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC )
363 return 1;
364
365 if(sd->invincible_timer != tid){
366 ShowError("invincible_timer %d != %d\n",sd->invincible_timer,tid);
367 return 0;
368 }
369 sd->invincible_timer = INVALID_TIMER;
370 skill_unit_move(&sd->bl,tick,1);
371
372 return 0;
373}
374
375void pc_setinvincibletimer(struct map_session_data* sd, int val) {
376 nullpo_retv(sd);
377
378 if( sd->invincible_timer != INVALID_TIMER )
379 delete_timer(sd->invincible_timer,pc_invincible_timer);
380 sd->invincible_timer = add_timer(gettick()+val,pc_invincible_timer,sd->bl.id,0);
381}
382
383void pc_delinvincibletimer(struct map_session_data* sd)
384{
385 nullpo_retv(sd);
386
387 if( sd->invincible_timer != INVALID_TIMER )
388 {
389 delete_timer(sd->invincible_timer,pc_invincible_timer);
390 sd->invincible_timer = INVALID_TIMER;
391 skill_unit_move(&sd->bl,gettick(),1);
392 }
393}
394
395static int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr_t data)
396{
397 struct map_session_data *sd;
398 int i;
399
400 if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC )
401 return 1;
402
403 if( sd->spiritball <= 0 )
404 {
405 ShowError("pc_spiritball_timer: %d spiritball's available. (aid=%d cid=%d tid=%d)\n", sd->spiritball, sd->status.account_id, sd->status.char_id, tid);
406 sd->spiritball = 0;
407 return 0;
408 }
409
410 ARR_FIND(0, sd->spiritball, i, sd->spirit_timer[i] == tid);
411 if( i == sd->spiritball )
412 {
413 ShowError("pc_spiritball_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid);
414 return 0;
415 }
416
417 sd->spiritball--;
418 if( i != sd->spiritball )
419 memmove(sd->spirit_timer+i, sd->spirit_timer+i+1, (sd->spiritball-i)*sizeof(int));
420 sd->spirit_timer[sd->spiritball] = INVALID_TIMER;
421
422 clif_spiritball(&sd->bl);
423
424 return 0;
425}
426
427int pc_addspiritball(struct map_session_data *sd,int interval,int max)
428{
429 int tid, i;
430
431 nullpo_ret(sd);
432
433 if(max > MAX_SKILL_LEVEL)
434 max = MAX_SKILL_LEVEL;
435 if(sd->spiritball < 0)
436 sd->spiritball = 0;
437
438 if( sd->spiritball && sd->spiritball >= max )
439 {
440 if(sd->spirit_timer[0] != INVALID_TIMER)
441 delete_timer(sd->spirit_timer[0],pc_spiritball_timer);
442 sd->spiritball--;
443 if( sd->spiritball != 0 )
444 memmove(sd->spirit_timer+0, sd->spirit_timer+1, (sd->spiritball)*sizeof(int));
445 sd->spirit_timer[sd->spiritball] = INVALID_TIMER;
446 }
447
448 tid = add_timer(gettick()+interval, pc_spiritball_timer, sd->bl.id, 0);
449 ARR_FIND(0, sd->spiritball, i, sd->spirit_timer[i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->spirit_timer[i])->tick) < 0);
450 if( i != sd->spiritball )
451 memmove(sd->spirit_timer+i+1, sd->spirit_timer+i, (sd->spiritball-i)*sizeof(int));
452 sd->spirit_timer[i] = tid;
453 sd->spiritball++;
454 if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
455 clif_millenniumshield(sd,sd->spiritball);
456 else
457 clif_spiritball(&sd->bl);
458
459 return 0;
460}
461
462int pc_delspiritball(struct map_session_data *sd,int count,int type)
463{
464 int i;
465
466 nullpo_ret(sd);
467
468 if(sd->spiritball <= 0) {
469 sd->spiritball = 0;
470 return 0;
471 }
472
473 if(count <= 0)
474 return 0;
475 if(count > sd->spiritball)
476 count = sd->spiritball;
477 sd->spiritball -= count;
478 if(count > MAX_SKILL_LEVEL)
479 count = MAX_SKILL_LEVEL;
480
481 for(i=0;i<count;i++) {
482 if(sd->spirit_timer[i] != INVALID_TIMER) {
483 delete_timer(sd->spirit_timer[i],pc_spiritball_timer);
484 sd->spirit_timer[i] = INVALID_TIMER;
485 }
486 }
487 for(i=count;i<MAX_SKILL_LEVEL;i++) {
488 sd->spirit_timer[i-count] = sd->spirit_timer[i];
489 sd->spirit_timer[i] = INVALID_TIMER;
490 }
491
492 if(!type) {
493 if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
494 clif_millenniumshield(sd,sd->spiritball);
495 else
496 clif_spiritball(&sd->bl);
497 }
498 return 0;
499}
500
501static int pc_check_banding( struct block_list *bl, va_list ap ) {
502 int *c, *b_sd;
503 struct block_list *src;
504 struct map_session_data *tsd;
505 struct status_change *sc;
506
507 nullpo_ret(bl);
508 nullpo_ret(tsd = (struct map_session_data*)bl);
509 nullpo_ret(src = va_arg(ap,struct block_list *));
510 c = va_arg(ap,int *);
511 b_sd = va_arg(ap, int *);
512
513 if(pc_isdead(tsd))
514 return 0;
515
516 sc = status_get_sc(bl);
517
518 if( bl == src )
519 return 0;
520
521 if( sc && sc->data[SC_BANDING] )
522 {
523 b_sd[(*c)++] = tsd->bl.id;
524 return 1;
525 }
526
527 return 0;
528}
529
530int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
531 int c;
532 int b_sd[MAX_PARTY]; // In case of a full Royal Guard party.
533 int i, j, hp, extra_hp = 0, tmp_qty = 0;
534 int range = skill_get_splash(LG_BANDING,skill_lv);
535
536 nullpo_ret(sd);
537
538 c = 0;
539 memset(b_sd, 0, sizeof(b_sd));
540 i = party_foreachsamemap(pc_check_banding,sd,range,&sd->bl,&c,&b_sd);
541
542 if( c < 1 ) //just recalc status no need to recalc hp
543 { // No more Royal Guards in Banding found.
544 struct status_change *sc;
545 if( (sc = status_get_sc(&sd->bl)) != NULL && sc->data[SC_BANDING] )
546 {
547 sc->data[SC_BANDING]->val2 = 0; // Reset the counter
548 status_calc_bl(&sd->bl, status_sc2scb_flag(SC_BANDING));
549 }
550 return 0;
551 }
552
553 //Add yourself
554 hp = status_get_hp(&sd->bl);
555 i++;
556
557 // Get total HP of all Royal Guards in party.
558 for( j = 0; j < i; j++ ){
559 struct map_session_data *bsd = map_id2sd(b_sd[j]);
560 if( bsd != NULL )
561 hp += status_get_hp(&bsd->bl);
562 }
563
564 // Set average HP.
565 hp = hp / i;
566
567 // If a Royal Guard have full HP, give more HP to others that haven't full HP.
568 for( j = 0; j < i; j++ )
569 {
570 int tmp_hp=0;
571 struct map_session_data *bsd = map_id2sd(b_sd[j]);
572 if( bsd != NULL && (tmp_hp = hp - status_get_max_hp(&bsd->bl)) > 0 ){
573 extra_hp += tmp_hp;
574 tmp_qty++;
575 }
576 }
577
578 if( extra_hp > 0 && tmp_qty > 0 )
579 hp += extra_hp / tmp_qty;
580
581 for( j = 0; j < i; j++ ){
582 struct map_session_data *bsd = map_id2sd(b_sd[j]);
583 if( bsd != NULL )
584 {
585 struct status_change *sc;
586 status_set_hp(&bsd->bl,hp,0); // Set hp
587 if( (sc = status_get_sc(&bsd->bl)) != NULL && sc->data[SC_BANDING] )
588 {
589 sc->data[SC_BANDING]->val2 = c; // Set the counter. It doesn't count your self.
590 status_calc_bl(&bsd->bl, status_sc2scb_flag(SC_BANDING)); // Set atk and def.
591 }
592 }
593 }
594
595 return c;
596}
597
598// Increases a player's fame points and displays a notice to him
599void pc_addfame(struct map_session_data *sd,int count,short flag)
600{
601 int ranktype=-1;
602 nullpo_retv(sd);
603 switch( flag )
604 {
605 case 1: // Pk Rank
606 sd->status.pk.score += count;
607 if( sd->status.pk.score > MAX_FAME )
608 sd->status.pk.score = MAX_FAME;
609
610 clif_rank_info(sd,count,sd->status.pk.score,0);
611 chrif_updatefamelist(sd,1);
612 return;
613 case 2: // Bg Ranked Matchs
614 sd->status.bgstats.rank_points += count;
615 if( sd->status.bgstats.rank_points > MAX_FAME )
616 sd->status.bgstats.rank_points = MAX_FAME;
617
618 clif_rank_info(sd,count,sd->status.bgstats.rank_points,1);
619 chrif_updatefamelist(sd,2);
620 return;
621 case 3: // Bg Normal Matchs
622 sd->status.bgstats.points += count;
623 if( sd->status.bgstats.points > MAX_FAME )
624 sd->status.bgstats.points = MAX_FAME;
625
626 clif_rank_info(sd,count,sd->status.bgstats.points,1);
627 chrif_updatefamelist(sd,3);
628 return;
629 }
630
631 // Normal Rankings
632 sd->status.fame += count;
633 if(sd->status.fame > MAX_FAME)
634 sd->status.fame = MAX_FAME;
635
636 switch(sd->class_&MAPID_UPPERMASK){
637 case MAPID_BLACKSMITH: ranktype=0; break;
638 case MAPID_ALCHEMIST: ranktype=1; break;
639 case MAPID_TAEKWON: ranktype=2; break;
640 }
641
642 clif_update_rankingpoint(sd,ranktype,count);
643 chrif_updatefamelist(sd,0);
644}
645
646// PVP Event Fame
647void pc_pvpevent_addfame(struct map_session_data *sd, bool single)
648{
649 struct map_session_data *p_sd;
650 int player_pos, fame_pos, i;
651 char output[256];
652 bool updatereg = false;
653 nullpo_retv(sd);
654
655 ARR_FIND(0, MAX_FAME_LIST, player_pos, pvpevent_fame_list[player_pos].id == sd->status.char_id); // Search if the player is on the List
656 ARR_FIND(0, MAX_FAME_LIST, fame_pos, pvpevent_fame_list[fame_pos].fame <= sd->pvpevent_fame); // Search if the player should be in the List
657
658 if( fame_pos == MAX_FAME_LIST )
659 ; // Nothing to do, not enough points to rank this time...
660
661 // ===========================================
662 // From here, player have fame_pos =
663 // ===========================================
664 else if( player_pos == fame_pos )
665 { // Same Potion
666 if( pvpevent_fame_list[fame_pos].fame < sd->pvpevent_fame )
667 { // Need to update own score
668 pvpevent_fame_list[fame_pos].fame = sd->pvpevent_fame;
669 updatereg = single;
670 }
671 }
672 else if( player_pos == MAX_FAME_LIST )
673 { // New Player Entering Ranking
674 for( i = MAX_FAME_LIST - 1; i > fame_pos; i-- )
675 memcpy(&pvpevent_fame_list[i], &pvpevent_fame_list[i - 1], sizeof(struct fame_list));
676
677 pvpevent_fame_list[fame_pos].id = sd->status.char_id;
678 pvpevent_fame_list[fame_pos].fame = sd->pvpevent_fame;
679 safestrncpy(pvpevent_fame_list[fame_pos].name, sd->status.name, NAME_LENGTH);
680
681 if( single )
682 {
683 updatereg = true;
684 sprintf(output, "-- Entering Top %d PVP Event Fame List at position %d --", MAX_FAME_LIST, fame_pos + 1);
685 clif_disp_onlyself(sd, output, strlen(output));
686
687 for( i = fame_pos + 1; i < MAX_FAME_LIST; i++ )
688 {
689 if( pvpevent_fame_list[i].id == 0 || (p_sd = map_charid2sd(pvpevent_fame_list[i].id)) == NULL )
690 continue;
691
692 sprintf(output, "-- Going Down to Position %d on Top %d PVP Event Fame List --", i + 1, MAX_FAME_LIST);
693 clif_disp_onlyself(p_sd, output, strlen(output));
694 }
695 }
696 }
697
698 // ===========================================
699 // From here, player have player_pos =
700 // ===========================================
701 else if( fame_pos > player_pos )
702 ; // Player need to increase own score to rank...
703 else if( fame_pos < player_pos )
704 { // Already on the List and going UP
705 for( i = player_pos; i > fame_pos; i-- )
706 memcpy(&pvpevent_fame_list[i], &pvpevent_fame_list[i - 1], sizeof(struct fame_list));
707
708 pvpevent_fame_list[fame_pos].id = sd->status.char_id;
709 pvpevent_fame_list[fame_pos].fame = sd->pvpevent_fame;
710 safestrncpy(pvpevent_fame_list[fame_pos].name, sd->status.name, NAME_LENGTH);
711
712 if( single )
713 {
714 updatereg = true;
715 sprintf(output, "-- Going UP to Position %d on Top %d PVP Event Fame List --", fame_pos + 1, MAX_FAME_LIST);
716 clif_disp_onlyself(sd, output, strlen(output));
717
718 for( i = fame_pos + 1; i < player_pos + 1; i++ )
719 {
720 if( pvpevent_fame_list[i].id == 0 || (p_sd = map_charid2sd(pvpevent_fame_list[i].id)) == NULL )
721 continue;
722
723 sprintf(output, "-- Going Down to Position %d on Top %d PVP Event Fame List --", i + 1, MAX_FAME_LIST);
724 clif_disp_onlyself(p_sd, output, strlen(output));
725 }
726 }
727 }
728
729 if( updatereg )
730 {
731 i = 0;
732 while( i < MAX_FAME_LIST && pvpevent_fame_list[i].id )
733 {
734 mapreg_setregstr(add_str("$pvpevent_name$")+(i<<24), pvpevent_fame_list[i].name);
735 mapreg_setreg(add_str("$pvpevent_id")+(i<<24), pvpevent_fame_list[i].id);
736 mapreg_setreg(add_str("$pvpevent_fame")+(i<<24), pvpevent_fame_list[i].fame);
737 i++;
738 }
739
740 mapreg_setreg(add_str("$pvpevent_count"),i);
741 }
742}
743
744// Check whether a player ID is in the fame rankers' list of its job, returns his/her position if so, 0 else
745unsigned char pc_famerank(int char_id, int job)
746{
747 int i;
748
749 switch(job){
750 case MAPID_BLACKSMITH: // Blacksmith
751 for(i = 0; i < MAX_FAME_LIST; i++){
752 if(smith_fame_list[i].id == char_id)
753 return i + 1;
754 }
755 break;
756 case MAPID_ALCHEMIST: // Alchemist
757 for(i = 0; i < MAX_FAME_LIST; i++){
758 if(chemist_fame_list[i].id == char_id)
759 return i + 1;
760 }
761 break;
762 case MAPID_TAEKWON: // Taekwon
763 for(i = 0; i < MAX_FAME_LIST; i++){
764 if(taekwon_fame_list[i].id == char_id)
765 return i + 1;
766 }
767 break;
768 }
769
770 return 0;
771}
772
773unsigned char pc_pvpfamerank(int char_id)
774{
775 int i;
776
777 for (i = 0; i < MAX_FAME_LIST; i++){
778 if(pvprank_fame_list[i].id == char_id)
779 return i + 1;
780 }
781
782 return 0;
783}
784
785int pc_setrestartvalue(struct map_session_data *sd,int type) {
786 struct status_data *status, *b_status;
787 nullpo_ret(sd);
788
789 b_status = &sd->base_status;
790 status = &sd->battle_status;
791
792 if (type&1) { //Normal resurrection
793 status->hp = 1; //Otherwise status_heal may fail if dead.
794 status_heal(&sd->bl, b_status->hp, 0, 1);
795 if( status->sp < b_status->sp )
796 status_set_sp(&sd->bl, b_status->sp, 1);
797 } else { //Just for saving on the char-server (with values as if respawned)
798 sd->status.hp = b_status->hp;
799 sd->status.sp = (status->sp < b_status->sp)?b_status->sp:status->sp;
800 }
801 return 0;
802}
803
804/*==========================================
805 Rental System
806 *------------------------------------------*/
807static int pc_inventory_rental_end(int tid, unsigned int tick, int id, intptr_t data)
808{
809 struct map_session_data *sd = map_id2sd(id);
810 if( sd == NULL )
811 return 0;
812 if( tid != sd->rental_timer )
813 {
814 ShowError("pc_inventory_rental_end: invalid timer id.\n");
815 return 0;
816 }
817
818 pc_inventory_rentals(sd);
819 return 1;
820}
821
822int pc_inventory_rental_clear(struct map_session_data *sd)
823{
824 if( sd->rental_timer != INVALID_TIMER )
825 {
826 delete_timer(sd->rental_timer, pc_inventory_rental_end);
827 sd->rental_timer = INVALID_TIMER;
828 }
829
830 return 1;
831}
832
833void pc_inventory_rentals(struct map_session_data *sd)
834{
835 int i, c = 0;
836 unsigned int expire_tick, next_tick = UINT_MAX;
837
838 for( i = 0; i < MAX_INVENTORY; i++ )
839 { // Check for Rentals on Inventory
840 if( sd->status.inventory[i].nameid == 0 )
841 continue; // Nothing here
842 if( sd->status.inventory[i].expire_time == 0 )
843 continue;
844
845 if( sd->status.inventory[i].expire_time <= time(NULL) ) {
846 if( sd->status.inventory[i].nameid == ITEMID_REINS_OF_MOUNT && &sd->sc && sd->sc.data[SC_ALL_RIDING] )
847 status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER);
848 clif_rental_expired(sd->fd, i, sd->status.inventory[i].nameid);
849 pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER);
850 } else {
851 expire_tick = (unsigned int)(sd->status.inventory[i].expire_time - time(NULL)) * 1000;
852 clif_rental_time(sd->fd, sd->status.inventory[i].nameid, (int)(expire_tick / 1000));
853 next_tick = min(expire_tick, next_tick);
854 c++;
855 }
856 }
857
858 for( i = 0; i < MAX_CART; i++ )
859 { // Check for Rentals on Cart
860 if( sd->status.cart[i].nameid == 0 )
861 continue; // Nothing here
862 if( sd->status.cart[i].expire_time == 0 )
863 continue;
864
865 if( sd->status.cart[i].expire_time <= time(NULL) )
866 {
867 clif_rental_expired(sd->fd, -1, sd->status.cart[i].nameid);
868 pc_cart_delitem(sd, i, 1, 0, LOG_TYPE_OTHER);
869 }
870 else
871 {
872 expire_tick = (unsigned int)(sd->status.cart[i].expire_time - time(NULL)) * 1000;
873 clif_rental_time(sd->fd, sd->status.cart[i].nameid, (int)(expire_tick / 1000));
874 next_tick = min(expire_tick, next_tick);
875 c++;
876 }
877 }
878
879 for( i = 0; i < MAX_STORAGE; i++ )
880 { // Check for Rentals on Storage
881 if( sd->status.storage.items[i].nameid == 0 )
882 continue;
883 if( sd->status.storage.items[i].expire_time == 0 )
884 continue;
885
886 if( sd->status.storage.items[i].expire_time <= time(NULL) )
887 {
888 clif_rental_expired(sd->fd, -1, sd->status.storage.items[i].nameid);
889 storage_delitem(sd, i, 1);
890 }
891 else
892 {
893 expire_tick = (unsigned int)(sd->status.storage.items[i].expire_time - time(NULL)) * 1000;
894 clif_rental_time(sd->fd, sd->status.storage.items[i].nameid, (int)(expire_tick / 1000));
895 next_tick = min(expire_tick, next_tick);
896 c++;
897 }
898 }
899
900 for( i = 0; i < MAX_EXTRA_STORAGE; i++ )
901 { // Check for Rentals on Extra Storage
902 if( sd->status.ext_storage.items[i].nameid == 0 )
903 continue;
904 if( sd->status.ext_storage.items[i].expire_time == 0 )
905 continue;
906
907 if( sd->status.ext_storage.items[i].expire_time <= time(NULL) )
908 {
909 clif_rental_expired(sd->fd, -1, sd->status.ext_storage.items[i].nameid);
910 ext_storage_delitem(sd, i, 1);
911 }
912 else
913 {
914 expire_tick = (unsigned int)(sd->status.ext_storage.items[i].expire_time - time(NULL)) * 1000;
915 clif_rental_time(sd->fd, sd->status.ext_storage.items[i].nameid, (int)(expire_tick / 1000));
916 next_tick = min(expire_tick, next_tick);
917 c++;
918 }
919 }
920
921 if( c > 0 ) // min(next_tick,3600000) 1 hour each timer to keep announcing to the owner, and to avoid a but with rental time > 15 days
922 sd->rental_timer = add_timer(gettick() + min(next_tick,3600000), pc_inventory_rental_end, sd->bl.id, 0);
923 else
924 sd->rental_timer = INVALID_TIMER;
925}
926
927void pc_inventory_rental_add(struct map_session_data *sd, int seconds)
928{
929 int tick = seconds * 1000;
930
931 if( sd == NULL )
932 return;
933
934 if( sd->rental_timer != INVALID_TIMER )
935 {
936 const struct TimerData * td;
937 td = get_timer(sd->rental_timer);
938 if( DIFF_TICK(td->tick, gettick()) > tick )
939 { // Update Timer as this one ends first than the current one
940 pc_inventory_rental_clear(sd);
941 sd->rental_timer = add_timer(gettick() + tick, pc_inventory_rental_end, sd->bl.id, 0);
942 }
943 }
944 else
945 sd->rental_timer = add_timer(gettick() + min(tick,3600000), pc_inventory_rental_end, sd->bl.id, 0);
946}
947
948/*==========================================
949 Ranking Reset
950 *------------------------------------------*/
951void pc_ranking_reset(int type, bool char_server)
952{
953 struct map_session_data *sd;
954 struct s_mapiterator* iter;
955
956 iter = mapit_getallusers();
957 for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
958 {
959 switch( type )
960 {
961 case 0: // WoE Ranking Reset
962 memset(&sd->status.wstats, 0, sizeof(struct s_woestats));
963 memset(&sd->status.skillcount, 0, sizeof(struct s_skillcount));
964 sd->status.wstats.score = 2000;
965 break;
966 case 1: // Battleground Stats
967 memset(&sd->status.bgstats, 0, sizeof(struct s_battleground_stats));
968 memset(&sd->status.bg_skillcount, 0, sizeof(struct s_skillcount));
969 sd->status.bgstats.score = 2000;
970 break;
971 case 2: // PVP Event Ranking
972 memset(&sd->status.pvp, 0, sizeof(struct s_killrank));
973 sd->status.pvp.score = 2000;
974 break;
975 }
976 }
977 mapit_free(iter);
978
979 if( char_server ) chrif_ranking_reset(type);
980}
981
982/*==========================================
983 Item Removal
984 *------------------------------------------*/
985void pc_item_remove4all(int nameid, bool char_server)
986{
987 if( char_server )
988 chrif_item_remove4all(nameid);
989 else
990 {
991 struct map_session_data *sd;
992 struct s_mapiterator* iter;
993 int index;
994
995 iter = mapit_getallusers();
996 for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
997 {
998 for( index = 0; index < MAX_INVENTORY; index++ )
999 { // Inventory Removal
1000 if( sd->status.inventory[index].nameid != nameid )
1001 continue;
1002 pc_delitem(sd, index, sd->status.inventory[index].amount, 0, 0, LOG_TYPE_COMMAND);
1003 }
1004
1005 for( index = 0; index < MAX_CART; index++ )
1006 { // Cart Removal
1007 if( sd->status.cart[index].nameid != nameid )
1008 continue;
1009 pc_cart_delitem(sd, index, sd->status.cart[index].amount, 0, LOG_TYPE_COMMAND);
1010 }
1011
1012 for( index = 0; index < MAX_STORAGE; index++ )
1013 { // Storage Removal
1014 if( sd->status.storage.items[index].nameid != nameid )
1015 continue;
1016 storage_delitem(sd, index, sd->status.storage.items[index].amount);
1017 }
1018
1019 for( index = 0; index < MAX_EXTRA_STORAGE; index++ )
1020 { // Extra Storage
1021 if( sd->status.ext_storage.items[index].nameid != nameid )
1022 continue;
1023 ext_storage_delitem(sd, index, sd->status.ext_storage.items[index].amount);
1024 }
1025 }
1026 mapit_free(iter);
1027 }
1028}
1029
1030/**
1031 * Determines if player can give / drop / trade / vend items
1032 */
1033bool pc_can_give_items(struct map_session_data *sd)
1034{
1035 return pc_has_permission(sd, PC_PERM_TRADE);
1036}
1037
1038/**
1039 * Determines if player can give / drop / trade / vend bounded items
1040 */
1041bool pc_can_give_bounded_items(struct map_session_data *sd)
1042{
1043 return pc_has_permission(sd, PC_PERM_TRADE_BOUNDED);
1044}
1045
1046/*==========================================
1047 * prepares character for saving.
1048 *------------------------------------------*/
1049int pc_makesavestatus(struct map_session_data *sd)
1050{
1051 nullpo_ret(sd);
1052
1053 if(!battle_config.save_clothcolor)
1054 sd->status.clothes_color=0;
1055
1056 //Only copy the Cart/Peco/Falcon options, the rest are handled via
1057 //status change load/saving. [Skotlex]
1058#ifdef NEW_CARTS
1059 sd->status.option = sd->sc.option&(OPTION_INVISIBLE|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR);
1060#else
1061 sd->status.option = sd->sc.option&(OPTION_INVISIBLE|OPTION_CART|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR);
1062#endif
1063 if (sd->sc.data[SC_JAILED])
1064 { //When Jailed, do not move last point.
1065 if(pc_isdead(sd)){
1066 pc_setrestartvalue(sd,0);
1067 } else {
1068 sd->status.hp = sd->battle_status.hp;
1069 sd->status.sp = sd->battle_status.sp;
1070 }
1071 sd->status.last_point.map = sd->mapindex;
1072 sd->status.last_point.x = sd->bl.x;
1073 sd->status.last_point.y = sd->bl.y;
1074 return 0;
1075 }
1076
1077 if(pc_isdead(sd)){
1078 pc_setrestartvalue(sd,0);
1079 memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
1080 } else {
1081 sd->status.hp = sd->battle_status.hp;
1082 sd->status.sp = sd->battle_status.sp;
1083 sd->status.last_point.map = sd->mapindex;
1084 sd->status.last_point.x = sd->bl.x;
1085 sd->status.last_point.y = sd->bl.y;
1086 }
1087
1088 if(map[sd->bl.m].flag.nosave){
1089 struct map_data *m=&map[sd->bl.m];
1090 if(m->save.map)
1091 memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point));
1092 else
1093 memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
1094 }
1095
1096 return 0;
1097}
1098
1099/*==========================================
1100 * Off init ? Connection?
1101 *------------------------------------------*/
1102int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int login_id1, unsigned int client_tick, int sex, int fd)
1103{
1104 nullpo_ret(sd);
1105
1106 sd->bl.id = account_id;
1107 sd->status.account_id = account_id;
1108 sd->status.char_id = char_id;
1109 sd->status.sex = sex;
1110 sd->login_id1 = login_id1;
1111 sd->login_id2 = 0; // at this point, we can not know the value :(
1112 sd->client_tick = client_tick;
1113 sd->state.active = 0; //to be set to 1 after player is fully authed and loaded.
1114 sd->bl.type = BL_PC;
1115 sd->canlog_tick = sd->canescape_tick = gettick();
1116 //Required to prevent homunculus copuing a base speed of 0.
1117 sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED;
1118 return 0;
1119}
1120
1121int pc_equippoint(struct map_session_data *sd,int n){
1122 int ep = 0, char_id = 0;
1123
1124 nullpo_ret(sd);
1125
1126 if(!sd->inventory_data[n])
1127 return 0;
1128
1129 if (!itemdb_isequip2(sd->inventory_data[n]))
1130 return 0; //Not equippable by players.
1131
1132 ep = sd->inventory_data[n]->equip;
1133 if(sd->inventory_data[n]->look == W_DAGGER ||
1134 sd->inventory_data[n]->look == W_1HSWORD ||
1135 sd->inventory_data[n]->look == W_1HAXE) {
1136 if(ep == EQP_HAND_R && (pc_checkskill(sd,AS_LEFT) > 0 || (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN ||
1137 (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO))//Kagerou and Oboro can dual wield daggers. [Rytech]
1138 return EQP_ARMS;
1139 }
1140
1141 if( battle_config.costume_reserved_char_id &&
1142 sd->status.inventory[n].card[0] == CARD0_CREATE &&
1143 (char_id = MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3])) == battle_config.costume_reserved_char_id )
1144 { // Costume Item - Converted
1145 if( ep&EQP_HEAD_TOP ) { ep &= ~EQP_HEAD_TOP; ep |= EQP_COSTUME_HEAD_TOP; }
1146 if( ep&EQP_HEAD_LOW ) { ep &= ~EQP_HEAD_LOW; ep |= EQP_COSTUME_HEAD_LOW; }
1147 if( ep&EQP_HEAD_MID ) { ep &= ~EQP_HEAD_MID; ep |= EQP_COSTUME_HEAD_MID; }
1148 }
1149 return ep;
1150}
1151
1152/**
1153 * Fill inventory_data with struct *item_data through inventory (fill with struct *item)
1154 * @param sd : player session
1155 * @return 0 sucess, 1:invalid sd
1156 */
1157int pc_setinventorydata(struct map_session_data *sd)
1158{
1159 uint8 i;
1160 nullpo_retr(1,sd);
1161
1162 for(i=0;i<MAX_INVENTORY;i++) {
1163 uint16 id = sd->status.inventory[i].nameid;
1164 sd->inventory_data[i] = id?itemdb_search(id):NULL;
1165 }
1166 return 0;
1167}
1168
1169int pc_calcweapontype(struct map_session_data *sd)
1170{
1171 nullpo_ret(sd);
1172
1173 // single-hand
1174 if(sd->weapontype2 == W_FIST) {
1175 sd->status.weapon = sd->weapontype1;
1176 return 1;
1177 }
1178 if(sd->weapontype1 == W_FIST) {
1179 sd->status.weapon = sd->weapontype2;
1180 return 1;
1181 }
1182 // dual-wield
1183 sd->status.weapon = 0;
1184 switch (sd->weapontype1){
1185 case W_DAGGER:
1186 switch (sd->weapontype2) {
1187 case W_DAGGER: sd->status.weapon = W_DOUBLE_DD; break;
1188 case W_1HSWORD: sd->status.weapon = W_DOUBLE_DS; break;
1189 case W_1HAXE: sd->status.weapon = W_DOUBLE_DA; break;
1190 }
1191 break;
1192 case W_1HSWORD:
1193 switch (sd->weapontype2) {
1194 case W_DAGGER: sd->status.weapon = W_DOUBLE_DS; break;
1195 case W_1HSWORD: sd->status.weapon = W_DOUBLE_SS; break;
1196 case W_1HAXE: sd->status.weapon = W_DOUBLE_SA; break;
1197 }
1198 break;
1199 case W_1HAXE:
1200 switch (sd->weapontype2) {
1201 case W_DAGGER: sd->status.weapon = W_DOUBLE_DA; break;
1202 case W_1HSWORD: sd->status.weapon = W_DOUBLE_SA; break;
1203 case W_1HAXE: sd->status.weapon = W_DOUBLE_AA; break;
1204 }
1205 }
1206 // unknown, default to right hand type
1207 if (!sd->status.weapon)
1208 sd->status.weapon = sd->weapontype1;
1209
1210 return 2;
1211}
1212
1213int pc_setequipindex(struct map_session_data *sd)
1214{
1215 int i,j;
1216
1217 nullpo_ret(sd);
1218
1219 for(i=0;i<EQI_MAX;i++)
1220 sd->equip_index[i] = -1;
1221
1222 for(i=0;i<MAX_INVENTORY;i++) {
1223 if(sd->status.inventory[i].nameid <= 0)
1224 continue;
1225 if(sd->status.inventory[i].equip) {
1226 for(j=0;j<EQI_MAX;j++)
1227 if(sd->status.inventory[i].equip & equip_pos[j])
1228 sd->equip_index[j] = i;
1229
1230 if(sd->status.inventory[i].equip & EQP_HAND_R)
1231 {
1232 if(sd->inventory_data[i])
1233 sd->weapontype1 = sd->inventory_data[i]->look;
1234 else
1235 sd->weapontype1 = 0;
1236 }
1237
1238 if( sd->status.inventory[i].equip & EQP_HAND_L )
1239 {
1240 if( sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON )
1241 sd->weapontype2 = sd->inventory_data[i]->look;
1242 else
1243 sd->weapontype2 = 0;
1244 }
1245 }
1246 }
1247 pc_calcweapontype(sd);
1248
1249 return 0;
1250}
1251
1252//static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int flag)
1253//{
1254// int i;
1255// struct item *item = &sd->status.inventory[eqindex];
1256// struct item_data *data;
1257//
1258// //Crafted/made/hatched items.
1259// if (itemdb_isspecial(item->card[0]))
1260// return 1;
1261//
1262// /* scan for enchant armor gems */
1263// if( item->card[MAX_SLOTS - 1] && s < MAX_SLOTS - 1 )
1264// s = MAX_SLOTS - 1;
1265//
1266// ARR_FIND( 0, s, i, item->card[i] && (data = itemdb_exists(item->card[i])) != NULL && data->flag.no_equip&flag );
1267// return( i < s ) ? 0 : 1;
1268//}
1269
1270static int pc_isAllowedCardOn_Ancient(struct map_session_data *sd,int s,int eqindex)
1271{
1272 int i;
1273 struct item *item = &sd->status.inventory[eqindex];
1274 struct item_data *data;
1275
1276 //Crafted/made/hatched items.
1277 if (itemdb_isspecial(item->card[0]))
1278 return 1;
1279
1280 /* scan for enchant armor gems */
1281 if( item->card[MAX_SLOTS - 1] && s < MAX_SLOTS - 1 )
1282 s = MAX_SLOTS - 1;
1283
1284 ARR_FIND( 0, s, i, item->card[i] && (data = itemdb_exists(item->card[i])) != NULL && !data->ancient );
1285 return( i < s ) ? 0 : 1;
1286}
1287
1288
1289/**
1290 * Check if an item is equiped by player
1291 * (Check if the itemid is equiped then search if that match the index in inventory (should be))
1292 * @param sd : player session
1293 * @param nameid : itemid
1294 * @return 1:yes, 0:no
1295 */
1296bool pc_isequipped(struct map_session_data *sd, int nameid)
1297{
1298 uint8 i;
1299
1300 for( i = 0; i < EQI_MAX; i++ )
1301 {
1302 int8 index = sd->equip_index[i], j;
1303 if( index < 0 ) continue;
1304
1305 if( i == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index ) continue;
1306 if( i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index ) continue;
1307 if( i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index) ) continue;
1308
1309 if( !sd->inventory_data[index] )
1310 continue;
1311 if( sd->inventory_data[index]->nameid == nameid )
1312 return true;
1313 for( j = 0; j < sd->inventory_data[index]->slot; j++ ){
1314 if( sd->status.inventory[index].card[j] == nameid )
1315 return true;
1316 }
1317 }
1318
1319 return false;
1320}
1321
1322bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd )
1323{
1324 if( !p1_sd || !p2_sd || !b_sd )
1325 return false;
1326
1327 if( b_sd->status.father || b_sd->status.mother || b_sd->adopt_invite )
1328 return false; // already adopted baby / in adopt request
1329
1330 if( !p1_sd->status.partner_id || !p1_sd->status.party_id || p1_sd->status.party_id != b_sd->status.party_id )
1331 return false; // You need to be married and in party with baby to adopt
1332
1333 if( p1_sd->status.partner_id != p2_sd->status.char_id || p2_sd->status.partner_id != p1_sd->status.char_id )
1334 return false; // Not married, wrong married
1335
1336 if( p2_sd->status.party_id != p1_sd->status.party_id )
1337 return false; // Both parents need to be in the same party
1338
1339 // Parents need to have their ring equipped
1340 if( !pc_isequipped(p1_sd, WEDDING_RING_M) && !pc_isequipped(p1_sd, WEDDING_RING_F) )
1341 return false;
1342
1343 if( !pc_isequipped(p2_sd, WEDDING_RING_M) && !pc_isequipped(p2_sd, WEDDING_RING_F) )
1344 return false;
1345
1346 // Already adopted a baby
1347 if( p1_sd->status.child || p2_sd->status.child ) {
1348 clif_Adopt_reply(p1_sd, 0);
1349 return false;
1350 }
1351
1352 // Parents need at least lvl 70 to adopt
1353 if( p1_sd->status.base_level < 70 || p2_sd->status.base_level < 70 ) {
1354 clif_Adopt_reply(p1_sd, 1);
1355 return false;
1356 }
1357
1358 if( b_sd->status.partner_id ) {
1359 clif_Adopt_reply(p1_sd, 2);
1360 return false;
1361 }
1362
1363 if( !( ( b_sd->status.class_ >= JOB_NOVICE && b_sd->status.class_ <= JOB_THIEF ) || b_sd->status.class_ == JOB_SUPER_NOVICE ) )
1364 return false;
1365
1366 return true;
1367}
1368
1369/*==========================================
1370 * Adoption Process
1371 *------------------------------------------*/
1372bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd)
1373{
1374 int job, joblevel;
1375 unsigned int jobexp;
1376
1377 if( !pc_can_Adopt(p1_sd, p2_sd, b_sd) )
1378 return false;
1379
1380 // Preserve current job levels and progress
1381 joblevel = b_sd->status.job_level;
1382 jobexp = b_sd->status.job_exp;
1383
1384 job = pc_mapid2jobid(b_sd->class_|JOBL_BABY, b_sd->status.sex);
1385 if( job != -1 && !pc_jobchange(b_sd, job, 0) )
1386 { // Success, proceed to configure parents and baby skills
1387 p1_sd->status.child = b_sd->status.char_id;
1388 p2_sd->status.child = b_sd->status.char_id;
1389 b_sd->status.father = p1_sd->status.char_id;
1390 b_sd->status.mother = p2_sd->status.char_id;
1391
1392 // Restore progress
1393 b_sd->status.job_level = joblevel;
1394 clif_updatestatus(b_sd, SP_JOBLEVEL);
1395 b_sd->status.job_exp = jobexp;
1396 clif_updatestatus(b_sd, SP_JOBEXP);
1397
1398 // Baby Skills
1399 pc_skill(b_sd, WE_BABY, 1, 0);
1400 pc_skill(b_sd, WE_CALLPARENT, 1, 0);
1401
1402 // Parents Skills
1403 pc_skill(p1_sd, WE_CALLBABY, 1, 0);
1404 pc_skill(p2_sd, WE_CALLBABY, 1, 0);
1405
1406 return true;
1407 }
1408
1409 return false; // Job Change Fail
1410}
1411
1412/*==========================================
1413 * Check if player can use/equip selected item. Used by pc_isUseitem and pc_isequip
1414 Returns:
1415 false : Cannot use/equip
1416 true : Can use/equip
1417 * Credits:
1418 [Inkfish] for first idea
1419 [Haru] for third-classes extension
1420 [Cydh] finishing :D
1421 *------------------------------------------*/
1422static bool pc_isItemClass (struct map_session_data *sd, struct item_data* item) {
1423 while (1) {
1424 if (item->class_upper&ITEMJ_NORMAL && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY))) //normal classes (no upper, no baby, no third)
1425 break;
1426#ifndef RENEWAL
1427 //allow third classes to use trans. class items
1428 if (item->class_upper&ITEMJ_UPPER && sd->class_&(JOBL_UPPER|JOBL_THIRD)) //trans. classes
1429 break;
1430 //third-baby classes can use same item too
1431 if (item->class_upper&ITEMJ_BABY && sd->class_&JOBL_BABY) //baby classes
1432 break;
1433 //don't need to decide specific rules for third-classes?
1434 //items for third classes can be used for all third classes
1435 if (item->class_upper&(ITEMJ_THIRD|ITEMJ_THIRD_TRANS|ITEMJ_THIRD_BABY) && sd->class_&JOBL_THIRD)
1436 break;
1437#else
1438 //trans. classes (exl. third-trans.)
1439 if (item->class_upper&ITEMJ_UPPER && sd->class_&JOBL_UPPER && !(sd->class_&JOBL_THIRD))
1440 break;
1441 //baby classes (exl. third-baby)
1442 if (item->class_upper&ITEMJ_BABY && sd->class_&JOBL_BABY && !(sd->class_&JOBL_THIRD))
1443 break;
1444 //third classes (exl. third-trans. and baby-third)
1445 if (item->class_upper&ITEMJ_THIRD && sd->class_&JOBL_THIRD && !(sd->class_&(JOBL_UPPER|JOBL_BABY)))
1446 break;
1447 //trans-third classes
1448 if (item->class_upper&ITEMJ_THIRD_TRANS && sd->class_&JOBL_THIRD && sd->class_&JOBL_UPPER)
1449 break;
1450 //third-baby classes
1451 if (item->class_upper&ITEMJ_THIRD_BABY && sd->class_&JOBL_THIRD && sd->class_&JOBL_BABY)
1452 break;
1453#endif
1454 return false;
1455 }
1456 return true;
1457}
1458
1459/*=================================================
1460 * Checks if the player can equip the item at index n in inventory.
1461 * Returns 0 (no) or 1 (yes).
1462 *------------------------------------------------*/
1463int pc_isequip(struct map_session_data *sd,int n)
1464{
1465 struct item_data *item;
1466
1467 nullpo_ret(sd);
1468
1469 item = sd->inventory_data[n];
1470
1471 if(pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))
1472 return 1;
1473
1474 if(item == NULL)
1475 return 0;
1476 if(item->elv && sd->status.base_level < (unsigned int)item->elv)
1477 return 0;
1478#ifdef RENEWAL
1479 if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax)
1480 return 0;
1481#endif
1482 if(item->sex != 2 && sd->status.sex != item->sex)
1483 return 0;
1484
1485 if (sd->sc.count) {
1486
1487 if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_STRIPWEAPON]) // Also works with left-hand weapons [DracoRPG]
1488 return 0;
1489 if(item->equip & EQP_SHIELD && item->type == IT_ARMOR && sd->sc.data[SC_STRIPSHIELD])
1490 return 0;
1491 if(item->equip & EQP_ARMOR && sd->sc.data[SC_STRIPARMOR])
1492 return 0;
1493 if(item->equip & EQP_HEAD_TOP && sd->sc.data[SC_STRIPHELM])
1494 return 0;
1495 if(item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSORY])
1496 return 0;
1497 if(item->equip && sd->sc.data[SC_KYOUGAKU])
1498 return 0;
1499
1500 if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SUPERNOVICE) {
1501 //Spirit of Super Novice equip bonuses. [Skotlex]
1502 if (sd->status.base_level > 90 && item->equip & EQP_HELM)
1503 return 1; //Can equip all helms
1504
1505 if (sd->status.base_level > 96 && item->equip & EQP_ARMS && item->type == IT_WEAPON)
1506 switch(item->look) { //In weapons, the look determines type of weapon.
1507 case W_DAGGER: //Level 4 Knives are equippable.. this means all knives, I'd guess?
1508 case W_1HSWORD: //All 1H swords
1509 case W_1HAXE: //All 1H Axes
1510 case W_MACE: //All 1H Maces
1511 case W_STAFF: //All 1H Staves
1512 return 1;
1513 }
1514 }
1515 }
1516
1517 //fail to equip if item is restricted
1518 if (!battle_config.allow_equip_restricted_item && itemdb_isNoEquip(item, sd->bl.m))
1519 return 0;
1520
1521 //Not equipable by class. [Skotlex]
1522 if (!(1<<(sd->class_&MAPID_BASEMASK)&item->class_base[(sd->class_&JOBL_2_1)?1:((sd->class_&JOBL_2_2)?2:0)]))
1523 return 0;
1524
1525 if (!pc_isItemClass(sd,item))
1526 return 0;
1527
1528 return 1;
1529}
1530
1531int pc_isequip2(struct map_session_data *sd, int nameid)
1532{
1533 struct item_data *item;
1534 nullpo_ret(sd);
1535
1536 if( (item = itemdb_exists(nameid)) == NULL )
1537 return 0;
1538 if( pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT) )
1539 return 1;
1540 if( item->elv && sd->status.base_level < (unsigned int)item->elv )
1541 return 0; // Level Restriction
1542 if( item->sex != 2 && sd->status.sex != item->sex )
1543 return 0; // Sex Restriction
1544 if( !(1<<(sd->class_&MAPID_BASEMASK)&item->class_base[(sd->class_&JOBL_2_1)?1:((sd->class_&JOBL_2_2)?2:0)]) )
1545 return 0; // Not equipable by Class
1546 //Not usable by upper class. [Inkfish]
1547 while( 1 ) {
1548 if( item->class_upper&1 && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
1549 if( item->class_upper&2 && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
1550 if( item->class_upper&4 && sd->class_&JOBL_BABY ) break;
1551 if( item->class_upper&8 && sd->class_&JOBL_THIRD ) break;
1552 return 0;
1553 }
1554
1555 return 1;
1556}
1557
1558/*==========================================
1559 * No problem with the session id
1560 * set the status that has been sent from char server
1561 *------------------------------------------*/
1562bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers)
1563{
1564 int i;
1565#ifdef BOUND_ITEMS
1566 int j;
1567 int idxlist[MAX_INVENTORY];
1568#endif
1569 unsigned long tick = gettick();
1570 uint32 ip = session[sd->fd]->client_addr;
1571
1572 sd->login_id2 = login_id2;
1573 sd->group_id = group_id;
1574
1575 /* load user permissions */
1576 pc_group_pc_load(sd);
1577
1578 memcpy(&sd->status, st, sizeof(*st));
1579
1580 if (st->sex != sd->status.sex) {
1581 clif_authfail_fd(sd->fd, 0);
1582 return false;
1583 }
1584
1585 //Set the map-server used job id. [Skotlex]
1586 i = pc_jobid2mapid(sd->status.class_);
1587 if (i == -1) { //Invalid class?
1588 ShowError("pc_authok: Invalid class %d for player %s (%d:%d). Class was changed to novice.\n", sd->status.class_, sd->status.name, sd->status.account_id, sd->status.char_id);
1589 sd->status.class_ = JOB_NOVICE;
1590 sd->class_ = MAPID_NOVICE;
1591 } else
1592 sd->class_ = i;
1593
1594 // Checks and fixes to character status data, that are required
1595 // in case of configuration change or stuff, which cannot be
1596 // checked on char-server.
1597 sd->status.hair = cap_value(sd->status.hair,MIN_HAIR_STYLE,MAX_HAIR_STYLE);
1598 sd->status.hair_color = cap_value(sd->status.hair_color,MIN_HAIR_COLOR,MAX_HAIR_COLOR);
1599 sd->status.clothes_color = cap_value(sd->status.clothes_color,MIN_CLOTH_COLOR,MAX_CLOTH_COLOR);
1600
1601 //Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation.
1602 if(!sd->status.hp) pc_setdead(sd);
1603 sd->state.connect_new = 1;
1604 sd->state.size = global_size;
1605 sd->vend_coin = battle_config.vending_zeny_id;
1606
1607 sd->followtimer = INVALID_TIMER; // [MouseJstr]
1608 sd->invincible_timer = INVALID_TIMER;
1609 sd->npc_timer_id = INVALID_TIMER;
1610 sd->pvp_timer = INVALID_TIMER;
1611 sd->achievement_cutin_timer = INVALID_TIMER;
1612
1613#ifdef SECURE_NPCTIMEOUT
1614 // Initialize to defaults/expected
1615 sd->npc_idle_timer = INVALID_TIMER;
1616 sd->npc_idle_tick = tick;
1617 sd->npc_idle_type = NPCT_INPUT;
1618#endif
1619
1620 sd->canuseitem_tick = tick;
1621 sd->canusecashfood_tick = tick;
1622 sd->canequip_tick = tick;
1623 sd->cantalk_tick = tick;
1624 sd->canskill_tick = tick;
1625 sd->channel_cantalk_tick = tick;
1626 sd->canjoinchn_tick = tick;
1627 sd->cansendmail_tick = tick;
1628 sd->keyboard_action_tick = tick;
1629 sd->mouse_action_tick = tick;
1630
1631 sd->custom_data.session_start = last_tick;
1632 sd->status.last_tick = last_tick;
1633
1634 for(i = 0; i < MAX_SKILL_LEVEL; i++)
1635 sd->spirit_timer[i] = INVALID_TIMER;
1636 for(i = 0; i < ARRAYLENGTH(sd->autobonus); i++)
1637 sd->autobonus[i].active = INVALID_TIMER;
1638 for(i = 0; i < ARRAYLENGTH(sd->autobonus2); i++)
1639 sd->autobonus2[i].active = INVALID_TIMER;
1640 for(i = 0; i < ARRAYLENGTH(sd->autobonus3); i++)
1641 sd->autobonus3[i].active = INVALID_TIMER;
1642
1643 if (battle_config.item_auto_get)
1644 sd->aloot.rate = 10000;
1645
1646 if (battle_config.disp_experience)
1647 sd->state.showexp = 1;
1648 if (battle_config.disp_zeny)
1649 sd->state.showzeny = 1;
1650#ifdef VIP_ENABLE
1651 if (!battle_config.vip_disp_rate)
1652 sd->disableshowrate = 1;
1653#endif
1654
1655 if (!(battle_config.display_skill_fail&2))
1656 sd->state.showdelay = 1;
1657
1658 pc_setinventorydata(sd);
1659 pc_setequipindex(sd);
1660 // Adelays in pc_authok()
1661 adelays_dataset(&(sd->adelays_state), sd->status.name);
1662 // Adelays end.
1663
1664 if( sd->status.option&OPTION_INVISIBLE && !pc_can_use_command( sd, "hide", COMMAND_ATCOMMAND ) ){
1665 sd->status.option &= ~OPTION_INVISIBLE;
1666 }
1667
1668 status_change_init(&sd->bl);
1669
1670 sd->sc.option = sd->status.option; //This is the actual option used in battle.
1671 //Set here because we need the inventory data for weapon sprite parsing.
1672 status_set_viewdata(&sd->bl, sd->status.class_);
1673 unit_dataset(&sd->bl);
1674
1675 sd->guild_x = -1;
1676 sd->guild_y = -1;
1677
1678 // Event Timers
1679 for( i = 0; i < MAX_EVENTTIMER; i++ )
1680 sd->eventtimer[i] = INVALID_TIMER;
1681 // Rental Timer
1682 sd->rental_timer = INVALID_TIMER;
1683 sd->channel_invite_timer = INVALID_TIMER;
1684 sd->Premium_timer = INVALID_TIMER;
1685
1686 for( i = 0; i < 3; i++ )
1687 sd->hate_mob[i] = -1;
1688
1689 //warp player
1690 if ((i=pc_setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, CLR_OUTSIGHT)) != 0) {
1691 ShowError ("Last_point_map %s - id %d not found (error code %d)\n", mapindex_id2name(sd->status.last_point.map), sd->status.last_point.map, i);
1692
1693 // try warping to a default map instead (church graveyard)
1694 if (pc_setpos(sd, mapindex_name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != 0) {
1695 // if we fail again
1696 clif_authfail_fd(sd->fd, 0);
1697 return false;
1698 }
1699 }
1700
1701 clif_authok(sd);
1702
1703 //Prevent S. Novices from getting the no-death bonus just yet. [Skotlex]
1704 sd->die_counter=-1;
1705
1706 //display login notice
1707 ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in."
1708 " (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"',"
1709 " Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"',"
1710 " Group '"CL_WHITE"%d"CL_RESET"').\n",
1711 sd->status.name, sd->status.account_id, sd->status.char_id,
1712 sd->packet_ver, CONVIP(ip), sd->group_id);
1713 // Send friends list
1714 clif_friendslist_send(sd);
1715
1716 if( !changing_mapservers ) {
1717
1718 if (battle_config.display_version == 1)
1719 pc_show_version(sd);
1720
1721 // Message of the Day [Valaris]
1722 for(i=0; i < MOTD_LINE_SIZE && motd_text[i][0]; i++) {
1723 if (battle_config.motd_type)
1724 clif_disp_onlyself(sd,motd_text[i],strlen(motd_text[i]));
1725 else
1726 clif_displaymessage(sd->fd, motd_text[i]);
1727 }
1728
1729 // message of the limited time of the account
1730 if (expiration_time != 0) { // don't display if it's unlimited or unknow value
1731 char tmpstr[1024];
1732 strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(sd,501), localtime(&expiration_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S."
1733 clif_wis_message(sd->fd, wisp_server_name, tmpstr, strlen(tmpstr)+1);
1734 }
1735
1736 /**
1737 * Fixes login-without-aura glitch (the screen won't blink at this point, don't worry :P)
1738 **/
1739 clif_changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y);
1740 }
1741
1742 /**
1743 * Check if player have any item cooldowns on
1744 **/
1745 pc_itemcd_do(sd,true);
1746
1747#ifdef BOUND_ITEMS
1748 // Party bound item check
1749 if(sd->status.party_id == 0 && (j = pc_bound_chk(sd,3,idxlist))) { // Party was deleted while character offline
1750 for(i=0;i<j;i++)
1751 pc_delitem(sd,idxlist[i],sd->status.inventory[idxlist[i]].amount,0,1,LOG_TYPE_OTHER);
1752 }
1753#endif
1754
1755 // Player has not yet received the CashShop list
1756 sd->status.cashshop_sent = false;
1757
1758 // Request all registries (auth is considered completed whence they arrive)
1759 intif_request_registry(sd,7);
1760 return true;
1761}
1762
1763/*==========================================
1764 * Closes a connection because it failed to be authenticated from the char server.
1765 *------------------------------------------*/
1766void pc_authfail(struct map_session_data *sd)
1767{
1768 clif_authfail_fd(sd->fd, 0);
1769 return;
1770}
1771
1772/**
1773 * Player register a bl as hatred
1774 * @param sd : player session
1775 * @param pos : hate position [0;2]
1776 * @param bl : target bl
1777 * @return false:failed, true:success
1778 */
1779bool pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl)
1780{
1781 int class_;
1782 if (!sd || !bl || pos < 0 || pos > 2)
1783 return false;
1784 if (sd->hate_mob[pos] != -1)
1785 { //Can't change hate targets.
1786 clif_hate_info(sd, pos, sd->hate_mob[pos], 0); //Display current
1787 return false;
1788 }
1789
1790 class_ = status_get_class(bl);
1791 if (!pcdb_checkid(class_)) {
1792 unsigned int max_hp = status_get_max_hp(bl);
1793 if ((pos == 1 && max_hp < 6000) || (pos == 2 && max_hp < 20000))
1794 return false;
1795 if (pos != status_get_size(bl))
1796 return false; //Wrong size
1797 }
1798 sd->hate_mob[pos] = class_;
1799 pc_setglobalreg(sd,sg_info[pos].hate_var,class_+1);
1800 clif_hate_info(sd, pos, class_, 1);
1801 return true;
1802}
1803
1804/*==========================================
1805 * Invoked once after the char/account/account2 registry variables are received. [Skotlex]
1806 *------------------------------------------*/
1807int pc_reg_received(struct map_session_data *sd)
1808{
1809 uint8 i;
1810 char output[256], varname[32];
1811
1812 sd->change_level_2nd = pc_readglobalreg(sd,"jobchange_level");
1813 sd->change_level_3rd = pc_readglobalreg(sd,"jobchange_level_3rd");
1814 sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER");
1815 sd->user_aura = pc_readglobalreg(sd,"#USERAURA");
1816 sd->langtype = pc_readaccountreg(sd,"#langtype");
1817 if(msg_checklangtype(sd->langtype,true)<0) sd->langtype=0; //invalid langtype reset to default
1818
1819 // Cash shop
1820 sd->cashPoints = pc_readaccountreg(sd,"#CASHPOINTS");
1821 sd->kafraPoints = pc_readaccountreg(sd,"#KAFRAPOINTS");
1822
1823 // Cooking Exp
1824 sd->cook_mastery = pc_readglobalreg(sd,"COOK_MASTERY");
1825 sd->lgp_settings = pc_readglobalreg(sd,"LGP_SETTINGS");
1826
1827 if (!sd->lgp_settings)
1828 {
1829 sd->lgp_settings = (LGP_CIRCLE | LGP_SQUARE | LGP_AOES);
1830 sd->lgp_settings += 10;
1831 pc_setglobalreg(sd,"LGP_SETTINGS", sd->lgp_settings);
1832 }
1833
1834 pc_lgp_update_settings(sd);
1835 // eAmod
1836 sd->custom_data.MVPKiller = pc_readglobalreg(sd,"MVPRank");
1837 sd->lang_mastery = pc_readglobalreg(sd,"eAmod_Languages");
1838 sd->bg_team = pc_readglobalreg(sd,"Bat_Team");
1839 sd->Premium_Tick = pc_readaccountreg(sd,"#Premium_Tick"); // Premium Account System
1840
1841 if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON )
1842 { // Better check for class rather than skill to prevent "skill resets" from unsetting this
1843 sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID");
1844 sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT");
1845 }
1846
1847 // Hunting Missions [Zephyrus]
1848 sd->hunting_time = pc_readglobalreg(sd,"Mission_Tick");
1849 for( i = 0; i < 5; i++ )
1850 {
1851 sprintf(varname, "Mission_ID%d", i + 1);
1852 sd->hunting[i].mob_id = pc_readglobalreg(sd,varname);
1853 sprintf(varname, "Mission_Count%d", i + 1);
1854 sd->hunting[i].count = pc_readglobalreg(sd,varname);
1855 }
1856
1857 //SG map and mob read [Komurka]
1858 for(i=0;i<MAX_PC_FEELHATE;i++) //for now - someone need to make reading from txt/sql
1859 {
1860 uint16 j;
1861 if ((j = pc_readglobalreg(sd,sg_info[i].feel_var))!=0) {
1862 sd->feel_map[i].index = j;
1863 sd->feel_map[i].m = map_mapindex2mapid(j);
1864 } else {
1865 sd->feel_map[i].index = 0;
1866 sd->feel_map[i].m = -1;
1867 }
1868 sd->hate_mob[i] = pc_readglobalreg(sd,sg_info[i].hate_var)-1;
1869 }
1870
1871 if ((i = pc_checkskill(sd,RG_PLAGIARISM)) > 0) {
1872 sd->cloneskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM));
1873 if (sd->cloneskill_idx >= 0) {
1874 sd->status.skill[sd->cloneskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM);
1875 sd->status.skill[sd->cloneskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM_LV);
1876 if (sd->status.skill[sd->cloneskill_idx].lv > i)
1877 sd->status.skill[sd->cloneskill_idx].lv = i;
1878 sd->status.skill[sd->cloneskill_idx].flag = SKILL_FLAG_PLAGIARIZED;
1879 }
1880 }
1881 if ((i = pc_checkskill(sd,SC_REPRODUCE)) > 0) {
1882 sd->reproduceskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_REPRODUCE));
1883 if (sd->reproduceskill_idx >= 0) {
1884 sd->status.skill[sd->reproduceskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE);
1885 sd->status.skill[sd->reproduceskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE_LV);
1886 if (i < sd->status.skill[sd->reproduceskill_idx].lv)
1887 sd->status.skill[sd->reproduceskill_idx].lv = i;
1888 sd->status.skill[sd->reproduceskill_idx].flag = SKILL_FLAG_PLAGIARIZED;
1889 }
1890 }
1891 //Weird... maybe registries were reloaded?
1892 if (sd->state.active)
1893 return 0;
1894 sd->state.active = 1;
1895 if( battle_config.pc_validate_items ) pc_fix_items(sd);
1896
1897 // Stats Check ------
1898 if( battle_config.pc_validate_stats )
1899 {
1900 int b_stats = stats_point_table[sd->status.base_level] + (sd->class_&JOBL_UPPER ? 52 : 0),
1901 u_stats = 0;
1902 // Stats Used Calc
1903 for( i = 1; i <= sd->status.str - 1; i++ )
1904 u_stats += pc_need_status_point2(i);
1905 for( i = 1; i <= sd->status.int_ - 1; i++ )
1906 u_stats += pc_need_status_point2(i);
1907 for( i = 1; i <= sd->status.vit - 1; i++ )
1908 u_stats += pc_need_status_point2(i);
1909 for( i = 1; i <= sd->status.dex - 1; i++ )
1910 u_stats += pc_need_status_point2(i);
1911 for( i = 1; i <= sd->status.agi - 1; i++ )
1912 u_stats += pc_need_status_point2(i);
1913 for( i = 1; i <= sd->status.luk - 1; i++ )
1914 u_stats += pc_need_status_point2(i);
1915 // Free Stats Points
1916 u_stats += sd->status.status_point;
1917 if( u_stats != b_stats )
1918 {
1919 sd->status.status_point = b_stats;
1920 sd->status.str = 1;
1921 sd->status.agi = 1;
1922 sd->status.vit = 1;
1923 sd->status.int_ = 1;
1924 sd->status.dex = 1;
1925 sd->status.luk = 1;
1926 clif_displaymessage(sd->fd, "Abnormal Stats Points found. Your Build have been reset.");
1927 log_npc(sd,"Invalid Character Stats Points founds. Reseted.");
1928 }
1929 }
1930 // ------------------
1931
1932 if (sd->status.party_id)
1933 party_member_joined(sd);
1934 if (sd->status.guild_id)
1935 guild_member_joined(sd, false);
1936
1937 // pet
1938 if (sd->status.pet_id > 0)
1939 intif_request_petdata(sd->status.account_id, sd->status.char_id, sd->status.pet_id);
1940
1941 // Homunculus [albator]
1942 if( sd->status.hom_id > 0 )
1943 intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id);
1944 if( sd->status.mer_id > 0 )
1945 intif_mercenary_request(sd->status.mer_id, sd->status.char_id);
1946 if( sd->status.ele_id > 0 )
1947 intif_elemental_request(sd->status.ele_id, sd->status.char_id);
1948
1949 map_addiddb(&sd->bl);
1950 map_delnickdb(sd->status.char_id, sd->status.name);
1951 if (!chrif_auth_finished(sd))
1952 ShowError("pc_reg_received: Failed to properly remove player %d:%d from logging db!\n", sd->status.account_id, sd->status.char_id);
1953
1954 pc_check_available_item(sd); // Check for invalid(ated) items.
1955 pc_load_combo(sd);
1956
1957 status_calc_pc(sd,1);
1958 chrif_scdata_request(sd->status.account_id, sd->status.char_id);
1959 chrif_skillcooldown_request(sd->status.account_id, sd->status.char_id);
1960 chrif_bsdata_request(sd->status.char_id);
1961 sd->storage_size = MIN_STORAGE; //default to min
1962 if(battle_config.feature_banking)
1963 chrif_req_login_operation(sd->status.account_id, sd->status.name, 7, 0, 1, 0); //request Bank data
1964#ifdef VIP_ENABLE
1965 sd->vip.time = 0;
1966 sd->vip.enabled = 0;
1967 chrif_req_login_operation(sd->status.account_id, sd->status.name, 6, 0, 1, 0); // request VIP informations
1968#endif
1969 intif_Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox
1970 intif_request_questlog(sd);
1971 intif_request_achievement(sd);
1972
1973 if( sd->status.iprank > 0 )
1974 {
1975 sprintf(output, "Conectado desde NetCafe Asociado Rango %d. (+%d%% Exp Bono)", sd->status.iprank, sd->status.iprank * 2);
1976 clif_disp_onlyself(sd, output, strlen(output));
1977 }
1978
1979 /*// Security System
1980 if( pc_readaccountreg(sd,"#SECURITYCODE1") > 0 )
1981 {
1982 clif_displaymessage(sd->fd, "Item Security System ENABLE : Use @security for more options.");
1983 sd->state.secure_items = 1;
1984 }
1985 else
1986 clif_displaymessage(sd->fd, "Item Security System DISABLE : Use @security for more options.");
1987*/
1988 if( battle_config.channel_system_enable )
1989 {
1990 sd->channels = pc_readaccountreg(sd,"#CHANNEL_CONF");
1991 if( sd->channels&1 && server_channel[CHN_MAIN] )
1992 channel_join(sd, server_channel[CHN_MAIN]->name, "", false);
1993 if( sd->channels&2 && server_channel[CHN_VENDING] )
1994 channel_join(sd, server_channel[CHN_VENDING]->name, "", false);
1995 if( sd->channels&4 && server_channel[CHN_BATTLEGROUND] )
1996 channel_join(sd, server_channel[CHN_BATTLEGROUND]->name, "", false);
1997 if( pc_has_permission(sd,PC_PERM_CHANNEL_ADMIN) && (sd->channels&8) && server_channel[CHN_GAMEMASTER] )
1998 channel_join(sd, server_channel[CHN_GAMEMASTER]->name, "", false);
1999 }
2000
2001 if( pc_isPremium(sd) )
2002 {
2003 int tick = sd->Premium_Tick - (int)time(NULL), day, hour, minute, second;
2004
2005 sd->Premium_basegroup_id = sd->group_id; // Store Base Group to control expire
2006 sd->group_id = battle_config.premium_group_id;
2007 pc_group_pc_load(sd);
2008 sd->Premium_timer = add_timer(gettick() + min(((tick + 5) * 1000),3600000), pc_Premium_end, sd->bl.id, 0);
2009
2010 atcommand_expinfo_sub(tick, &day, &hour, &minute, &second);
2011 sprintf(output, "Premium Account expire at : %d days, %02d:%02d:%02d", day, hour, minute, second);
2012 clif_disp_onlyself(sd, output, strlen(output));
2013 }
2014
2015 if( battle_config.bg_reward_rates != 100 )
2016 {
2017 int erate = battle_config.bg_reward_rates - 100;
2018 sprintf(output, "Battleground Happy Hour. Rates at + %d %%", erate);
2019 clif_displaymessage(sd->fd, output);
2020 }
2021
2022 if (sd->state.connect_new == 0 && sd->fd) { //Character already loaded map! Gotta trigger LoadEndAck manually.
2023 sd->state.connect_new = 1;
2024 clif_parse_LoadEndAck(sd->fd, sd);
2025 }
2026
2027 pc_inventory_rentals(sd);
2028
2029 if( sd->sc.option&OPTION_INVISIBLE ) {
2030 sd->vd.class_ = INVISIBLE_CLASS;
2031 clif_displaymessage( sd->fd, msg_txt( sd, 11 ) ); // Invisible: On
2032 // decrement the number of pvp players on the map
2033 map[sd->bl.m].users_pvp--;
2034
2035 if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ){
2036 // unregister the player for ranking
2037 delete_timer( sd->pvp_timer, pc_calc_pvprank_timer );
2038 sd->pvp_timer = INVALID_TIMER;
2039 }
2040
2041 clif_changeoption( &sd->bl );
2042 }
2043
2044 if( sd->state.autotrade ){
2045 clif_parse_LoadEndAck(sd->fd, sd);
2046 }
2047
2048 return 1;
2049}
2050
2051int pc_calc_skillpoint(struct map_session_data* sd)
2052{
2053 uint16 i, skill_point=0;
2054
2055 nullpo_ret(sd);
2056
2057 for(i=1;i<MAX_SKILL;i++){
2058 uint8 skill_lv;
2059 if( (skill_lv = pc_checkskill(sd,i)) > 0) {
2060 uint16 inf2 = skill_get_inf2(i);
2061 if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) &&
2062 !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex]
2063 ) {
2064 if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
2065 skill_point += skill_lv;
2066 else
2067 if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0)
2068 skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
2069 }
2070 }
2071 }
2072
2073 return skill_point;
2074}
2075
2076
2077/*==========================================
2078 * Calculation of skill level.
2079 *------------------------------------------*/
2080int pc_calc_skilltree(struct map_session_data *sd)
2081{
2082 int i,id=0,flag;
2083 int c=0;
2084
2085 nullpo_ret(sd);
2086 i = pc_calc_skilltree_normalize_job(sd);
2087 c = pc_mapid2jobid(i, sd->status.sex);
2088 if( c == -1 )
2089 { //Unable to normalize job??
2090 ShowError("pc_calc_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id);
2091 return 1;
2092 }
2093 c = pc_class2idx(c);
2094
2095 for( i = 0; i < MAX_SKILL; i++ ) {
2096 if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these
2097 sd->status.skill[i].id = 0; //First clear skills.
2098 /* permanent skills that must be re-checked */
2099 if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) {
2100 switch( i ) {
2101 case NV_TRICKDEAD:
2102 if( (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) {
2103 sd->status.skill[i].id = 0;
2104 sd->status.skill[i].lv = 0;
2105 sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
2106 }
2107 break;
2108 }
2109 }
2110 }
2111
2112 for( i = 0; i < MAX_SKILL; i++ )
2113 {
2114 if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED )
2115 { // Restore original level of skills after deleting earned skills.
2116 sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
2117 sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
2118 }
2119
2120 if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU )
2121 { //Enable Bard/Dancer spirit linked skills.
2122 if( sd->status.sex )
2123 { //Link dancer skills to bard.
2124 if( sd->status.skill[i-8].lv < 10 )
2125 continue;
2126 sd->status.skill[i].id = i;
2127 sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill
2128 sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
2129 }
2130 else
2131 { //Link bard skills to dancer.
2132 if( sd->status.skill[i].lv < 10 )
2133 continue;
2134 sd->status.skill[i-8].id = i - 8;
2135 sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill
2136 sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
2137 }
2138 }
2139 }
2140
2141 if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) {
2142 for( i = 0; i < MAX_SKILL; i++ ) {
2143 switch(i) {
2144 /**
2145 * Dummy skills must be added here otherwise they'll be displayed in the,
2146 * skill tree and since they have no icons they'll give resource errors
2147 **/
2148 case SM_SELFPROVOKE:
2149 case AB_DUPLELIGHT_MELEE:
2150 case AB_DUPLELIGHT_MAGIC:
2151 case WL_CHAINLIGHTNING_ATK:
2152 case WL_TETRAVORTEX_FIRE:
2153 case WL_TETRAVORTEX_WATER:
2154 case WL_TETRAVORTEX_WIND:
2155 case WL_TETRAVORTEX_GROUND:
2156 case WL_SUMMON_ATK_FIRE:
2157 case WL_SUMMON_ATK_WIND:
2158 case WL_SUMMON_ATK_WATER:
2159 case WL_SUMMON_ATK_GROUND:
2160 case LG_OVERBRAND_BRANDISH:
2161 case LG_OVERBRAND_PLUSATK:
2162 case WM_SEVERE_RAINSTORM_MELEE:
2163 continue;
2164 default:
2165 break;
2166 }
2167 if( skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL) )
2168 continue; //Only skills you can't have are npc/guild ones
2169 if( skill_get_max(i) > 0 )
2170 sd->status.skill[i].id = i;
2171 }
2172 return 0;
2173 }
2174
2175 do {
2176 flag = 0;
2177 for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ )
2178 {
2179 int f;
2180 if( sd->status.skill[id].id )
2181 continue; //Skill already known.
2182
2183 f = 1;
2184 if(!battle_config.skillfree) {
2185 int j;
2186 for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) {
2187 int k;
2188 if((k=skill_tree[c][i].need[j].id))
2189 {
2190 if (sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED)
2191 k = 0; //Not learned.
2192 else
2193 if (sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
2194 k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0;
2195 else
2196 k = pc_checkskill(sd,k);
2197 if (k < skill_tree[c][i].need[j].lv)
2198 {
2199 f = 0;
2200 break;
2201 }
2202 }
2203 }
2204 if( sd->status.job_level < skill_tree[c][i].joblv ) { //We need to get the actual class in this case
2205 int class_ = pc_mapid2jobid(sd->class_, sd->status.sex);
2206 class_ = pc_class2idx(class_);
2207 if (class_ == c || (class_ != c && sd->status.job_level < skill_tree[class_][i].joblv))
2208 f = 0; // job level requirement wasn't satisfied
2209 }
2210 }
2211
2212 if( f ) {
2213 int inf2;
2214 inf2 = skill_get_inf2(id);
2215
2216 if(!sd->status.skill[id].lv && (
2217 (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
2218 inf2&INF2_WEDDING_SKILL ||
2219 (inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT])
2220 ))
2221 continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills.
2222
2223 sd->status.skill[id].id = id;
2224
2225 if(inf2&INF2_SPIRIT_SKILL) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed.
2226 sd->status.skill[id].lv = 1; // need to manually specify a skill level
2227 sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill.
2228 }
2229 flag = 1; // skill list has changed, perform another pass
2230 }
2231 }
2232 } while(flag);
2233
2234 //
2235 if( c > 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && sd->status.skill_point == 0 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) )
2236 {
2237 /* Taekwon Ranger Bonus Skill Tree
2238 ============================================
2239 - Grant All Taekwon Tree, but only as Bonus Skills in case they drop from ranking.
2240 - (c > 0) to avoid grant Novice Skill Tree in case of Skill Reset (need more logic)
2241 - (sd->status.skill_point == 0) to wait until all skill points are asigned to avoid problems with Job Change quest. */
2242
2243 for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ )
2244 {
2245 if( (skill_get_inf2(id)&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) )
2246 continue; //Do not include Quest/Wedding skills.
2247
2248 if( sd->status.skill[id].id == 0 )
2249 {
2250 sd->status.skill[id].id = id;
2251 sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill.
2252 }
2253 else if( id != NV_BASIC )
2254 {
2255 sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Remember original level
2256 }
2257
2258 sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_);
2259 }
2260 }
2261
2262 return 0;
2263}
2264
2265//Checks if you can learn a new skill after having leveled up a skill.
2266static void pc_check_skilltree(struct map_session_data *sd, int skill)
2267{
2268 int i,id=0,flag;
2269 int c=0;
2270
2271 if(battle_config.skillfree)
2272 return; //Function serves no purpose if this is set
2273
2274 i = pc_calc_skilltree_normalize_job(sd);
2275 c = pc_mapid2jobid(i, sd->status.sex);
2276 if (c == -1) { //Unable to normalize job??
2277 ShowError("pc_check_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id);
2278 return;
2279 }
2280 c = pc_class2idx(c);
2281 do {
2282 flag = 0;
2283 for( i = 0; i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0; i++ )
2284 {
2285 int j, f = 1;
2286 if( sd->status.skill[id].id ) //Already learned
2287 continue;
2288 for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ){
2289 int k = skill_tree[c][i].need[j].id;
2290 if( k != 0 ){
2291 if( sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED )
2292 k = 0; //Not learned.
2293 else
2294 if( sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
2295 k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0;
2296 else
2297 k = pc_checkskill(sd,k);
2298 if( k < skill_tree[c][i].need[j].lv )
2299 {
2300 f = 0;
2301 break;
2302 }
2303 }
2304 }
2305 if( !f )
2306 continue;
2307 if( sd->status.job_level < skill_tree[c][i].joblv )
2308 continue;
2309
2310 j = skill_get_inf2(id);
2311 if( !sd->status.skill[id].lv && (
2312 (j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
2313 j&INF2_WEDDING_SKILL ||
2314 (j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT])
2315 ) )
2316 continue; //Cannot be learned via normal means.
2317
2318 sd->status.skill[id].id = id;
2319 flag = 1;
2320 }
2321 } while(flag);
2322}
2323
2324// Make sure all the skills are in the correct condition
2325// before persisting to the backend.. [MouseJstr]
2326void pc_clean_skilltree(struct map_session_data *sd)
2327{
2328 uint16 i;
2329 for (i = 0; i < MAX_SKILL; i++){
2330 if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED)
2331 {
2332 sd->status.skill[i].id = 0;
2333 sd->status.skill[i].lv = 0;
2334 sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
2335 }
2336 else
2337 if (sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0){
2338 sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
2339 sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
2340 }
2341 }
2342}
2343
2344int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
2345{
2346 int skill_point, novice_skills;
2347 int c = sd->class_;
2348
2349 if (!battle_config.skillup_limit || pc_has_permission(sd, PC_PERM_ALL_SKILL))
2350 return c;
2351
2352 skill_point = pc_calc_skillpoint(sd);
2353
2354 novice_skills = job_info[pc_class2idx(JOB_NOVICE)].max_level[1] - 1;
2355
2356 // limit 1st class and above to novice job levels
2357 if(skill_point < novice_skills)
2358 {
2359 c = MAPID_NOVICE;
2360 }
2361 // limit 2nd class and above to first class job levels (super novices are exempt)
2362 else if ((sd->class_&JOBL_2) && (sd->class_&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE)
2363 {
2364 // regenerate change_level_2nd
2365 if (!sd->change_level_2nd)
2366 {
2367 if (sd->class_&JOBL_THIRD)
2368 {
2369 // if neither 2nd nor 3rd jobchange levels are known, we have to assume a default for 2nd
2370 if (!sd->change_level_3rd)
2371 sd->change_level_2nd = job_info[pc_class2idx(pc_mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex))].max_level[1];
2372 else
2373 sd->change_level_2nd = 1 + skill_point + sd->status.skill_point
2374 - (sd->status.job_level - 1)
2375 - (sd->change_level_3rd - 1)
2376 - novice_skills;
2377 }
2378 else
2379 {
2380 sd->change_level_2nd = 1 + skill_point + sd->status.skill_point
2381 - (sd->status.job_level - 1)
2382 - novice_skills;
2383
2384 }
2385
2386 pc_setglobalreg (sd, "jobchange_level", sd->change_level_2nd);
2387 }
2388
2389 if (skill_point < novice_skills + (sd->change_level_2nd - 1))
2390 {
2391 c &= MAPID_BASEMASK;
2392 }
2393 // limit 3rd class to 2nd class/trans job levels
2394 else if(sd->class_&JOBL_THIRD)
2395 {
2396 // regenerate change_level_3rd
2397 if (!sd->change_level_3rd)
2398 {
2399 sd->change_level_3rd = 1 + skill_point + sd->status.skill_point
2400 - (sd->status.job_level - 1)
2401 - (sd->change_level_2nd - 1)
2402 - novice_skills;
2403 pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd);
2404 }
2405
2406 if (skill_point < novice_skills + (sd->change_level_2nd - 1) + (sd->change_level_3rd - 1))
2407 c &= MAPID_UPPERMASK;
2408 }
2409 }
2410
2411 // restore non-limiting flags
2412 c |= sd->class_&(JOBL_UPPER|JOBL_BABY);
2413
2414 return c;
2415}
2416
2417/*==========================================
2418 * Updates the weight status
2419 *------------------------------------------
2420 * 1: overweight 50%
2421 * 2: overweight 90%
2422 * It's assumed that SC_WEIGHT50 and SC_WEIGHT90 are only started/stopped here.
2423 */
2424int pc_updateweightstatus(struct map_session_data *sd)
2425{
2426 int old_overweight;
2427 int new_overweight;
2428
2429 nullpo_retr(1, sd);
2430
2431 old_overweight = (sd->sc.data[SC_WEIGHT90]) ? 2 : (sd->sc.data[SC_WEIGHT50]) ? 1 : 0;
2432 new_overweight = (pc_is90overweight(sd)) ? 2 : (pc_is50overweight(sd)) ? 1 : 0;
2433
2434 if( old_overweight == new_overweight )
2435 return 0; // no change
2436
2437 // stop old status change
2438 if( old_overweight == 1 )
2439 status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER);
2440 else if( old_overweight == 2 )
2441 status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER);
2442
2443 // start new status change
2444 if( new_overweight == 1 )
2445 sc_start(&sd->bl,&sd->bl, SC_WEIGHT50, 100, 0, 0);
2446 else if( new_overweight == 2 )
2447 sc_start(&sd->bl,&sd->bl, SC_WEIGHT90, 100, 0, 0);
2448
2449 // update overweight status
2450 sd->regen.state.overweight = new_overweight;
2451
2452 return 0;
2453}
2454
2455int pc_disguise(struct map_session_data *sd, int class_)
2456{
2457 if (!class_ && !sd->disguise)
2458 return 0;
2459 if (class_ && sd->disguise == class_)
2460 return 0;
2461
2462 if(sd->sc.option&OPTION_INVISIBLE)
2463 { //Character is invisible. Stealth class-change. [Skotlex]
2464 sd->disguise = class_; //viewdata is set on uncloaking.
2465 return 2;
2466 }
2467
2468 if (sd->bl.prev != NULL) {
2469 pc_stop_walking(sd, 0);
2470 clif_clearunit_area(&sd->bl, CLR_OUTSIGHT);
2471 }
2472
2473 if (!class_) {
2474 sd->disguise = 0;
2475 class_ = sd->status.class_;
2476 } else
2477 sd->disguise=class_;
2478
2479 status_set_viewdata(&sd->bl, class_);
2480 clif_changeoption(&sd->bl);
2481
2482 if (sd->bl.prev != NULL) {
2483 clif_spawn(&sd->bl);
2484 if (class_ == sd->status.class_ && pc_iscarton(sd))
2485 { //It seems the cart info is lost on undisguise.
2486 clif_cartlist(sd);
2487 clif_updatestatus(sd,SP_CARTINFO);
2488 }
2489 if (sd->chatID) {
2490 struct chat_data* cd;
2491 nullpo_retr(1, sd);
2492 cd = (struct chat_data*)map_id2bl(sd->chatID);
2493 if( cd != NULL || (struct block_list*)sd == cd->owner )
2494 clif_dispchat(cd,0);
2495 }
2496 }
2497 return 1;
2498}
2499
2500static int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short flag, short card_id)
2501{
2502 int i;
2503
2504 if( !rate )
2505 return 0;
2506
2507 for( i = 0; i < max && spell[i].id; i++ )
2508 {
2509 if( (spell[i].card_id == card_id || spell[i].rate < 0 || rate < 0) && spell[i].id == id && spell[i].lv == lv )
2510 {
2511 if( !battle_config.autospell_stacking && spell[i].rate > 0 && rate > 0 )
2512 return 0;
2513 rate += spell[i].rate;
2514 break;
2515 }
2516 }
2517 if (i == max) {
2518 ShowWarning("pc_bonus: Reached max (%d) number of autospells per character!\n", max);
2519 return 0;
2520 }
2521 spell[i].id = id;
2522 spell[i].lv = lv;
2523 spell[i].rate = rate;
2524 //Auto-update flag value.
2525 if (!(flag&BF_RANGEMASK)) flag|=BF_SHORT|BF_LONG; //No range defined? Use both.
2526 if (!(flag&BF_WEAPONMASK)) flag|=BF_WEAPON; //No attack type defined? Use weapon.
2527 if (!(flag&BF_SKILLMASK)) {
2528 if (flag&(BF_MAGIC|BF_MISC)) flag|=BF_SKILL; //These two would never trigger without BF_SKILL
2529 if (flag&BF_WEAPON) flag|=BF_NORMAL; //By default autospells should only trigger on normal weapon attacks.
2530 }
2531 spell[i].flag|= flag;
2532 spell[i].card_id = card_id;
2533 return 1;
2534}
2535
2536static int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id)
2537{
2538 int i;
2539
2540 if( !rate )
2541 return 0;
2542
2543 for( i = 0; i < max && spell[i].id; i++ )
2544 {
2545 ; // each autospell works independently
2546 }
2547
2548 if( i == max )
2549 {
2550 ShowWarning("pc_bonus: Reached max (%d) number of autospells per character!\n", max);
2551 return 0;
2552 }
2553
2554 spell[i].flag = src_skill;
2555 spell[i].id = id;
2556 spell[i].lv = lv;
2557 spell[i].rate = rate;
2558 spell[i].card_id = card_id;
2559 return 1;
2560}
2561
2562static int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag)
2563{
2564 int i;
2565 if (!(flag&(ATF_SHORT|ATF_LONG)))
2566 flag|=ATF_SHORT|ATF_LONG; //Default range: both
2567 if (!(flag&(ATF_TARGET|ATF_SELF)))
2568 flag|=ATF_TARGET; //Default target: enemy.
2569 if (!(flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC)))
2570 flag|=ATF_WEAPON; //Default type: weapon.
2571
2572 for (i = 0; i < max && effect[i].flag; i++) {
2573 if (effect[i].id == id && effect[i].flag == flag)
2574 {
2575 effect[i].rate += rate;
2576 effect[i].arrow_rate += arrow_rate;
2577 return 1;
2578 }
2579 }
2580 if (i == max) {
2581 ShowWarning("pc_bonus: Reached max (%d) number of add effects per character!\n", max);
2582 return 0;
2583 }
2584 effect[i].id = id;
2585 effect[i].rate = rate;
2586 effect[i].arrow_rate = arrow_rate;
2587 effect[i].flag = flag;
2588 return 1;
2589}
2590
2591static int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill, unsigned char target)
2592{
2593 int i;
2594 for( i = 0; i < max && effect[i].skill; i++ )
2595 {
2596 if( effect[i].id == id && effect[i].skill == skill && effect[i].target == target )
2597 {
2598 effect[i].rate += rate;
2599 return 1;
2600 }
2601 }
2602 if( i == max ) {
2603 ShowWarning("pc_bonus: Reached max (%d) number of add effects on skill per character!\n", max);
2604 return 0;
2605 }
2606 effect[i].id = id;
2607 effect[i].rate = rate;
2608 effect[i].skill = skill;
2609 effect[i].target = target;
2610 return 1;
2611}
2612
2613/** Adjust/add drop rate modifier for player
2614* @param drop: Player's sd->add_drop (struct s_add_drop)
2615* @param max: Max bonus can be received
2616* @param nameid: item id that will be dropped
2617* @param group: group id
2618* @param class_: target class
2619* @param race: target race. if < 0, means monster_id
2620* @param rate: rate value: 1 ~ 10000. If < 0, it will be multiplied with mob level/10
2621*/
2622static void pc_bonus_item_drop(struct s_add_drop *drop, const short max, uint16 nameid, uint16 group, int class_, short race, int rate)
2623{
2624 uint8 i;
2625 if (nameid && !group && !itemdb_exists(nameid)) {
2626 ShowWarning("pc_bonus_item_drop: Invalid item id\n",nameid);
2627 return;
2628 }
2629 //Apply config rate adjustment settings.
2630 if (rate >= 0) { //Absolute drop.
2631 if (battle_config.item_rate_adddrop != 100)
2632 rate = rate*battle_config.item_rate_adddrop/100;
2633 if (rate < battle_config.item_drop_adddrop_min)
2634 rate = battle_config.item_drop_adddrop_min;
2635 else if (rate > battle_config.item_drop_adddrop_max)
2636 rate = battle_config.item_drop_adddrop_max;
2637 } else { //Relative drop, max/min limits are applied at drop time.
2638 if (battle_config.item_rate_adddrop != 100)
2639 rate = rate*battle_config.item_rate_adddrop/100;
2640 if (rate > -1)
2641 rate = -1;
2642 }
2643
2644 //Find match entry, and adjust the rate only
2645 for (i = 0; i < max; i++) {
2646 if (!&drop[i] || (!drop[i].nameid && !drop[i].group))
2647 continue;
2648 if (drop[i].nameid == nameid &&
2649 drop[i].group == group &&
2650 drop[i].race == race &&
2651 drop[i].class_ == class_
2652 )
2653 {
2654 //Adjust the rate if it has same classification
2655 if ((rate < 0 && drop[i].rate < 0) ||
2656 (rate > 0 && drop[i].rate > 0))
2657 {
2658 drop[i].rate += rate;
2659 return;
2660 }
2661 }
2662 }
2663 ARR_FIND(0,max,i,!&drop[i] || (drop[i].nameid == 0 && drop[i].group == 0));
2664 if (i >= max) {
2665 ShowWarning("pc_bonus_item_drop: Reached max (%d) number of added drops per character! (nameid:%d group:%d class_:%d race:%d rate:%d)\n",max,nameid,group,class_,race,rate);
2666 return;
2667 }
2668 drop[i].nameid = nameid;
2669 drop[i].group = group;
2670 drop[i].race = race;
2671 drop[i].class_ = class_;
2672 drop[i].rate = rate;
2673}
2674
2675bool pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short flag,const char *other_script,unsigned short pos,bool onskill)
2676{
2677 int i;
2678
2679 ARR_FIND(0, max, i, bonus[i].rate == 0);
2680 if( i == max )
2681 {
2682 ShowWarning("pc_addautobonus: Reached max (%d) number of autobonus per character!\n", max);
2683 return false;
2684 }
2685
2686 if( !onskill )
2687 {
2688 if( !(flag&BF_RANGEMASK) )
2689 flag|=BF_SHORT|BF_LONG; //No range defined? Use both.
2690 if( !(flag&BF_WEAPONMASK) )
2691 flag|=BF_WEAPON; //No attack type defined? Use weapon.
2692 if( !(flag&BF_SKILLMASK) )
2693 {
2694 if( flag&(BF_MAGIC|BF_MISC) )
2695 flag|=BF_SKILL; //These two would never trigger without BF_SKILL
2696 if( flag&BF_WEAPON )
2697 flag|=BF_NORMAL|BF_SKILL;
2698 }
2699 }
2700
2701 bonus[i].rate = rate;
2702 bonus[i].duration = dur;
2703 bonus[i].active = INVALID_TIMER;
2704 bonus[i].atk_type = flag;
2705 bonus[i].pos = pos;
2706 bonus[i].bonus_script = aStrdup(script);
2707 bonus[i].other_script = other_script?aStrdup(other_script):NULL;
2708 return true;
2709}
2710
2711void pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,char max,bool restore)
2712{
2713 int i;
2714 if (!sd)
2715 return;
2716
2717 for( i = 0; i < max; i++ )
2718 {
2719 if( autobonus[i].active != INVALID_TIMER )
2720 {
2721 if( restore && sd->state.autobonus&autobonus[i].pos )
2722 {
2723 if( autobonus[i].bonus_script )
2724 {
2725 int j;
2726 ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos );
2727 if( j < EQI_MAX )
2728 script_run_autobonus(autobonus[i].bonus_script,sd->bl.id,sd->equip_index[j]);
2729 }
2730 continue;
2731 }
2732 else
2733 { // Logout / Unequipped an item with an activated bonus
2734 delete_timer(autobonus[i].active,pc_endautobonus);
2735 autobonus[i].active = INVALID_TIMER;
2736 }
2737 }
2738
2739 if( autobonus[i].bonus_script ) aFree(autobonus[i].bonus_script);
2740 if( autobonus[i].other_script ) aFree(autobonus[i].other_script);
2741 autobonus[i].bonus_script = autobonus[i].other_script = NULL;
2742 autobonus[i].rate = autobonus[i].atk_type = autobonus[i].duration = autobonus[i].pos = 0;
2743 autobonus[i].active = INVALID_TIMER;
2744 }
2745}
2746
2747void pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus)
2748{
2749 if (!sd || !autobonus)
2750 return;
2751
2752 if( autobonus->other_script )
2753 {
2754 int j;
2755 ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos );
2756 if( j < EQI_MAX )
2757 script_run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]);
2758 }
2759
2760 autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)autobonus);
2761 sd->state.autobonus |= autobonus->pos;
2762 status_calc_pc(sd,0);
2763}
2764
2765int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data)
2766{
2767 struct map_session_data *sd = map_id2sd(id);
2768 struct s_autobonus *autobonus = (struct s_autobonus *)data;
2769
2770 nullpo_ret(sd);
2771 nullpo_ret(autobonus);
2772
2773 autobonus->active = INVALID_TIMER;
2774 sd->state.autobonus &= ~autobonus->pos;
2775 status_calc_pc(sd,0);
2776 return 0;
2777}
2778
2779int pc_bonus_addele(struct map_session_data* sd, unsigned char ele, short rate, short flag)
2780{
2781 int i;
2782 struct weapon_data* wd;
2783
2784 wd = (sd->state.lr_flag ? &sd->left_weapon : &sd->right_weapon);
2785
2786 ARR_FIND(0, MAX_PC_BONUS, i, wd->addele2[i].rate == 0);
2787
2788 if (i == MAX_PC_BONUS)
2789 {
2790 ShowWarning("pc_addele: Reached max (%d) possible bonuses for this player.\n", MAX_PC_BONUS);
2791 return 0;
2792 }
2793
2794 if (!(flag&BF_RANGEMASK))
2795 flag |= BF_SHORT|BF_LONG;
2796 if (!(flag&BF_WEAPONMASK))
2797 flag |= BF_WEAPON;
2798 if (!(flag&BF_SKILLMASK))
2799 {
2800 if (flag&(BF_MAGIC|BF_MISC))
2801 flag |= BF_SKILL;
2802 if (flag&BF_WEAPON)
2803 flag |= BF_NORMAL|BF_SKILL;
2804 }
2805
2806 wd->addele2[i].ele = ele;
2807 wd->addele2[i].rate = rate;
2808 wd->addele2[i].flag = flag;
2809
2810 return 0;
2811}
2812
2813int pc_bonus_subele(struct map_session_data* sd, unsigned char ele, short rate, short flag)
2814{
2815 int i;
2816
2817 ARR_FIND(0, MAX_PC_BONUS, i, sd->subele2[i].rate == 0);
2818
2819 if (i == MAX_PC_BONUS)
2820 {
2821 ShowWarning("pc_subele: Reached max (%d) possible bonuses for this player.\n", MAX_PC_BONUS);
2822 return 0;
2823 }
2824
2825 if (!(flag&BF_RANGEMASK))
2826 flag |= BF_SHORT|BF_LONG;
2827 if (!(flag&BF_WEAPONMASK))
2828 flag |= BF_WEAPON;
2829 if (!(flag&BF_SKILLMASK))
2830 {
2831 if (flag&(BF_MAGIC|BF_MISC))
2832 flag |= BF_SKILL;
2833 if (flag&BF_WEAPON)
2834 flag |= BF_NORMAL|BF_SKILL;
2835 }
2836
2837 sd->subele2[i].ele = ele;
2838 sd->subele2[i].rate = rate;
2839 sd->subele2[i].flag = flag;
2840
2841 return 0;
2842}
2843
2844/*==========================================
2845 * Add a bonus(type) to player sd
2846 *------------------------------------------*/
2847int pc_bonus(struct map_session_data *sd,int type,int val)
2848{
2849 struct status_data *status;
2850 int bonus;
2851 nullpo_ret(sd);
2852
2853 status = &sd->base_status;
2854
2855 switch(type){
2856 case SP_STR:
2857 case SP_AGI:
2858 case SP_VIT:
2859 case SP_INT:
2860 case SP_DEX:
2861 case SP_LUK:
2862 if(sd->state.lr_flag != 2)
2863 sd->param_bonus[type-SP_STR]+=val;
2864 break;
2865 case SP_ATK1:
2866 if(!sd->state.lr_flag) {
2867 bonus = status->rhw.atk + val;
2868 status->rhw.atk = cap_value(bonus, 0, USHRT_MAX);
2869 }
2870 else if(sd->state.lr_flag == 1) {
2871 bonus = status->lhw.atk + val;
2872 status->lhw.atk = cap_value(bonus, 0, USHRT_MAX);
2873 }
2874 break;
2875 case SP_ATK2:
2876 if(!sd->state.lr_flag) {
2877 bonus = status->rhw.atk2 + val;
2878 status->rhw.atk2 = cap_value(bonus, 0, USHRT_MAX);
2879 }
2880 else if(sd->state.lr_flag == 1) {
2881 bonus = status->lhw.atk2 + val;
2882 status->lhw.atk2 = cap_value(bonus, 0, USHRT_MAX);
2883 }
2884 break;
2885 case SP_BASE_ATK:
2886 if(sd->state.lr_flag != 2) {
2887 #ifdef RENEWAL
2888 sd->bonus.eatk += val;
2889 #else
2890 bonus = status->batk + val;
2891 status->batk = cap_value(bonus, 0, USHRT_MAX);
2892 #endif
2893 }
2894 break;
2895 case SP_DEF1:
2896 if(sd->state.lr_flag != 2) {
2897 bonus = status->def + val;
2898 #ifdef RENEWAL
2899 status->def = cap_value(bonus, SHRT_MIN, SHRT_MAX);
2900 #else
2901 status->def = cap_value(bonus, CHAR_MIN, CHAR_MAX);
2902 #endif
2903 }
2904 break;
2905 case SP_DEF2:
2906 if(sd->state.lr_flag != 2) {
2907 bonus = status->def2 + val;
2908 status->def2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
2909 }
2910 break;
2911 case SP_MDEF1:
2912 if(sd->state.lr_flag != 2) {
2913 bonus = status->mdef + val;
2914 #ifdef RENEWAL
2915 status->mdef = cap_value(bonus, SHRT_MIN, SHRT_MAX);
2916 #else
2917 status->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX);
2918 #endif
2919 if( sd->state.lr_flag == 3 ) {//Shield, used for royal guard
2920 sd->bonus.shieldmdef += bonus;
2921 }
2922 }
2923 break;
2924 case SP_MDEF2:
2925 if(sd->state.lr_flag != 2) {
2926 bonus = status->mdef2 + val;
2927 status->mdef2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
2928 }
2929 break;
2930 case SP_HIT:
2931 if(sd->state.lr_flag != 2) {
2932 bonus = status->hit + val;
2933 status->hit = cap_value(bonus, SHRT_MIN, SHRT_MAX);
2934 } else
2935 sd->bonus.arrow_hit+=val;
2936 break;
2937 case SP_FLEE1:
2938 if(sd->state.lr_flag != 2) {
2939 bonus = status->flee + val;
2940 status->flee = cap_value(bonus, SHRT_MIN, SHRT_MAX);
2941 }
2942 break;
2943 case SP_FLEE2:
2944 if(sd->state.lr_flag != 2) {
2945 bonus = status->flee2 + val*10;
2946 status->flee2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
2947 }
2948 break;
2949 case SP_CRITICAL:
2950 if(sd->state.lr_flag != 2) {
2951 bonus = status->cri + val*10;
2952 status->cri = cap_value(bonus, SHRT_MIN, SHRT_MAX);
2953 } else
2954 sd->bonus.arrow_cri += val*10;
2955 break;
2956 case SP_ATKELE:
2957 if(val > ELE_ALL) {
2958 ShowError("pc_bonus: SP_ATKELE: Invalid element %d\n", val);
2959 break;
2960 }
2961 switch (sd->state.lr_flag)
2962 {
2963 case 2:
2964 switch (sd->status.weapon) {
2965 case W_BOW:
2966 case W_REVOLVER:
2967 case W_RIFLE:
2968 case W_GATLING:
2969 case W_SHOTGUN:
2970 case W_GRENADE:
2971 //Become weapon element.
2972 status->rhw.ele=val;
2973 break;
2974 default: //Become arrow element.
2975 sd->bonus.arrow_ele=val;
2976 break;
2977 }
2978 break;
2979 case 1:
2980 status->lhw.ele=val;
2981 break;
2982 default:
2983 status->rhw.ele=val;
2984 break;
2985 }
2986 break;
2987 case SP_DEFELE:
2988 if(val > ELE_ALL) {
2989 ShowError("pc_bonus: SP_DEFELE: Invalid element %d\n", val);
2990 break;
2991 }
2992 if(sd->state.lr_flag != 2)
2993 status->def_ele=val;
2994 break;
2995 case SP_MAXHP:
2996 if(sd->state.lr_flag == 2)
2997 break;
2998 sd->bonus.hp += val;
2999 break;
3000 case SP_MAXSP:
3001 if(sd->state.lr_flag == 2)
3002 break;
3003 sd->bonus.sp += val;
3004 break;
3005 #ifndef RENEWAL_CAST
3006 case SP_VARCASTRATE:
3007 #endif
3008 case SP_CASTRATE:
3009 if(sd->state.lr_flag != 2)
3010 sd->castrate+=val;
3011 break;
3012 case SP_MAXHPRATE:
3013 if(sd->state.lr_flag != 2)
3014 sd->hprate+=val;
3015 break;
3016 case SP_MAXSPRATE:
3017 if(sd->state.lr_flag != 2)
3018 sd->sprate+=val;
3019 break;
3020 case SP_SPRATE:
3021 if(sd->state.lr_flag != 2)
3022 sd->dsprate+=val;
3023 break;
3024 case SP_ATTACKRANGE:
3025 switch (sd->state.lr_flag) {
3026 case 2:
3027 switch (sd->status.weapon) {
3028 case W_BOW:
3029 case W_REVOLVER:
3030 case W_RIFLE:
3031 case W_GATLING:
3032 case W_SHOTGUN:
3033 case W_GRENADE:
3034 status->rhw.range += val;
3035 }
3036 break;
3037 case 1:
3038 status->lhw.range += val;
3039 break;
3040 default:
3041 status->rhw.range += val;
3042 break;
3043 }
3044 break;
3045 case SP_SPEED_RATE: //Non stackable increase
3046 if(sd->state.lr_flag != 2)
3047 sd->bonus.speed_rate = min(sd->bonus.speed_rate, -val);
3048 break;
3049 case SP_SPEED_ADDRATE: //Stackable increase
3050 if(sd->state.lr_flag != 2)
3051 sd->bonus.speed_add_rate -= val;
3052 break;
3053 case SP_ASPD: //Raw increase
3054 if(sd->state.lr_flag != 2)
3055 sd->bonus.aspd_add -= 10*val;
3056 break;
3057 case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone
3058 if(sd->state.lr_flag != 2)
3059 #ifndef RENEWAL_ASPD
3060 status->aspd_rate -= 10*val;
3061 #else
3062 status->aspd_rate2 += val;
3063 #endif
3064 break;
3065 case SP_HP_RECOV_RATE:
3066 if(sd->state.lr_flag != 2)
3067 sd->hprecov_rate += val;
3068 break;
3069 case SP_SP_RECOV_RATE:
3070 if(sd->state.lr_flag != 2)
3071 sd->sprecov_rate += val;
3072 break;
3073 case SP_CRITICAL_DEF:
3074 if(sd->state.lr_flag != 2)
3075 sd->bonus.critical_def += val;
3076 break;
3077 case SP_NEAR_ATK_DEF:
3078 if(sd->state.lr_flag != 2)
3079 sd->bonus.near_attack_def_rate += val;
3080 break;
3081 case SP_LONG_ATK_DEF:
3082 if(sd->state.lr_flag != 2)
3083 sd->bonus.long_attack_def_rate += val;
3084 break;
3085 case SP_DOUBLE_RATE:
3086 if(sd->state.lr_flag == 0 && sd->bonus.double_rate < val)
3087 sd->bonus.double_rate = val;
3088 break;
3089 case SP_DOUBLE_ADD_RATE:
3090 if(sd->state.lr_flag == 0)
3091 sd->bonus.double_add_rate += val;
3092 break;
3093 case SP_MATK_RATE:
3094 if(sd->state.lr_flag != 2)
3095 sd->matk_rate += val;
3096 break;
3097 case SP_IGNORE_DEF_ELE:
3098 if(val > ELE_ALL) {
3099 ShowError("pc_bonus: SP_IGNORE_DEF_ELE: Invalid element %d\n", val);
3100 break;
3101 }
3102 if(!sd->state.lr_flag)
3103 sd->right_weapon.ignore_def_ele |= 1<<val;
3104 else if(sd->state.lr_flag == 1)
3105 sd->left_weapon.ignore_def_ele |= 1<<val;
3106 break;
3107 case SP_IGNORE_DEF_RACE:
3108 if(!sd->state.lr_flag)
3109 sd->right_weapon.ignore_def_race |= 1<<val;
3110 else if(sd->state.lr_flag == 1)
3111 sd->left_weapon.ignore_def_race |= 1<<val;
3112 break;
3113 case SP_IGNORE_DEF_CLASS:
3114 if(!sd->state.lr_flag)
3115 sd->right_weapon.ignore_def_class |= 1<<val;
3116 else if(sd->state.lr_flag == 1)
3117 sd->left_weapon.ignore_def_class |= 1<<val;
3118 break;
3119 case SP_ATK_RATE:
3120 if(sd->state.lr_flag != 2)
3121 sd->bonus.atk_rate += val;
3122 break;
3123 case SP_MAGIC_ATK_DEF:
3124 if(sd->state.lr_flag != 2)
3125 sd->bonus.magic_def_rate += val;
3126 break;
3127 case SP_MISC_ATK_DEF:
3128 if(sd->state.lr_flag != 2)
3129 sd->bonus.misc_def_rate += val;
3130 break;
3131 case SP_IGNORE_MDEF_ELE:
3132 if(val > ELE_ALL) {
3133 ShowError("pc_bonus: SP_IGNORE_MDEF_ELE: Invalid element %d\n", val);
3134 break;
3135 }
3136 if(sd->state.lr_flag != 2)
3137 sd->bonus.ignore_mdef_ele |= 1<<val;
3138 break;
3139 case SP_IGNORE_MDEF_RACE:
3140 if(sd->state.lr_flag != 2)
3141 sd->bonus.ignore_mdef_race |= 1<<val;
3142 break;
3143 case SP_PERFECT_HIT_RATE:
3144 if(sd->state.lr_flag != 2 && sd->bonus.perfect_hit < val)
3145 sd->bonus.perfect_hit = val;
3146 break;
3147 case SP_PERFECT_HIT_ADD_RATE:
3148 if(sd->state.lr_flag != 2)
3149 sd->bonus.perfect_hit_add += val;
3150 break;
3151 case SP_CRITICAL_RATE:
3152 if(sd->state.lr_flag != 2)
3153 sd->critical_rate+=val;
3154 break;
3155 case SP_DEF_RATIO_ATK_ELE:
3156 if(val > ELE_ALL) {
3157 ShowError("pc_bonus: SP_DEF_RATIO_ATK_ELE: Invalid element %d\n", val);
3158 break;
3159 }
3160 if(!sd->state.lr_flag)
3161 sd->right_weapon.def_ratio_atk_ele |= 1<<val;
3162 else if(sd->state.lr_flag == 1)
3163 sd->left_weapon.def_ratio_atk_ele |= 1<<val;
3164 break;
3165 case SP_DEF_RATIO_ATK_RACE:
3166 if(val > RC_ALL) {
3167 ShowError("pc_bonus: SP_DEF_RATIO_ATK_RACE: Invalid race %d\n", val);
3168 break;
3169 }
3170 if(!sd->state.lr_flag)
3171 sd->right_weapon.def_ratio_atk_race |= 1<<val;
3172 else if(sd->state.lr_flag == 1)
3173 sd->left_weapon.def_ratio_atk_race |= 1<<val;
3174 break;
3175 case SP_DEF_RATIO_ATK_CLASS:
3176 if(val > CLASS_ALL) {
3177 ShowError("pc_bonus: SP_DEF_RATIO_ATK_CLASS: Invalid class %d\n", val);
3178 break;
3179 }
3180 if(!sd->state.lr_flag)
3181 sd->right_weapon.def_ratio_atk_class |= 1<<val;
3182 else if(sd->state.lr_flag == 1)
3183 sd->left_weapon.def_ratio_atk_class |= 1<<val;
3184 break;
3185 case SP_HIT_RATE:
3186 if(sd->state.lr_flag != 2)
3187 sd->hit_rate += val;
3188 break;
3189 case SP_FLEE_RATE:
3190 if(sd->state.lr_flag != 2)
3191 sd->flee_rate += val;
3192 break;
3193 case SP_FLEE2_RATE:
3194 if(sd->state.lr_flag != 2)
3195 sd->flee2_rate += val;
3196 break;
3197 case SP_DEF_RATE:
3198 if(sd->state.lr_flag != 2)
3199 sd->def_rate += val;
3200 break;
3201 case SP_DEF2_RATE:
3202 if(sd->state.lr_flag != 2)
3203 sd->def2_rate += val;
3204 break;
3205 case SP_MDEF_RATE:
3206 if(sd->state.lr_flag != 2)
3207 sd->mdef_rate += val;
3208 break;
3209 case SP_MDEF2_RATE:
3210 if(sd->state.lr_flag != 2)
3211 sd->mdef2_rate += val;
3212 break;
3213 case SP_RESTART_FULL_RECOVER:
3214 if(sd->state.lr_flag != 2)
3215 sd->special_state.restart_full_recover = 1;
3216 break;
3217 case SP_NO_CASTCANCEL:
3218 if(sd->state.lr_flag != 2)
3219 sd->special_state.no_castcancel = 1;
3220 break;
3221 case SP_NO_CASTCANCEL2:
3222 if(sd->state.lr_flag != 2)
3223 sd->special_state.no_castcancel2 = 1;
3224 break;
3225 case SP_NO_SIZEFIX:
3226 if(sd->state.lr_flag != 2)
3227 sd->special_state.no_sizefix = 1;
3228 break;
3229 case SP_NO_MAGIC_DAMAGE:
3230 if(sd->state.lr_flag == 2)
3231 break;
3232 val+= sd->special_state.no_magic_damage;
3233 sd->special_state.no_magic_damage = cap_value(val,0,100);
3234 break;
3235 case SP_NO_WEAPON_DAMAGE:
3236 if(sd->state.lr_flag == 2)
3237 break;
3238 val+= sd->special_state.no_weapon_damage;
3239 sd->special_state.no_weapon_damage = cap_value(val,0,100);
3240 break;
3241 case SP_NO_MISC_DAMAGE:
3242 if(sd->state.lr_flag == 2)
3243 break;
3244 val+= sd->special_state.no_misc_damage;
3245 sd->special_state.no_misc_damage = cap_value(val,0,100);
3246 break;
3247 case SP_NO_GEMSTONE:
3248 if(sd->state.lr_flag != 2 && sd->special_state.no_gemstone != 2)
3249 sd->special_state.no_gemstone = 1;
3250 break;
3251 case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG]
3252 if(sd->state.lr_flag != 2) {
3253 sd->special_state.intravision = 1;
3254 clif_status_load(&sd->bl, SI_INTRAVISION, 1);
3255 if( battle_config.anti_mayapurple_hack ) map_foreachinrange(clif_insight_bl2tbl, &sd->bl, AREA_SIZE, BL_PC, &sd->bl);
3256 }
3257 break;
3258 case SP_NO_KNOCKBACK:
3259 if(sd->state.lr_flag != 2)
3260 sd->special_state.no_knockback = 1;
3261 break;
3262 case SP_SPLASH_RANGE:
3263 if(sd->bonus.splash_range < val)
3264 sd->bonus.splash_range = val;
3265 break;
3266 case SP_SPLASH_ADD_RANGE:
3267 sd->bonus.splash_add_range += val;
3268 break;
3269 case SP_SHORT_WEAPON_DAMAGE_RETURN:
3270 if(sd->state.lr_flag != 2)
3271 sd->bonus.short_weapon_damage_return += val;
3272 break;
3273 case SP_LONG_WEAPON_DAMAGE_RETURN:
3274 if(sd->state.lr_flag != 2)
3275 sd->bonus.long_weapon_damage_return += val;
3276 break;
3277 case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here
3278 if(sd->state.lr_flag != 2)
3279 sd->bonus.magic_damage_return += val;
3280 break;
3281 case SP_ALL_STATS: // [Valaris]
3282 if(sd->state.lr_flag!=2) {
3283 sd->param_bonus[SP_STR-SP_STR]+=val;
3284 sd->param_bonus[SP_AGI-SP_STR]+=val;
3285 sd->param_bonus[SP_VIT-SP_STR]+=val;
3286 sd->param_bonus[SP_INT-SP_STR]+=val;
3287 sd->param_bonus[SP_DEX-SP_STR]+=val;
3288 sd->param_bonus[SP_LUK-SP_STR]+=val;
3289 }
3290 break;
3291 case SP_AGI_VIT: // [Valaris]
3292 if(sd->state.lr_flag!=2) {
3293 sd->param_bonus[SP_AGI-SP_STR]+=val;
3294 sd->param_bonus[SP_VIT-SP_STR]+=val;
3295 }
3296 break;
3297 case SP_AGI_DEX_STR: // [Valaris]
3298 if(sd->state.lr_flag!=2) {
3299 sd->param_bonus[SP_AGI-SP_STR]+=val;
3300 sd->param_bonus[SP_DEX-SP_STR]+=val;
3301 sd->param_bonus[SP_STR-SP_STR]+=val;
3302 }
3303 break;
3304 case SP_PERFECT_HIDE: // [Valaris]
3305 if(sd->state.lr_flag!=2)
3306 sd->special_state.perfect_hiding=1;
3307 break;
3308 case SP_UNBREAKABLE:
3309 if(sd->state.lr_flag!=2)
3310 sd->bonus.unbreakable += val;
3311 break;
3312 case SP_UNBREAKABLE_WEAPON:
3313 if(sd->state.lr_flag != 2)
3314 sd->bonus.unbreakable_equip |= EQP_WEAPON;
3315 break;
3316 case SP_UNBREAKABLE_ARMOR:
3317 if(sd->state.lr_flag != 2)
3318 sd->bonus.unbreakable_equip |= EQP_ARMOR;
3319 break;
3320 case SP_UNBREAKABLE_HELM:
3321 if(sd->state.lr_flag != 2)
3322 sd->bonus.unbreakable_equip |= EQP_HELM;
3323 break;
3324 case SP_UNBREAKABLE_SHIELD:
3325 if(sd->state.lr_flag != 2)
3326 sd->bonus.unbreakable_equip |= EQP_SHIELD;
3327 break;
3328 case SP_UNBREAKABLE_GARMENT:
3329 if(sd->state.lr_flag != 2)
3330 sd->bonus.unbreakable_equip |= EQP_GARMENT;
3331 break;
3332 case SP_UNBREAKABLE_SHOES:
3333 if(sd->state.lr_flag != 2)
3334 sd->bonus.unbreakable_equip |= EQP_SHOES;
3335 break;
3336 case SP_CLASSCHANGE: // [Valaris]
3337 if(sd->state.lr_flag !=2)
3338 sd->bonus.classchange=val;
3339 break;
3340 case SP_LONG_ATK_RATE:
3341 if(sd->state.lr_flag != 2) //[Lupus] it should stack, too. As any other cards rate bonuses
3342 sd->bonus.long_attack_atk_rate+=val;
3343 break;
3344 case SP_BREAK_WEAPON_RATE:
3345 if(sd->state.lr_flag != 2)
3346 sd->bonus.break_weapon_rate+=val;
3347 break;
3348 case SP_BREAK_ARMOR_RATE:
3349 if(sd->state.lr_flag != 2)
3350 sd->bonus.break_armor_rate+=val;
3351 break;
3352 case SP_ADD_STEAL_RATE:
3353 if(sd->state.lr_flag != 2)
3354 sd->bonus.add_steal_rate+=val;
3355 break;
3356 case SP_DELAYRATE:
3357 if(sd->state.lr_flag != 2)
3358 sd->delayrate+=val;
3359 break;
3360 case SP_CRIT_ATK_RATE:
3361 if(sd->state.lr_flag != 2)
3362 sd->bonus.crit_atk_rate += val;
3363 break;
3364 case SP_NO_REGEN:
3365 if(sd->state.lr_flag != 2)
3366 sd->regen.state.block|=val;
3367 break;
3368 case SP_UNSTRIPABLE_WEAPON:
3369 if(sd->state.lr_flag != 2)
3370 sd->bonus.unstripable_equip |= EQP_WEAPON;
3371 break;
3372 case SP_UNSTRIPABLE:
3373 case SP_UNSTRIPABLE_ARMOR:
3374 if(sd->state.lr_flag != 2)
3375 sd->bonus.unstripable_equip |= EQP_ARMOR;
3376 break;
3377 case SP_UNSTRIPABLE_HELM:
3378 if(sd->state.lr_flag != 2)
3379 sd->bonus.unstripable_equip |= EQP_HELM;
3380 break;
3381 case SP_UNSTRIPABLE_SHIELD:
3382 if(sd->state.lr_flag != 2)
3383 sd->bonus.unstripable_equip |= EQP_SHIELD;
3384 break;
3385 case SP_HP_DRAIN_VALUE:
3386 if(!sd->state.lr_flag) {
3387 sd->right_weapon.hp_drain_class[CLASS_NORMAL].value += val;
3388 sd->right_weapon.hp_drain_class[CLASS_BOSS].value += val;
3389 } else if(sd->state.lr_flag == 1) {
3390 sd->left_weapon.hp_drain_class[CLASS_NORMAL].value += val;
3391 sd->left_weapon.hp_drain_class[CLASS_BOSS].value += val;
3392 }
3393 break;
3394 case SP_SP_DRAIN_VALUE:
3395 if(!sd->state.lr_flag) {
3396 sd->right_weapon.sp_drain_class[CLASS_NORMAL].value += val;
3397 sd->right_weapon.sp_drain_class[CLASS_BOSS].value += val;
3398 } else if(sd->state.lr_flag == 1) {
3399 sd->left_weapon.sp_drain_class[CLASS_NORMAL].value += val;
3400 sd->left_weapon.sp_drain_class[CLASS_BOSS].value += val;
3401 }
3402 break;
3403 case SP_SP_GAIN_VALUE:
3404 if(!sd->state.lr_flag)
3405 sd->bonus.sp_gain_value += val;
3406 break;
3407 case SP_HP_GAIN_VALUE:
3408 if(!sd->state.lr_flag)
3409 sd->bonus.hp_gain_value += val;
3410 break;
3411 case SP_MAGIC_SP_GAIN_VALUE:
3412 if(!sd->state.lr_flag)
3413 sd->bonus.magic_sp_gain_value += val;
3414 break;
3415 case SP_MAGIC_HP_GAIN_VALUE:
3416 if(!sd->state.lr_flag)
3417 sd->bonus.magic_hp_gain_value += val;
3418 break;
3419 case SP_ADD_HEAL_RATE:
3420 if(sd->state.lr_flag != 2)
3421 sd->bonus.add_heal_rate += val;
3422 break;
3423 case SP_ADD_HEAL2_RATE:
3424 if(sd->state.lr_flag != 2)
3425 sd->bonus.add_heal2_rate += val;
3426 break;
3427 case SP_ADD_ITEM_HEAL_RATE:
3428 if(sd->state.lr_flag != 2)
3429 sd->bonus.itemhealrate2 += val;
3430 break;
3431 case SP_EMATK:
3432 if(sd->state.lr_flag != 2)
3433 sd->bonus.ematk += val;
3434 break;
3435 case SP_FIXCASTRATE:
3436 if(sd->state.lr_flag != 2)
3437 sd->bonus.fixcastrate -= val;
3438 break;
3439 case SP_ADD_FIXEDCAST:
3440 if(sd->state.lr_flag != 2)
3441 sd->bonus.add_fixcast += val;
3442 break;
3443 #ifdef RENEWAL_CAST
3444 case SP_VARCASTRATE:
3445 if(sd->state.lr_flag != 2)
3446 sd->bonus.varcastrate -= val;
3447 break;
3448 case SP_ADD_VARIABLECAST:
3449 if(sd->state.lr_flag != 2)
3450 sd->bonus.add_varcast += val;
3451 break;
3452 #endif
3453 case SP_MAXWEIGHT: // eAmod
3454 case SP_ADDMAXWEIGHT:
3455 if (sd->state.lr_flag != 2)
3456 sd->max_weight += val;
3457 break;
3458 default:
3459 ShowWarning("pc_bonus: unknown type %d %d !\n",type,val);
3460 break;
3461 }
3462 return 0;
3463}
3464
3465/*==========================================
3466 * Player bonus (type) with args type2 and val, called trough bonus2 (npc)
3467 *------------------------------------------*/
3468int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
3469{
3470 int i;
3471
3472 nullpo_ret(sd);
3473
3474 switch(type){
3475 case SP_ADDELE:
3476 if(type2 > ELE_ALL) {
3477 ShowError("pc_bonus2: SP_ADDELE: Invalid element %d\n", type2);
3478 break;
3479 }
3480 if(!sd->state.lr_flag)
3481 sd->right_weapon.addele[type2]+=val;
3482 else if(sd->state.lr_flag == 1)
3483 sd->left_weapon.addele[type2]+=val;
3484 else if(sd->state.lr_flag == 2)
3485 sd->arrow_addele[type2]+=val;
3486 break;
3487 case SP_ADDRACE:
3488 if(!sd->state.lr_flag)
3489 sd->right_weapon.addrace[type2]+=val;
3490 else if(sd->state.lr_flag == 1)
3491 sd->left_weapon.addrace[type2]+=val;
3492 else if(sd->state.lr_flag == 2)
3493 sd->arrow_addrace[type2]+=val;
3494 break;
3495 case SP_ADDCLASS:
3496 if(!sd->state.lr_flag)
3497 sd->right_weapon.addclass[type2]+=val;
3498 else if(sd->state.lr_flag == 1)
3499 sd->left_weapon.addclass[type2]+=val;
3500 else if(sd->state.lr_flag == 2)
3501 sd->arrow_addclass[type2]+=val;
3502 break;
3503 case SP_ADDSIZE:
3504 if(!sd->state.lr_flag)
3505 sd->right_weapon.addsize[type2]+=val;
3506 else if(sd->state.lr_flag == 1)
3507 sd->left_weapon.addsize[type2]+=val;
3508 else if(sd->state.lr_flag == 2)
3509 sd->arrow_addsize[type2]+=val;
3510 break;
3511 case SP_SUBELE:
3512 if(type2 > ELE_ALL) {
3513 ShowError("pc_bonus2: SP_SUBELE: Invalid element %d\n", type2);
3514 break;
3515 }
3516 if(sd->state.lr_flag != 2)
3517 sd->subele[type2]+=val;
3518 break;
3519 case SP_SUBRACE:
3520 if(sd->state.lr_flag != 2)
3521 sd->subrace[type2]+=val;
3522 break;
3523 case SP_SUBCLASS:
3524 if(sd->state.lr_flag != 2)
3525 sd->subclass[type2]+=val;
3526 break;
3527 case SP_ADDEFF:
3528 if (type2 > SC_MAX) {
3529 ShowWarning("pc_bonus2 (Add Effect): %d is not supported.\n", type2);
3530 break;
3531 }
3532 pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2,
3533 sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, 0);
3534 break;
3535 case SP_ADDEFF2:
3536 if (type2 > SC_MAX) {
3537 ShowWarning("pc_bonus2 (Add Effect2): %d is not supported.\n", type2);
3538 break;
3539 }
3540 pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2,
3541 sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, ATF_SELF);
3542 break;
3543 case SP_RESEFF:
3544 if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) {
3545 ShowWarning("pc_bonus2 (Resist Effect): %d is not supported.\n", type2);
3546 break;
3547 }
3548 if(sd->state.lr_flag == 2)
3549 break;
3550 i = sd->reseff[type2-SC_COMMON_MIN]+val;
3551 sd->reseff[type2-SC_COMMON_MIN]= cap_value(i, 0, 10000);
3552 break;
3553 case SP_MAGIC_ADDELE:
3554 if(type2 > ELE_ALL) {
3555 ShowError("pc_bonus2: SP_MAGIC_ADDELE: Invalid element %d\n", type2);
3556 break;
3557 }
3558 if(sd->state.lr_flag != 2)
3559 sd->magic_addele[type2]+=val;
3560 break;
3561 case SP_MAGIC_ADDRACE:
3562 if(sd->state.lr_flag != 2)
3563 sd->magic_addrace[type2]+=val;
3564 break;
3565 case SP_MAGIC_ADDCLASS:
3566 if(sd->state.lr_flag != 2)
3567 sd->magic_addclass[type2]+=val;
3568 break;
3569 case SP_MAGIC_ADDSIZE:
3570 if(sd->state.lr_flag != 2)
3571 sd->magic_addsize[type2]+=val;
3572 break;
3573 case SP_MAGIC_ATK_ELE:
3574 if(sd->state.lr_flag != 2)
3575 sd->magic_atk_ele[type2]+=val;
3576 break;
3577 case SP_ADD_DAMAGE_CLASS:
3578 switch (sd->state.lr_flag) {
3579 case 0: //Right hand
3580 ARR_FIND(0, ARRAYLENGTH(sd->right_weapon.add_dmg), i, sd->right_weapon.add_dmg[i].rate == 0 || sd->right_weapon.add_dmg[i].class_ == type2);
3581 if (i == ARRAYLENGTH(sd->right_weapon.add_dmg))
3582 {
3583 ShowWarning("pc_bonus2: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->right_weapon.add_dmg));
3584 break;
3585 }
3586 sd->right_weapon.add_dmg[i].class_ = type2;
3587 sd->right_weapon.add_dmg[i].rate += val;
3588 if (!sd->right_weapon.add_dmg[i].rate) //Shift the rest of elements up.
3589 memmove(&sd->right_weapon.add_dmg[i], &sd->right_weapon.add_dmg[i+1], sizeof(sd->right_weapon.add_dmg) - (i+1)*sizeof(sd->right_weapon.add_dmg[0]));
3590 break;
3591 case 1: //Left hand
3592 ARR_FIND(0, ARRAYLENGTH(sd->left_weapon.add_dmg), i, sd->left_weapon.add_dmg[i].rate == 0 || sd->left_weapon.add_dmg[i].class_ == type2);
3593 if (i == ARRAYLENGTH(sd->left_weapon.add_dmg))
3594 {
3595 ShowWarning("pc_bonus2: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->left_weapon.add_dmg));
3596 break;
3597 }
3598 sd->left_weapon.add_dmg[i].class_ = type2;
3599 sd->left_weapon.add_dmg[i].rate += val;
3600 if (!sd->left_weapon.add_dmg[i].rate) //Shift the rest of elements up.
3601 memmove(&sd->left_weapon.add_dmg[i], &sd->left_weapon.add_dmg[i+1], sizeof(sd->left_weapon.add_dmg) - (i+1)*sizeof(sd->left_weapon.add_dmg[0]));
3602 break;
3603 }
3604 break;
3605 case SP_ADD_MAGIC_DAMAGE_CLASS:
3606 if(sd->state.lr_flag == 2)
3607 break;
3608 ARR_FIND(0, ARRAYLENGTH(sd->add_mdmg), i, sd->add_mdmg[i].rate == 0 || sd->add_mdmg[i].class_ == type2);
3609 if (i == ARRAYLENGTH(sd->add_mdmg))
3610 {
3611 ShowWarning("pc_bonus2: Reached max (%d) number of add Class magic dmg bonuses per character!\n", ARRAYLENGTH(sd->add_mdmg));
3612 break;
3613 }
3614 sd->add_mdmg[i].class_ = type2;
3615 sd->add_mdmg[i].rate += val;
3616 if (!sd->add_mdmg[i].rate) //Shift the rest of elements up.
3617 memmove(&sd->add_mdmg[i], &sd->add_mdmg[i+1], sizeof(sd->add_mdmg) - (i+1)*sizeof(sd->add_mdmg[0]));
3618 break;
3619 case SP_ADD_DEF_MONSTER:
3620 if(sd->state.lr_flag == 2)
3621 break;
3622 ARR_FIND(0, ARRAYLENGTH(sd->add_def), i, sd->add_def[i].rate == 0 || sd->add_def[i].class_ == type2);
3623 if (i == ARRAYLENGTH(sd->add_def))
3624 {
3625 ShowWarning("pc_bonus2: Reached max (%d) number of add Class def bonuses per character!\n", ARRAYLENGTH(sd->add_def));
3626 break;
3627 }
3628 sd->add_def[i].class_ = type2;
3629 sd->add_def[i].rate += val;
3630 if (!sd->add_def[i].rate) //Shift the rest of elements up.
3631 memmove(&sd->add_def[i], &sd->add_def[i+1], sizeof(sd->add_def) - (i+1)*sizeof(sd->add_def[0]));
3632 break;
3633 case SP_ADD_MDEF_MONSTER:
3634 if(sd->state.lr_flag == 2)
3635 break;
3636 ARR_FIND(0, ARRAYLENGTH(sd->add_mdef), i, sd->add_mdef[i].rate == 0 || sd->add_mdef[i].class_ == type2);
3637 if (i == ARRAYLENGTH(sd->add_mdef))
3638 {
3639 ShowWarning("pc_bonus2: Reached max (%d) number of add Class mdef bonuses per character!\n", ARRAYLENGTH(sd->add_mdef));
3640 break;
3641 }
3642 sd->add_mdef[i].class_ = type2;
3643 sd->add_mdef[i].rate += val;
3644 if (!sd->add_mdef[i].rate) //Shift the rest of elements up.
3645 memmove(&sd->add_mdef[i], &sd->add_mdef[i+1], sizeof(sd->add_mdef) - (i+1)*sizeof(sd->add_mdef[0]));
3646 break;
3647 case SP_HP_DRAIN_RATE:
3648 if(!sd->state.lr_flag) {
3649 sd->right_weapon.hp_drain_class[CLASS_NORMAL].rate += type2;
3650 sd->right_weapon.hp_drain_class[CLASS_NORMAL].per += val;
3651 sd->right_weapon.hp_drain_class[CLASS_BOSS].rate += type2;
3652 sd->right_weapon.hp_drain_class[CLASS_BOSS].per += val;
3653 }
3654 else if(sd->state.lr_flag == 1) {
3655 sd->left_weapon.hp_drain_class[CLASS_NORMAL].rate += type2;
3656 sd->left_weapon.hp_drain_class[CLASS_NORMAL].per += val;
3657 sd->left_weapon.hp_drain_class[CLASS_BOSS].rate += type2;
3658 sd->left_weapon.hp_drain_class[CLASS_BOSS].per += val;
3659 }
3660 break;
3661 case SP_HP_DRAIN_VALUE:
3662 if(!sd->state.lr_flag) {
3663 sd->right_weapon.hp_drain_class[CLASS_NORMAL].value += type2;
3664 sd->right_weapon.hp_drain_class[CLASS_NORMAL].type = val;
3665 sd->right_weapon.hp_drain_class[CLASS_BOSS].value += type2;
3666 sd->right_weapon.hp_drain_class[CLASS_BOSS].type = val;
3667 }
3668 else if(sd->state.lr_flag == 1) {
3669 sd->left_weapon.hp_drain_class[CLASS_NORMAL].value += type2;
3670 sd->left_weapon.hp_drain_class[CLASS_NORMAL].type = val;
3671 sd->left_weapon.hp_drain_class[CLASS_BOSS].value += type2;
3672 sd->left_weapon.hp_drain_class[CLASS_BOSS].type = val;
3673 }
3674 break;
3675 case SP_SP_DRAIN_RATE:
3676 if(!sd->state.lr_flag) {
3677 sd->right_weapon.sp_drain_class[CLASS_NORMAL].rate += type2;
3678 sd->right_weapon.sp_drain_class[CLASS_NORMAL].per += val;
3679 sd->right_weapon.sp_drain_class[CLASS_BOSS].rate += type2;
3680 sd->right_weapon.sp_drain_class[CLASS_BOSS].per += val;
3681 }
3682 else if(sd->state.lr_flag == 1) {
3683 sd->left_weapon.sp_drain_class[CLASS_NORMAL].rate += type2;
3684 sd->left_weapon.sp_drain_class[CLASS_NORMAL].per += val;
3685 sd->left_weapon.sp_drain_class[CLASS_BOSS].rate += type2;
3686 sd->left_weapon.sp_drain_class[CLASS_BOSS].per += val;
3687 }
3688 break;
3689 case SP_SP_DRAIN_VALUE:
3690 if(!sd->state.lr_flag) {
3691 sd->right_weapon.sp_drain_class[CLASS_NORMAL].value += type2;
3692 sd->right_weapon.sp_drain_class[CLASS_NORMAL].type = val;
3693 sd->right_weapon.sp_drain_class[CLASS_BOSS].value += type2;
3694 sd->right_weapon.sp_drain_class[CLASS_BOSS].type = val;
3695 }
3696 else if(sd->state.lr_flag == 1) {
3697 sd->left_weapon.sp_drain_class[CLASS_NORMAL].value += type2;
3698 sd->left_weapon.sp_drain_class[CLASS_NORMAL].type = val;
3699 sd->left_weapon.sp_drain_class[CLASS_BOSS].value += type2;
3700 sd->left_weapon.sp_drain_class[CLASS_BOSS].type = val;
3701 }
3702 break;
3703 case SP_SP_VANISH_RATE:
3704 if(sd->state.lr_flag != 2) {
3705 sd->bonus.sp_vanish_rate += type2;
3706 sd->bonus.sp_vanish_per += val;
3707 }
3708 break;
3709 case SP_HP_VANISH_RATE:
3710 if(sd->state.lr_flag != 2) {
3711 sd->bonus.hp_vanish_rate += type2;
3712 sd->bonus.hp_vanish_per += val;
3713 }
3714 break;
3715 case SP_GET_ZENY_NUM:
3716 if(sd->state.lr_flag != 2 && sd->bonus.get_zeny_rate < val) {
3717 sd->bonus.get_zeny_rate = val;
3718 sd->bonus.get_zeny_num = type2;
3719 }
3720 break;
3721 case SP_ADD_GET_ZENY_NUM:
3722 if(sd->state.lr_flag != 2) {
3723 sd->bonus.get_zeny_rate += val;
3724 sd->bonus.get_zeny_num += type2;
3725 }
3726 break;
3727 case SP_WEAPON_COMA_ELE:
3728 if(type2 > ELE_ALL) {
3729 ShowError("pc_bonus2: SP_WEAPON_COMA_ELE: Invalid element %d\n", type2);
3730 break;
3731 }
3732 if(sd->state.lr_flag == 2)
3733 break;
3734 sd->weapon_coma_ele[type2] += val;
3735 sd->special_state.bonus_coma = 1;
3736 break;
3737 case SP_WEAPON_COMA_RACE:
3738 if(sd->state.lr_flag == 2)
3739 break;
3740 sd->weapon_coma_race[type2] += val;
3741 sd->special_state.bonus_coma = 1;
3742 break;
3743 case SP_WEAPON_COMA_CLASS:
3744 if(sd->state.lr_flag == 2)
3745 break;
3746 sd->weapon_coma_class[type2] += val;
3747 sd->special_state.bonus_coma = 1;
3748 break;
3749 case SP_WEAPON_ATK:
3750 if(sd->state.lr_flag != 2)
3751 sd->weapon_atk[type2]+=val;
3752 break;
3753 case SP_WEAPON_ATK_RATE:
3754 if(sd->state.lr_flag != 2)
3755 sd->weapon_atk_rate[type2]+=val;
3756 break;
3757 case SP_CRITICAL_ADDRACE:
3758 if(sd->state.lr_flag != 2)
3759 sd->critaddrace[type2] += val*10;
3760 break;
3761 case SP_ADDEFF_WHENHIT:
3762 if (type2 > SC_MAX) {
3763 ShowWarning("pc_bonus2 (Add Effect when hit): %d is not supported.\n", type2);
3764 break;
3765 }
3766 if(sd->state.lr_flag != 2)
3767 pc_bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, val, 0, 0);
3768 break;
3769 case SP_SKILL_ATK:
3770 if(sd->state.lr_flag == 2)
3771 break;
3772 ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == 0 || sd->skillatk[i].id == type2);
3773 if (i == ARRAYLENGTH(sd->skillatk))
3774 { //Better mention this so the array length can be updated. [Skotlex]
3775 ShowDebug("run_script: bonus2 bSkillAtk reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillatk), type2, val);
3776 break;
3777 }
3778 if (sd->skillatk[i].id == type2)
3779 sd->skillatk[i].val += val;
3780 else {
3781 sd->skillatk[i].id = type2;
3782 sd->skillatk[i].val = val;
3783 }
3784 break;
3785 case SP_SKILL_HEAL:
3786 if(sd->state.lr_flag == 2)
3787 break;
3788 ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == 0 || sd->skillheal[i].id == type2);
3789 if (i == ARRAYLENGTH(sd->skillheal))
3790 { // Better mention this so the array length can be updated. [Skotlex]
3791 ShowDebug("run_script: bonus2 bSkillHeal reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal), type2, val);
3792 break;
3793 }
3794 if (sd->skillheal[i].id == type2)
3795 sd->skillheal[i].val += val;
3796 else {
3797 sd->skillheal[i].id = type2;
3798 sd->skillheal[i].val = val;
3799 }
3800 break;
3801 case SP_SKILL_HEAL2:
3802 if(sd->state.lr_flag == 2)
3803 break;
3804 ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == 0 || sd->skillheal2[i].id == type2);
3805 if (i == ARRAYLENGTH(sd->skillheal2))
3806 { // Better mention this so the array length can be updated. [Skotlex]
3807 ShowDebug("run_script: bonus2 bSkillHeal2 reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal2), type2, val);
3808 break;
3809 }
3810 if (sd->skillheal2[i].id == type2)
3811 sd->skillheal2[i].val += val;
3812 else {
3813 sd->skillheal2[i].id = type2;
3814 sd->skillheal2[i].val = val;
3815 }
3816 break;
3817 case SP_ADD_SKILL_BLOW:
3818 if(sd->state.lr_flag == 2)
3819 break;
3820 ARR_FIND(0, ARRAYLENGTH(sd->skillblown), i, sd->skillblown[i].id == 0 || sd->skillblown[i].id == type2);
3821 if (i == ARRAYLENGTH(sd->skillblown))
3822 { //Better mention this so the array length can be updated. [Skotlex]
3823 ShowDebug("run_script: bonus2 bSkillBlown reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillblown), type2, val);
3824 break;
3825 }
3826 if(sd->skillblown[i].id == type2)
3827 sd->skillblown[i].val += val;
3828 else {
3829 sd->skillblown[i].id = type2;
3830 sd->skillblown[i].val = val;
3831 }
3832 break;
3833#ifndef RENEWAL_CAST
3834 case SP_VARCASTRATE:
3835#endif
3836 case SP_CASTRATE:
3837 if(sd->state.lr_flag == 2)
3838 break;
3839 ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2);
3840 if (i == ARRAYLENGTH(sd->skillcast))
3841 { //Better mention this so the array length can be updated. [Skotlex]
3842 ShowDebug("run_script: bonus2 %s reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n",
3843
3844#ifndef RENEWAL_CAST
3845 "bCastRate",
3846#else
3847 "bVariableCastrate",
3848#endif
3849
3850 ARRAYLENGTH(sd->skillcast), type2, val);
3851 break;
3852 }
3853 if(sd->skillcast[i].id == type2)
3854 sd->skillcast[i].val += val;
3855 else {
3856 sd->skillcast[i].id = type2;
3857 sd->skillcast[i].val = val;
3858 }
3859 break;
3860 case SP_FIXCASTRATE:
3861 if(sd->state.lr_flag == 2)
3862 break;
3863 ARR_FIND(0, ARRAYLENGTH(sd->skillfixcastrate), i, sd->skillfixcastrate[i].id == 0 || sd->skillfixcastrate[i].id == type2);
3864 if (i == ARRAYLENGTH(sd->skillfixcastrate))
3865 {
3866 ShowDebug("run_script: bonus2 bFixedCastrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcastrate), type2, val);
3867 break;
3868 }
3869 if(sd->skillfixcastrate[i].id == type2)
3870 sd->skillfixcastrate[i].val += val;
3871 else {
3872 sd->skillfixcastrate[i].id = type2;
3873 sd->skillfixcastrate[i].val = val;
3874 }
3875 break;
3876 case SP_HP_LOSS_RATE:
3877 if(sd->state.lr_flag != 2) {
3878 sd->hp_loss.value = type2;
3879 sd->hp_loss.rate = val;
3880 }
3881 break;
3882 case SP_HP_REGEN_RATE:
3883 if(sd->state.lr_flag != 2) {
3884 sd->hp_regen.value = type2;
3885 sd->hp_regen.rate = val;
3886 }
3887 break;
3888 case SP_ADDRACE2:
3889 if (!(type2 > RC2_NONE && type2 < RC2_MAX))
3890 break;
3891 if(sd->state.lr_flag != 2)
3892 sd->right_weapon.addrace2[type2] += val;
3893 else
3894 sd->left_weapon.addrace2[type2] += val;
3895 break;
3896 case SP_SUBSIZE:
3897 if(sd->state.lr_flag != 2)
3898 sd->subsize[type2]+=val;
3899 break;
3900 case SP_SUBRACE2:
3901 if (!(type2 > RC2_NONE && type2 < RC2_MAX))
3902 break;
3903 if(sd->state.lr_flag != 2)
3904 sd->subrace2[type2]+=val;
3905 break;
3906 case SP_ADD_ITEM_HEAL_RATE:
3907 if(sd->state.lr_flag == 2)
3908 break;
3909 if (type2 < MAX_ITEMGROUP) { //Group bonus
3910 sd->itemgrouphealrate[type2] += val;
3911 break;
3912 }
3913 //Standard item bonus.
3914 for(i=0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid && sd->itemhealrate[i].nameid != type2; i++);
3915 if(i == ARRAYLENGTH(sd->itemhealrate)) {
3916 ShowWarning("pc_bonus2: Reached max (%d) number of item heal bonuses per character!\n", ARRAYLENGTH(sd->itemhealrate));
3917 break;
3918 }
3919 sd->itemhealrate[i].nameid = type2;
3920 sd->itemhealrate[i].rate += val;
3921 break;
3922 case SP_EXP_ADDRACE:
3923 if(sd->state.lr_flag != 2)
3924 sd->expaddrace[type2]+=val;
3925 break;
3926 case SP_EXP_ADDCLASS:
3927 if(sd->state.lr_flag != 2)
3928 sd->expaddclass[type2]+=val;
3929 break;
3930 case SP_SP_GAIN_RACE:
3931 if(sd->state.lr_flag != 2)
3932 sd->sp_gain_race[type2]+=val;
3933 break;
3934 case SP_ADD_MONSTER_DROP_ITEM:
3935 if (sd->state.lr_flag != 2)
3936 pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, CLASS_ALL, RC_NONE_, val);
3937 break;
3938 case SP_ADD_MONSTER_DROP_ITEMGROUP:
3939 if (sd->state.lr_flag != 2)
3940 pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, CLASS_ALL, RC_NONE_, val);
3941 break;
3942 case SP_SP_LOSS_RATE:
3943 if(sd->state.lr_flag != 2) {
3944 sd->sp_loss.value = type2;
3945 sd->sp_loss.rate = val;
3946 }
3947 break;
3948 case SP_SP_REGEN_RATE:
3949 if(sd->state.lr_flag != 2) {
3950 sd->sp_regen.value = type2;
3951 sd->sp_regen.rate = val;
3952 }
3953 break;
3954 case SP_HP_DRAIN_VALUE_RACE:
3955 if(!sd->state.lr_flag) {
3956 sd->right_weapon.hp_drain_race[type2].value += val;
3957 }
3958 else if(sd->state.lr_flag == 1) {
3959 sd->left_weapon.hp_drain_race[type2].value += val;
3960 }
3961 break;
3962 case SP_SP_DRAIN_VALUE_RACE:
3963 if(!sd->state.lr_flag) {
3964 sd->right_weapon.sp_drain_race[type2].value += val;
3965 }
3966 else if(sd->state.lr_flag == 1) {
3967 sd->left_weapon.sp_drain_race[type2].value += val;
3968 }
3969 break;
3970 case SP_HP_DRAIN_VALUE_CLASS:
3971 if(!sd->state.lr_flag) {
3972 sd->right_weapon.hp_drain_class[type2].value += val;
3973 }
3974 else if(sd->state.lr_flag == 1) {
3975 sd->left_weapon.hp_drain_class[type2].value += val;
3976 }
3977 break;
3978 case SP_SP_DRAIN_VALUE_CLASS:
3979 if(!sd->state.lr_flag) {
3980 sd->right_weapon.sp_drain_class[type2].value += val;
3981 }
3982 else if(sd->state.lr_flag == 1) {
3983 sd->left_weapon.sp_drain_class[type2].value += val;
3984 }
3985 break;
3986 case SP_IGNORE_MDEF_RACE_RATE:
3987 if(sd->state.lr_flag != 2)
3988 sd->ignore_mdef_by_race[type2] += val;
3989 break;
3990 case SP_IGNORE_MDEF_CLASS_RATE:
3991 if(sd->state.lr_flag != 2)
3992 sd->ignore_mdef_by_class[type2] += val;
3993 break;
3994 case SP_IGNORE_DEF_RACE_RATE:
3995 if(sd->state.lr_flag != 2)
3996 sd->ignore_def_by_race[type2] += val;
3997 break;
3998 case SP_SP_GAIN_RACE_ATTACK:
3999 if(sd->state.lr_flag != 2)
4000 sd->sp_gain_race_attack[type2] = cap_value(sd->sp_gain_race_attack[type2] + val, 0, INT16_MAX);
4001 break;
4002 case SP_HP_GAIN_RACE_ATTACK:
4003 if(sd->state.lr_flag != 2)
4004 sd->hp_gain_race_attack[type2] = cap_value(sd->hp_gain_race_attack[type2] + val, 0, INT16_MAX);
4005 break;
4006 case SP_SKILL_USE_SP_RATE: //bonus2 bSkillUseSPrate,n,x;
4007 if(sd->state.lr_flag == 2)
4008 break;
4009 ARR_FIND(0, ARRAYLENGTH(sd->skillusesprate), i, sd->skillusesprate[i].id == 0 || sd->skillusesprate[i].id == type2);
4010 if (i == ARRAYLENGTH(sd->skillusesprate)) {
4011 ShowDebug("run_script: bonus2 bSkillUseSPrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesprate), type2, val);
4012 break;
4013 }
4014 if (sd->skillusesprate[i].id == type2)
4015 sd->skillusesprate[i].val += val;
4016 else {
4017 sd->skillusesprate[i].id = type2;
4018 sd->skillusesprate[i].val = val;
4019 }
4020 break;
4021 case SP_SKILL_COOLDOWN:
4022 if(sd->state.lr_flag == 2)
4023 break;
4024 ARR_FIND(0, ARRAYLENGTH(sd->skillcooldown), i, sd->skillcooldown[i].id == 0 || sd->skillcooldown[i].id == type2);
4025 if (i == ARRAYLENGTH(sd->skillcooldown))
4026 {
4027 ShowDebug("run_script: bonus2 bSkillCoolDown reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillcooldown), type2, val);
4028 break;
4029 }
4030 if (sd->skillcooldown[i].id == type2)
4031 sd->skillcooldown[i].val += val;
4032 else {
4033 sd->skillcooldown[i].id = type2;
4034 sd->skillcooldown[i].val = val;
4035 }
4036 break;
4037 case SP_SKILL_FIXEDCAST:
4038 if(sd->state.lr_flag == 2)
4039 break;
4040 ARR_FIND(0, ARRAYLENGTH(sd->skillfixcast), i, sd->skillfixcast[i].id == 0 || sd->skillfixcast[i].id == type2);
4041 if (i == ARRAYLENGTH(sd->skillfixcast))
4042 {
4043 ShowDebug("run_script: bonus2 bSkillFixedCast reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcast), type2, val);
4044 break;
4045 }
4046 if (sd->skillfixcast[i].id == type2)
4047 sd->skillfixcast[i].val += val;
4048 else {
4049 sd->skillfixcast[i].id = type2;
4050 sd->skillfixcast[i].val = val;
4051 }
4052 break;
4053 case SP_SKILL_VARIABLECAST:
4054 if(sd->state.lr_flag == 2)
4055 break;
4056 ARR_FIND(0, ARRAYLENGTH(sd->skillvarcast), i, sd->skillvarcast[i].id == 0 || sd->skillvarcast[i].id == type2);
4057 if (i == ARRAYLENGTH(sd->skillvarcast))
4058 {
4059 ShowDebug("run_script: bonus2 bSkillVariableCast reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillvarcast), type2, val);
4060 break;
4061 }
4062 if (sd->skillvarcast[i].id == type2)
4063 sd->skillvarcast[i].val += val;
4064 else {
4065 sd->skillvarcast[i].id = type2;
4066 sd->skillvarcast[i].val = val;
4067 }
4068 break;
4069#ifdef RENEWAL_CAST
4070 case SP_VARCASTRATE:
4071 if(sd->state.lr_flag == 2)
4072 break;
4073 ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2);
4074 if (i == ARRAYLENGTH(sd->skillcast))
4075 {
4076 ShowDebug("run_script: bonus2 bVariableCastrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n",ARRAYLENGTH(sd->skillcast), type2, val);
4077 break;
4078 }
4079 if(sd->skillcast[i].id == type2)
4080 sd->skillcast[i].val -= val;
4081 else {
4082 sd->skillcast[i].id = type2;
4083 sd->skillcast[i].val -= val;
4084 }
4085 break;
4086#endif
4087 case SP_SKILL_USE_SP: //bonus2 bSkillUseSP,n,x;
4088 if(sd->state.lr_flag == 2)
4089 break;
4090 ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == 0 || sd->skillusesp[i].id == type2);
4091 if (i == ARRAYLENGTH(sd->skillusesp)) {
4092 ShowDebug("run_script: bonus2 bSkillUseSP reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesp), type2, val);
4093 break;
4094 }
4095 if (sd->skillusesp[i].id == type2)
4096 sd->skillusesp[i].val += val;
4097 else {
4098 sd->skillusesp[i].id = type2;
4099 sd->skillusesp[i].val = val;
4100 }
4101 break;
4102 default:
4103 ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
4104 break;
4105 }
4106 return 0;
4107}
4108
4109int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
4110{
4111 nullpo_ret(sd);
4112
4113 switch(type){
4114 case SP_ADD_MONSTER_DROP_ITEM:
4115 if(sd->state.lr_flag != 2)
4116 pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, CLASS_NONE, type3, val);
4117 break;
4118 case SP_ADD_MONSTER_ID_DROP_ITEM:
4119 if(sd->state.lr_flag != 2)
4120 pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, CLASS_NONE, -type3, val);
4121 break;
4122 case SP_ADD_CLASS_DROP_ITEM:
4123 if(sd->state.lr_flag != 2)
4124 pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, type3, RC_NONE_, val);
4125 break;
4126 case SP_AUTOSPELL:
4127 if(sd->state.lr_flag != 2)
4128 {
4129 int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
4130 target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF));
4131 pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell),
4132 target?-type2:type2, type3, val, 0, current_equip_card_id);
4133 }
4134 break;
4135 case SP_AUTOSPELL_WHENHIT:
4136 if(sd->state.lr_flag != 2)
4137 {
4138 int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
4139 target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF));
4140 pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2),
4141 target?-type2:type2, type3, val, BF_NORMAL|BF_SKILL, current_equip_card_id);
4142 }
4143 break;
4144 case SP_SP_DRAIN_RATE:
4145 if(!sd->state.lr_flag) {
4146 sd->right_weapon.sp_drain_class[CLASS_NORMAL].rate += type2;
4147 sd->right_weapon.sp_drain_class[CLASS_NORMAL].per += type3;
4148 sd->right_weapon.sp_drain_class[CLASS_NORMAL].type = val;
4149 sd->right_weapon.sp_drain_class[CLASS_BOSS].rate += type2;
4150 sd->right_weapon.sp_drain_class[CLASS_BOSS].per += type3;
4151 sd->right_weapon.sp_drain_class[CLASS_BOSS].type = val;
4152
4153 }
4154 else if(sd->state.lr_flag == 1) {
4155 sd->left_weapon.sp_drain_class[CLASS_NORMAL].rate += type2;
4156 sd->left_weapon.sp_drain_class[CLASS_NORMAL].per += type3;
4157 sd->left_weapon.sp_drain_class[CLASS_NORMAL].type = val;
4158 sd->left_weapon.sp_drain_class[CLASS_BOSS].rate += type2;
4159 sd->left_weapon.sp_drain_class[CLASS_BOSS].per += type3;
4160 sd->left_weapon.sp_drain_class[CLASS_BOSS].type = val;
4161 }
4162 break;
4163 case SP_ADD_MONSTER_DROP_ITEMGROUP:
4164 if (sd->state.lr_flag != 2)
4165 pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, CLASS_NONE, type3, val);
4166 break;
4167 case SP_ADD_CLASS_DROP_ITEMGROUP:
4168 if (sd->state.lr_flag != 2)
4169 pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, type3, RC_NONE_, val);
4170 break;
4171
4172 case SP_ADDEFF:
4173 if (type2 > SC_MAX) {
4174 ShowWarning("pc_bonus3 (Add Effect): %d is not supported.\n", type2);
4175 break;
4176 }
4177 pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2,
4178 sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, val);
4179 break;
4180
4181 case SP_ADDEFF_WHENHIT:
4182 if (type2 > SC_MAX) {
4183 ShowWarning("pc_bonus3 (Add Effect when hit): %d is not supported.\n", type2);
4184 break;
4185 }
4186 if(sd->state.lr_flag != 2)
4187 pc_bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, type3, 0, val);
4188 break;
4189
4190 case SP_ADDEFF_ONSKILL:
4191 if( type3 > SC_MAX ) {
4192 ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type3);
4193 break;
4194 }
4195 if( sd->state.lr_flag != 2 )
4196 pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, val, type2, ATF_TARGET);
4197 break;
4198
4199 case SP_ADDELE:
4200 if (type2 > ELE_ALL) {
4201 ShowWarning("pc_bonus3 (SP_ADDELE): element %d is out of range.\n", type2);
4202 break;
4203 }
4204 if (sd->state.lr_flag != 2)
4205 pc_bonus_addele(sd, (unsigned char)type2, type3, val);
4206 break;
4207
4208 case SP_SUBELE:
4209 if (type2 > ELE_ALL) {
4210 ShowWarning("pc_bonus3 (SP_SUBELE): element %d is out of range.\n", type2);
4211 break;
4212 }
4213 if (sd->state.lr_flag != 2)
4214 pc_bonus_subele(sd, (unsigned char)type2, type3, val);
4215 break;
4216
4217 default:
4218 ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val);
4219 break;
4220 }
4221
4222 return 0;
4223}
4224
4225int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val)
4226{
4227 nullpo_ret(sd);
4228
4229 switch(type){
4230 case SP_AUTOSPELL:
4231 if(sd->state.lr_flag != 2)
4232 pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, 0, current_equip_card_id);
4233 break;
4234
4235 case SP_AUTOSPELL_WHENHIT:
4236 if(sd->state.lr_flag != 2)
4237 pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, BF_NORMAL|BF_SKILL, current_equip_card_id);
4238 break;
4239
4240 case SP_AUTOSPELL_ONSKILL:
4241 if(sd->state.lr_flag != 2)
4242 {
4243 int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
4244 target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF));
4245
4246 pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, target?-type3:type3, type4, val, current_equip_card_id);
4247 }
4248 break;
4249
4250 case SP_ADDEFF_ONSKILL:
4251 if( type2 > SC_MAX ) {
4252 ShowWarning("pc_bonus4 (Add Effect on skill): %d is not supported.\n", type2);
4253 break;
4254 }
4255 if( sd->state.lr_flag != 2 )
4256 pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, type4, type2, val);
4257 break;
4258
4259 case SP_DEF_SET: //bonus4 bSetDefRace,n,x,r,y;
4260 if( type2 > RC_ALL ) {
4261 ShowWarning("pc_bonus4 (DEF_SET): %d is not supported.\n", type2);
4262 break;
4263 }
4264 if(sd->state.lr_flag == 2)
4265 break;
4266 sd->def_set_race[type2].rate = type3;
4267 sd->def_set_race[type2].tick = type4;
4268 sd->def_set_race[type2].value = val;
4269 break;
4270
4271 case SP_MDEF_SET: //bonus4 bSetMDefRace,n,x,r,y;
4272 if( type2 > RC_ALL ) {
4273 ShowWarning("pc_bonus4 (MDEF_SET): %d is not supported.\n", type2);
4274 break;
4275 }
4276 if(sd->state.lr_flag == 2)
4277 break;
4278 sd->mdef_set_race[type2].rate = type3;
4279 sd->mdef_set_race[type2].tick = type4;
4280 sd->mdef_set_race[type2].value = val;
4281 break;
4282
4283 default:
4284 ShowWarning("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val);
4285 break;
4286 }
4287
4288 return 0;
4289}
4290
4291int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4,int type5,int val)
4292{
4293 nullpo_ret(sd);
4294
4295 switch(type){
4296 case SP_AUTOSPELL:
4297 if(sd->state.lr_flag != 2)
4298 pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id);
4299 break;
4300
4301 case SP_AUTOSPELL_WHENHIT:
4302 if(sd->state.lr_flag != 2)
4303 pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id);
4304 break;
4305
4306 case SP_AUTOSPELL_ONSKILL:
4307 if(sd->state.lr_flag != 2)
4308 pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, (val&1?-type3:type3), (val&2?-type4:type4), type5, current_equip_card_id);
4309 break;
4310
4311 default:
4312 ShowWarning("pc_bonus5: unknown type %d %d %d %d %d %d!\n",type,type2,type3,type4,type5,val);
4313 break;
4314 }
4315
4316 return 0;
4317}
4318
4319/*==========================================
4320 * Grants a player a given skill. Flag values are:
4321 * 0 - Grant permanent skill to be bound to skill tree
4322 * 1 - Grant an item skill (temporary)
4323 * 2 - Like 1, except the level granted can stack with previously learned level.
4324 * 4 - Like 0, except the skill will ignore skill tree (saves through job changes and resets).
4325 *------------------------------------------*/
4326int pc_skill(TBL_PC* sd, int id, int level, int flag)
4327{
4328 nullpo_ret(sd);
4329
4330 if( id <= 0 || id >= MAX_SKILL || skill_db[id].name == NULL) {
4331 ShowError("pc_skill: Skill with id %d does not exist in the skill database\n", id);
4332 return 0;
4333 }
4334 if( level > MAX_SKILL_LEVEL ) {
4335 ShowError("pc_skill: Skill level %d too high. Max lv supported is %d\n", level, MAX_SKILL_LEVEL);
4336 return 0;
4337 }
4338 if( flag == 2 && sd->status.skill[id].lv + level > MAX_SKILL_LEVEL ) {
4339 ShowError("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d\n", level, MAX_SKILL_LEVEL, sd->status.skill[id].lv);
4340 return 0;
4341 }
4342
4343 switch( flag ){
4344 case 0: //Set skill data overwriting whatever was there before.
4345 sd->status.skill[id].id = id;
4346 sd->status.skill[id].lv = level;
4347 sd->status.skill[id].flag = SKILL_FLAG_PERMANENT;
4348 if( level == 0 ) { //Remove skill.
4349 sd->status.skill[id].id = 0;
4350 clif_deleteskill(sd,id);
4351 } else
4352 clif_addskill(sd,id);
4353 if( !skill_get_inf(id) ) //Only recalculate for passive skills.
4354 status_calc_pc(sd, 0);
4355 break;
4356 case 1: //Item bonus skill.
4357 if( sd->status.skill[id].id == id ){
4358 if( sd->status.skill[id].lv >= level )
4359 return 0;
4360 if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level.
4361 sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv;
4362 } else {
4363 sd->status.skill[id].id = id;
4364 sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY;
4365 }
4366 sd->status.skill[id].lv = level;
4367 break;
4368 case 2: //Add skill bonus on top of what you had.
4369 if( sd->status.skill[id].id == id ){
4370 if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT )
4371 sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level.
4372 } else {
4373 sd->status.skill[id].id = id;
4374 sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill.
4375 }
4376 sd->status.skill[id].lv += level;
4377 break;
4378 case 4: //Permanent granted skills ignore the skill tree
4379 sd->status.skill[id].id = id;
4380 sd->status.skill[id].lv = level;
4381 sd->status.skill[id].flag = SKILL_FLAG_PERM_GRANTED;
4382 if( level == 0 ) { //Remove skill.
4383 sd->status.skill[id].id = 0;
4384 clif_deleteskill(sd,id);
4385 } else
4386 clif_addskill(sd,id);
4387 if( !skill_get_inf(id) ) //Only recalculate for passive skills.
4388 status_calc_pc(sd, 0);
4389 break;
4390 default: //Unknown flag?
4391 return 0;
4392 }
4393 return 1;
4394}
4395/*==========================================
4396 * Append a card to an item ?
4397 *------------------------------------------*/
4398int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip)
4399{
4400 int i;
4401 int nameid;
4402
4403 nullpo_ret(sd);
4404
4405 if( idx_equip < 0 || idx_equip >= MAX_INVENTORY || sd->inventory_data[idx_equip] == NULL )
4406 return 0; //Invalid item index.
4407 if( idx_card < 0 || idx_card >= MAX_INVENTORY || sd->inventory_data[idx_card] == NULL )
4408 return 0; //Invalid card index.
4409 if( sd->status.inventory[idx_equip].nameid <= 0 || sd->status.inventory[idx_equip].amount < 1 )
4410 return 0; // target item missing
4411 if( sd->status.inventory[idx_card].nameid <= 0 || sd->status.inventory[idx_card].amount < 1 )
4412 return 0; // target card missing
4413 if( sd->inventory_data[idx_equip]->type != IT_WEAPON && sd->inventory_data[idx_equip]->type != IT_ARMOR )
4414 return 0; // only weapons and armor are allowed
4415 if( sd->inventory_data[idx_card]->type != IT_CARD )
4416 return 0; // must be a card
4417 if( sd->status.inventory[idx_equip].identify == 0 )
4418 return 0; // target must be identified
4419 if( itemdb_isspecial(sd->status.inventory[idx_equip].card[0]) )
4420 return 0; // card slots reserved for other purposes
4421 if( (sd->inventory_data[idx_equip]->equip & sd->inventory_data[idx_card]->equip) == 0 )
4422 return 0; // card cannot be compounded on this item type
4423 if( itemdb_isenchant(sd->status.inventory[idx_card].nameid) && sd->inventory_data[idx_equip]->slot > 3 )
4424 return 0; // Reserved slot for Enchant is a normal slot
4425 if( sd->inventory_data[idx_equip]->type == IT_WEAPON && sd->inventory_data[idx_card]->equip == EQP_SHIELD )
4426 return 0; // attempted to place shield card on left-hand weapon.
4427 if( sd->status.inventory[idx_equip].equip != 0 )
4428 return 0; // item must be unequipped
4429
4430 // remember the card id to insert
4431 nameid = sd->status.inventory[idx_card].nameid;
4432
4433 if( itemdb_isenchant(nameid) )
4434 {
4435 switch( sd->inventory_data[idx_equip]->nameid )
4436 { // Non Enchantable Equipment
4437 case 2357: return 0;
4438 }
4439 i = 3; // Enchant Slot - Can overwrite current enchant
4440 }
4441 else
4442 {
4443 ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0 );
4444 if( i == sd->inventory_data[idx_equip]->slot )
4445 return 0; // no free slots
4446 }
4447
4448 if( pc_delitem(sd,idx_card,1,1,0,LOG_TYPE_OTHER) == 1 )
4449 {// failed
4450 clif_insert_card(sd,idx_equip,idx_card,1);
4451 }
4452 else
4453 {// success
4454 log_pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->status.inventory[idx_equip]);
4455 sd->status.inventory[idx_equip].card[i] = nameid;
4456 log_pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip]);
4457 clif_insert_card(sd,idx_equip,idx_card,0);
4458 if( itemdb_isenchant(nameid) )
4459 {
4460 clif_delitem(sd,idx_equip,1,3);
4461 clif_additem(sd,idx_equip,1,0);
4462 }
4463 }
4464
4465 return 0;
4466}
4467
4468//
4469// Items
4470//
4471
4472/*==========================================
4473 * Update buying value by skills
4474 *------------------------------------------*/
4475int pc_modifybuyvalue(struct map_session_data *sd,int orig_value)
4476{
4477 int skill,val = orig_value,rate1 = 0,rate2 = 0;
4478 if( !battle_config.super_woe_enable )
4479 { // Discount not usable on Super WoE / GvG Events
4480 if( (skill = pc_checkskill(sd,MC_DISCOUNT)) > 0 ) // merchant discount
4481 rate1 = 5 + skill * 2 - ((skill==10)? 1:0);
4482 if( (skill = pc_checkskill(sd,RG_COMPULSION)) > 0 ) // rogue discount
4483 rate2 = 5 + skill * 4;
4484 }
4485 if(rate1 < rate2) rate1 = rate2;
4486 if(rate1)
4487 val = (int)((double)orig_value*(double)(100-rate1)/100.);
4488 if(val < 0) val = 0;
4489 if(orig_value > 0 && val < 1) val = 1;
4490
4491 return val;
4492}
4493
4494/*==========================================
4495 * Update selling value by skills
4496 *------------------------------------------*/
4497int pc_modifysellvalue(struct map_session_data *sd,int orig_value)
4498{
4499 int skill,val = orig_value,rate = 0;
4500 if((skill=pc_checkskill(sd,MC_OVERCHARGE))>0) //OverCharge
4501 rate = 5+skill*2-((skill==10)? 1:0);
4502 if(rate)
4503 val = (int)((double)orig_value*(double)(100+rate)/100.);
4504 if(val < 0) val = 0;
4505 if(orig_value > 0 && val < 1) val = 1;
4506
4507 return val;
4508}
4509
4510/*==========================================
4511 * Checking if we have enough place on inventory for new item
4512 * Make sure to take 30k as limit (for client I guess)
4513 *------------------------------------------*/
4514int pc_checkadditem(struct map_session_data *sd,int nameid,int amount)
4515{
4516 int i;
4517 struct item_data* data;
4518
4519 nullpo_ret(sd);
4520
4521 if(amount > MAX_AMOUNT)
4522 return CHKADDITEM_OVERAMOUNT;
4523
4524 data = itemdb_search(nameid);
4525
4526 if(!itemdb_isstackable2(data))
4527 return CHKADDITEM_NEW;
4528
4529 if( data->stack.inventory && amount > data->stack.amount )
4530 return CHKADDITEM_OVERAMOUNT;
4531
4532 for(i=0;i<MAX_INVENTORY;i++){
4533 // FIXME: This does not consider the checked item's cards, thus could check a wrong slot for stackability.
4534 if(sd->status.inventory[i].nameid==nameid){
4535 if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) )
4536 return CHKADDITEM_OVERAMOUNT;
4537 return CHKADDITEM_EXIST;
4538 }
4539 }
4540
4541 return CHKADDITEM_NEW;
4542}
4543
4544/*==========================================
4545 * Return number of available place in inventory
4546 * Each non stackable item will reduce place by 1
4547 *------------------------------------------*/
4548int pc_inventoryblank(struct map_session_data *sd)
4549{
4550 int i,b;
4551
4552 nullpo_ret(sd);
4553
4554 for(i=0,b=0;i<MAX_INVENTORY;i++){
4555 if(sd->status.inventory[i].nameid==0)
4556 b++;
4557 }
4558
4559 return b;
4560}
4561
4562/*==========================================
4563 * attempts to remove zeny from player (sd)
4564 *------------------------------------------*/
4565int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd)
4566{
4567 nullpo_retr(-1,sd);
4568
4569 zeny = cap_value(zeny,-MAX_ZENY,MAX_ZENY); //prevent command UB
4570 if( zeny < 0 )
4571 {
4572 ShowError("pc_payzeny: Paying negative Zeny (zeny=%d, account_id=%d, char_id=%d).\n", zeny, sd->status.account_id, sd->status.char_id);
4573 return 1;
4574 }
4575
4576 if( sd->status.zeny < zeny )
4577 return 1; //Not enough.
4578
4579 sd->status.zeny -= zeny;
4580 clif_updatestatus(sd,SP_ZENY);
4581
4582 if(!tsd) tsd = sd;
4583 log_zeny(sd, type, tsd, -zeny);
4584 if( zeny > 0 && sd->state.showzeny ) {
4585 char output[255];
4586 sprintf(output, "Removed %dz.", zeny);
4587 clif_disp_onlyself(sd,output,strlen(output));
4588 }
4589
4590 return 0;
4591}
4592
4593/** Makes player pays by using cash points
4594 * @param sd Player who pays
4595 * @param price How many point player has to pay
4596 * @param points
4597 * @param type e_log_pick_type
4598 * @return -2: Paying negative points, -1: Not enough points, otherwise is succes (cash+points)
4599 */
4600int pc_paycash(struct map_session_data *sd, int price, int points, e_log_pick_type type ){
4601 int cash;
4602 nullpo_retr(-1,sd);
4603
4604 points = cap_value(points,-MAX_ZENY,MAX_ZENY); //prevent command UB
4605 if( price < 0 || points < 0 )
4606 {
4607 ShowError("pc_paycash: Paying negative points (price=%d, points=%d, account_id=%d, char_id=%d).\n", price, points, sd->status.account_id, sd->status.char_id);
4608 return -2;
4609 }
4610
4611 if( points > price )
4612 {
4613 ShowWarning("pc_paycash: More kafra points provided than needed (price=%d, points=%d, account_id=%d, char_id=%d).\n", price, points, sd->status.account_id, sd->status.char_id);
4614 points = price;
4615 }
4616
4617 cash = price-points;
4618
4619 if( sd->cashPoints < cash || sd->kafraPoints < points )
4620 {
4621 ShowError("pc_paycash: Not enough points (cash=%d, kafra=%d) to cover the price (cash=%d, kafra=%d) (account_id=%d, char_id=%d).\n", sd->cashPoints, sd->kafraPoints, cash, points, sd->status.account_id, sd->status.char_id);
4622 return -1;
4623 }
4624
4625 pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints-cash);
4626 if( cash ){
4627 log_cash( sd, type, LOG_CASH_TYPE_CASH, -cash );
4628 }
4629 pc_setaccountreg(sd, "#KAFRAPOINTS", sd->kafraPoints-points);
4630 if( points ){
4631 log_cash( sd, type, LOG_CASH_TYPE_KAFRA, -points );
4632 }
4633
4634 if( battle_config.cashshop_show_points )
4635 {
4636 char output[128];
4637 sprintf(output, msg_txt(sd,504), points, cash, sd->kafraPoints, sd->cashPoints);
4638 clif_disp_onlyself(sd, output, strlen(output));
4639 }
4640 return cash+points;
4641}
4642
4643int pc_getcash( struct map_session_data *sd, int cash, int points, e_log_pick_type type ){
4644 char output[128];
4645 nullpo_retr(-1,sd);
4646
4647 cash = cap_value(cash,-MAX_ZENY,MAX_ZENY); //prevent command UB
4648 points = cap_value(points,-MAX_ZENY,MAX_ZENY); //prevent command UB
4649 if( cash > 0 )
4650 {
4651 if( cash > MAX_ZENY-sd->cashPoints )
4652 {
4653 ShowWarning("pc_getcash: Cash point overflow (cash=%d, have cash=%d, account_id=%d, char_id=%d).\n", cash, sd->cashPoints, sd->status.account_id, sd->status.char_id);
4654 cash = MAX_ZENY-sd->cashPoints;
4655 }
4656
4657 pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints+cash);
4658 if( cash ){
4659 log_cash( sd, type, LOG_CASH_TYPE_CASH, cash );
4660 }
4661
4662 if( battle_config.cashshop_show_points )
4663 {
4664 sprintf(output, msg_txt(sd,505), cash, sd->cashPoints);
4665 clif_disp_onlyself(sd, output, strlen(output));
4666 }
4667 return cash;
4668 }
4669 else if( cash < 0 )
4670 {
4671 ShowError("pc_getcash: Obtaining negative cash points (cash=%d, account_id=%d, char_id=%d).\n", cash, sd->status.account_id, sd->status.char_id);
4672 return -1;
4673 }
4674
4675 if( points > 0 )
4676 {
4677 if( points > MAX_ZENY-sd->kafraPoints )
4678 {
4679 ShowWarning("pc_getcash: Kafra point overflow (points=%d, have points=%d, account_id=%d, char_id=%d).\n", points, sd->kafraPoints, sd->status.account_id, sd->status.char_id);
4680 points = MAX_ZENY-sd->kafraPoints;
4681 }
4682
4683 pc_setaccountreg(sd, "#KAFRAPOINTS", sd->kafraPoints+points);
4684 if( points ){
4685 log_cash( sd, type, LOG_CASH_TYPE_KAFRA, points );
4686 }
4687
4688 if( battle_config.cashshop_show_points )
4689 {
4690 sprintf(output, msg_txt(sd,506), points, sd->kafraPoints);
4691 clif_disp_onlyself(sd, output, strlen(output));
4692 }
4693 return points;
4694 }
4695 else if( points < 0 )
4696 {
4697 ShowError("pc_getcash: Obtaining negative kafra points (points=%d, account_id=%d, char_id=%d).\n", points, sd->status.account_id, sd->status.char_id);
4698 return -1;
4699 }
4700 return -2; //shouldn't happen but jsut in case
4701}
4702
4703/*==========================================
4704 * Attempts to give zeny to player (sd)
4705 * tsd (optional) from who for log (if null take sd)
4706 *------------------------------------------*/
4707int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd)
4708{
4709 nullpo_retr(-1,sd);
4710
4711 zeny = cap_value(zeny,-MAX_ZENY,MAX_ZENY); //prevent command UB
4712 if( zeny < 0 )
4713 {
4714 ShowError("pc_getzeny: Obtaining negative Zeny (zeny=%d, account_id=%d, char_id=%d).\n", zeny, sd->status.account_id, sd->status.char_id);
4715 return 1;
4716 }
4717
4718 if( zeny > MAX_ZENY - sd->status.zeny )
4719 zeny = MAX_ZENY - sd->status.zeny;
4720
4721 sd->status.zeny += zeny;
4722 clif_updatestatus(sd,SP_ZENY);
4723 achievement_validate_zeny(sd,ATZ_HAVE,sd->status.zeny);
4724
4725 if(!tsd) tsd = sd;
4726 log_zeny(sd, type, tsd, zeny);
4727 if( zeny > 0 && sd->state.showzeny ) {
4728 char output[255];
4729 sprintf(output, "Gained %dz.", zeny);
4730 clif_disp_onlyself(sd,output,strlen(output));
4731 }
4732
4733 return 0;
4734}
4735
4736/*==========================================
4737 * Searching a specified itemid in inventory and return his stored index
4738 *------------------------------------------*/
4739int pc_search_inventory(struct map_session_data *sd,int item_id)
4740{
4741 int i, char_id;
4742 nullpo_retr(-1, sd);
4743
4744 if( item_id )
4745 {
4746 if( map_bg_items(sd->bl.m) && battle_config.bg_reserved_char_id )
4747 { // Battleground Items
4748 ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == item_id && sd->status.inventory[i].amount > 0 && sd->status.inventory[i].card[0] == CARD0_CREATE && MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3]) == battle_config.bg_reserved_char_id );
4749 if( i < MAX_INVENTORY ) return i;
4750 }
4751 else if( map[sd->bl.m].flag.ancient && battle_config.ancient_reserved_char_id )
4752 { // Ancient Items
4753 ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == item_id && sd->status.inventory[i].amount > 0 && sd->status.inventory[i].card[0] == CARD0_CREATE && MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3]) == battle_config.ancient_reserved_char_id );
4754 if( i < MAX_INVENTORY ) return i;
4755 }
4756 else if( map_gvg_items(sd->bl.m) && battle_config.woe_reserved_char_id )
4757 { // WoE Items
4758 ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == item_id && sd->status.inventory[i].amount > 0 && sd->status.inventory[i].card[0] == CARD0_CREATE && MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3]) == battle_config.woe_reserved_char_id );
4759 if( i < MAX_INVENTORY ) return i;
4760 }
4761 }
4762
4763 for( i = 0; i < MAX_INVENTORY; i++ )
4764 {
4765 if( sd->status.inventory[i].nameid != item_id )
4766 continue;
4767 if( item_id && sd->status.inventory[i].amount < 1 )
4768 continue;
4769 if( item_id && sd->status.inventory[i].card[0] == CARD0_CREATE && (char_id = MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3])) > 0 )
4770 {
4771 if( !map_bg_items(sd->bl.m) && battle_config.bg_reserved_char_id && battle_config.bg_reserved_char_id == char_id )
4772 continue;
4773 if( !map[sd->bl.m].flag.ancient && battle_config.ancient_reserved_char_id && battle_config.ancient_reserved_char_id == char_id )
4774 continue;
4775 if( !map_gvg_items(sd->bl.m) && battle_config.woe_reserved_char_id && battle_config.woe_reserved_char_id == char_id )
4776 continue;
4777 }
4778
4779 return i;
4780 }
4781
4782 return -1;
4783}
4784
4785/*==========================================
4786 * Attempt to add a new item to inventory.
4787 * Return:
4788 0 = success
4789 1 = invalid itemid not found or negative amount
4790 2 = overweight
4791 3 = ?
4792 4 = no free place found
4793 5 = max amount reached
4794 6 = ?
4795 7 = stack limitation
4796 *------------------------------------------*/
4797int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type)
4798{
4799 struct item_data *data;
4800 int i;
4801 unsigned int w;
4802
4803 nullpo_retr(1, sd);
4804 nullpo_retr(1, item_data);
4805
4806 if( item_data->nameid <= 0 || amount <= 0 )
4807 return ADDITEM_INVALID;
4808 if( amount > MAX_AMOUNT )
4809 return ADDITEM_OVERAMOUNT;
4810
4811 data = itemdb_search(item_data->nameid);
4812
4813 if( data->stack.inventory && amount > data->stack.amount )
4814 {// item stack limitation
4815 return ADDITEM_STACKLIMIT;
4816 }
4817
4818 w = data->weight*amount;
4819 if(sd->weight + w > sd->max_weight)
4820 return ADDITEM_OVERWEIGHT;
4821
4822 i = MAX_INVENTORY;
4823
4824 if( itemdb_isstackable2(data) && item_data->unique_id == 0 && item_data->expire_time == 0 )
4825 { // Stackable | Non Serialized (non unique) | Non Rental
4826 for( i = 0; i < MAX_INVENTORY; i++ )
4827 {
4828 if( sd->status.inventory[i].nameid == item_data->nameid && sd->status.inventory[i].bound == item_data->bound && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 )
4829 {
4830 if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) )
4831 return 5;
4832 sd->status.inventory[i].amount += amount;
4833 clif_additem(sd,i,amount,0);
4834 break;
4835 }
4836 }
4837 }
4838
4839 if( i >= MAX_INVENTORY )
4840 {
4841 i = pc_search_inventory(sd,0);
4842 if( i < 0 )
4843 return ADDITEM_OVERITEM;
4844
4845 memcpy(&sd->status.inventory[i], item_data, sizeof(sd->status.inventory[0]));
4846 // clear equips field first, just in case
4847 if( item_data->equip )
4848 sd->status.inventory[i].equip = 0;
4849
4850 sd->status.inventory[i].amount = amount;
4851 sd->inventory_data[i] = data;
4852 clif_additem(sd,i,amount,0);
4853 }
4854
4855 if( i < MAX_INVENTORY ) achievement_validate_item(sd,AT_ITEM_HAVE,sd->status.inventory[i].nameid,sd->status.inventory[i].amount);
4856
4857#ifdef NSI_UNIQUE_ID
4858 if( !itemdb_isstackable2(data) && !item_data->unique_id )
4859 sd->status.inventory[i].unique_id = itemdb_unique_id(0,0);
4860#endif
4861 log_pick_pc(sd, log_type, amount, &sd->status.inventory[i]);
4862
4863 sd->weight += w;
4864 clif_updatestatus(sd,SP_WEIGHT);
4865 //Auto-equip
4866 if(data->flag.autoequip)
4867 pc_equipitem(sd, i, data->equip);
4868
4869 /* rental item check */
4870 if( item_data->expire_time ) {
4871 if( time(NULL) > item_data->expire_time ) {
4872 clif_rental_expired(sd->fd, i, sd->status.inventory[i].nameid);
4873 pc_delitem(sd, i, sd->status.inventory[i].amount, 1, 0, LOG_TYPE_OTHER);
4874 } else {
4875 int seconds = (int)( item_data->expire_time - time(NULL) );
4876 clif_rental_time(sd->fd, sd->status.inventory[i].nameid, seconds);
4877 pc_inventory_rental_add(sd, seconds);
4878 }
4879 }
4880
4881 return ADDITEM_SUCCESS;
4882}
4883
4884/*==========================================
4885 * Remove an item at index n from inventory by amount.
4886 * Parameters :
4887 * @type
4888 * 1 : don't notify deletion
4889 * 2 : don't notify weight change
4890 * Return:
4891 * 0 = success
4892 * 1 = invalid itemid or negative amount
4893 *------------------------------------------*/
4894int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type)
4895{
4896 nullpo_retr(1, sd);
4897
4898 if(n < 0 || sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || sd->inventory_data[n] == NULL)
4899 return 1;
4900
4901 if (is_secure(sd)){
4902 if (security_opt(sd)&S_CANT_DELETE){
4903 clif_displaymessage(sd->fd,"Security is on. You cannot delete item.");
4904 return 1;
4905 }
4906 }
4907
4908 log_pick_pc(sd, log_type, -amount, &sd->status.inventory[n]);
4909
4910 sd->status.inventory[n].amount -= amount;
4911 sd->weight -= sd->inventory_data[n]->weight*amount ;
4912 if( sd->status.inventory[n].amount <= 0 ){
4913 if(sd->status.inventory[n].equip)
4914 pc_unequipitem(sd,n,3);
4915 memset(&sd->status.inventory[n],0,sizeof(sd->status.inventory[0]));
4916 sd->inventory_data[n] = NULL;
4917 }
4918 if(!(type&1))
4919 clif_delitem(sd,n,amount,reason);
4920 if(!(type&2))
4921 clif_updatestatus(sd,SP_WEIGHT);
4922
4923 return 0;
4924}
4925
4926/*==========================================
4927 * Attempt to drop an item.
4928 * Return:
4929 * 0 = fail
4930 * 1 = success
4931 *------------------------------------------*/
4932int pc_dropitem(struct map_session_data *sd,int n,int amount)
4933{
4934 struct item_data *item_data; // [Zephyrus] Mensaje al Drop
4935 nullpo_retr(1, sd);
4936
4937 if(n < 0 || n >= MAX_INVENTORY)
4938 return 0;
4939
4940 if(amount <= 0)
4941 return 0;
4942
4943 if(sd->status.inventory[n].nameid <= 0 ||
4944 sd->status.inventory[n].amount <= 0 ||
4945 sd->status.inventory[n].amount < amount ||
4946 sd->state.trading || sd->state.vending ||
4947 !sd->inventory_data[n] //pc_delitem would fail on this case.
4948 )
4949 return 0;
4950 if (is_secure(sd)){
4951 if (security_opt(sd)&S_CANT_DROP || security_opt(sd)&S_CANT_DELETE){
4952 clif_displaymessage(sd->fd,"Security is on. You cannot drop item.");
4953 return 0;
4954 }
4955 }
4956
4957 if( map[sd->bl.m].flag.nodrop )
4958 {
4959 clif_displaymessage (sd->fd, msg_txt(sd,271));
4960 return 0; //Can't drop items in nodrop mapflag maps.
4961 }
4962
4963 if( sd->state.secure_items )
4964 {
4965 clif_displaymessage(sd->fd, "You can't drop. Blocked with @security");
4966 return 0;
4967 }
4968
4969 if( !pc_candrop(sd,&sd->status.inventory[n]) )
4970 {
4971 clif_displaymessage (sd->fd, msg_txt(sd,263));
4972 return 0;
4973 }
4974
4975 if (!map_addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, sd->status.guild_id, 2))
4976 return 0;
4977
4978 if ((item_data= itemdb_exists(sd->status.inventory[n].nameid)) != NULL)
4979 if (item_data->type == IT_WEAPON || item_data->type == IT_CARD || item_data->type == IT_ARMOR) {
4980 char output[100];
4981 sprintf(output, "[- You drop an item !!. Please be sure about this -]", item_data->jname);
4982 clif_displaymessage (sd->fd, output);
4983 }
4984
4985 pc_delitem(sd, n, amount, 1, 0, LOG_TYPE_PICKDROP_PLAYER);
4986 clif_dropitem(sd, n, amount);
4987 return 1;
4988}
4989
4990/*==========================================
4991 * Attempt to pick up an item.
4992 * Return:
4993 * 0 = fail
4994 * 1 = success
4995 *------------------------------------------*/
4996int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
4997{
4998 int flag=0;
4999 unsigned int tick = gettick();
5000 struct party_data *p=NULL;
5001
5002 nullpo_ret(sd);
5003 nullpo_ret(fitem);
5004
5005 if(!check_distance_bl(&fitem->bl, &sd->bl, 2) && sd->ud.skill_id!=BS_GREED)
5006 return 0; // Distance is too far
5007
5008 if( sd->sc.cant.pickup )
5009 return 0;
5010
5011 if( battle_config.super_woe_enable && fitem->guild_id && sd->status.guild_id != fitem->guild_id )
5012 return 0; // Cannot pickup items from other Guilds
5013
5014 if (sd->status.party_id)
5015 p = party_search(sd->status.party_id);
5016
5017 if(fitem->first_get_charid > 0 && fitem->first_get_charid != sd->status.char_id) {
5018 struct map_session_data *first_sd = map_charid2sd(fitem->first_get_charid);
5019 if(DIFF_TICK(tick,fitem->first_get_tick) < 0) {
5020 if (!(p && p->party.item&1 &&
5021 first_sd && first_sd->status.party_id == sd->status.party_id
5022 ))
5023 return 0;
5024 }
5025 else if(fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id) {
5026 struct map_session_data *second_sd = map_charid2sd(fitem->second_get_charid);
5027 if(DIFF_TICK(tick, fitem->second_get_tick) < 0) {
5028 if(!(p && p->party.item&1 &&
5029 ((first_sd && first_sd->status.party_id == sd->status.party_id) ||
5030 (second_sd && second_sd->status.party_id == sd->status.party_id))
5031 ))
5032 return 0;
5033 }
5034 else if(fitem->third_get_charid > 0 && fitem->third_get_charid != sd->status.char_id){
5035 struct map_session_data *third_sd = map_charid2sd(fitem->third_get_charid);
5036 if(DIFF_TICK(tick,fitem->third_get_tick) < 0) {
5037 if(!(p && p->party.item&1 &&
5038 ((first_sd && first_sd->status.party_id == sd->status.party_id) ||
5039 (second_sd && second_sd->status.party_id == sd->status.party_id) ||
5040 (third_sd && third_sd->status.party_id == sd->status.party_id))
5041 ))
5042 return 0;
5043 }
5044 }
5045 }
5046 }
5047
5048 //This function takes care of giving the item to whoever should have it, considering party-share options.
5049 if ((flag = party_share_loot(p,sd,&fitem->item_data, fitem->first_get_charid))) {
5050 clif_additem(sd,0,0,flag);
5051 return 1;
5052 }
5053
5054 //Display pickup animation.
5055 pc_stop_attack(sd);
5056 clif_takeitem(&sd->bl,&fitem->bl);
5057 map_clearflooritem(&fitem->bl);
5058 return 1;
5059}
5060
5061/*==========================================
5062 * Check if item is usable.
5063 * Return:
5064 * 0 = no
5065 * 1 = yes
5066 *------------------------------------------*/
5067int pc_isUseitem(struct map_session_data *sd,int n)
5068{
5069 struct item_data *item;
5070 int nameid;
5071
5072 nullpo_ret(sd);
5073
5074 item = sd->inventory_data[n];
5075 nameid = sd->status.inventory[n].nameid;
5076
5077 if( item == NULL )
5078 return 0;
5079 //Not consumable item
5080 if( item->type != IT_HEALING && item->type != IT_USABLE && item->type != IT_CASH )
5081 return 0;
5082 if( !item->script ) //if it has no script, you can't really consume it!
5083 return 0;
5084 if (pc_has_permission(sd,PC_PERM_ITEM_UNCONDITIONAL))
5085 return 1;
5086 if(map[sd->bl.m].flag.noitemconsumption) //consumable but mapflag prevent it
5087 return 0;
5088 //Prevent mass item usage. [Skotlex]
5089 if( DIFF_TICK(sd->canuseitem_tick,gettick()) > 0 ||
5090 (itemdb_iscashfood(nameid) && DIFF_TICK(sd->canusecashfood_tick,gettick()) > 0)
5091 )
5092 return 0;
5093
5094 if( (item->item_usage.flag&NOUSE_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override) ) {
5095 return 0; // You cannot use this item while sitting.
5096 }
5097
5098 if (sd->state.storage_flag && item->type != IT_CASH) {
5099 clif_colormes(sd, color_table[COLOR_RED], msg_txt(sd,388));
5100 return 0; // You cannot use this item while storage is open.
5101 }
5102
5103 switch( nameid ) {
5104 case ITEMID_ANODYNE:
5105 if( map_flag_gvg3(sd->bl.m) )
5106 return 0;
5107 case ITEMID_ALOEBERA:
5108 if( pc_issit(sd) )
5109 return 0;
5110 break;
5111 case ITEMID_WING_OF_FLY:
5112 case ITEMID_GIANT_FLY_WING:
5113 if( map[sd->bl.m].flag.noteleport || map_flag_gvg3(sd->bl.m) || !guild_canescape(sd) )
5114 {
5115 clif_skill_teleportmessage(sd,0);
5116 return 0;
5117 }
5118 case ITEMID_WING_OF_BUTTERFLY:
5119 case ITEMID_DUN_TELE_SCROLL1:
5120 case ITEMID_DUN_TELE_SCROLL2:
5121 case ITEMID_DUN_TELE_SCROLL3:
5122 case ITEMID_WOB_RUNE:
5123 case ITEMID_WOB_SCHWALTZ:
5124 case ITEMID_WOB_RACHEL:
5125 case ITEMID_WOB_LOCAL:
5126 case ITEMID_SIEGE_TELEPORT_SCROLL:
5127 if( sd->duel_group && !battle_config.duel_allow_teleport ) {
5128 clif_displaymessage(sd->fd, msg_txt(sd,663));
5129 return 0;
5130 }
5131 if( !guild_canescape(sd) )
5132 { // Guild Wars
5133 clif_displaymessage(sd->fd, "Guild Wars: Cannot escape in battle");
5134 return 0;
5135 }
5136 if( nameid != 601 && nameid != 12212 && map[sd->bl.m].flag.noreturn )
5137 return 0;
5138 break;
5139 case ITEMID_BRANCH_OF_DEAD_TREE:
5140 case ITEMID_RED_POUCH_OF_SURPRISE:
5141 case ITEMID_BLOODY_DEAD_BRANCH:
5142 case ITEMID_PORING_BOX:
5143 case ITEMID_TREASURE_CHEST_SUMMONED_II:
5144 if( map[sd->bl.m].flag.nobranch || map_flag_gvg3(sd->bl.m) )
5145 return 0;
5146 break;
5147 case 12211: // Kafra Card
5148 if( map_flag_gvg(sd->bl.m) )
5149 return 0;
5150 break;
5151 case ITEMID_BUBBLE_GUM:
5152 case ITEMID_COMP_BUBBLE_GUM:
5153 if( sd->sc.data[SC_ITEMBOOST] )
5154 return 0;
5155 break;
5156 case ITEMID_BATTLE_MANUAL:
5157 case ITEMID_COMP_BATTLE_MANUAL:
5158 case ITEMID_THICK_BATTLE_MANUAL:
5159 case ITEMID_NOBLE_NAMEPLATE:
5160 case ITEMID_BATTLE_MANUAL25:
5161 case ITEMID_BATTLE_MANUAL100:
5162 case ITEMID_BATTLE_MANUAL300:
5163 if( sd->sc.data[SC_EXPBOOST] )
5164 return 0;
5165 break;
5166 case ITEMID_JOB_MANUAL50:
5167 if( sd->sc.data[SC_JEXPBOOST] )
5168 return 0;
5169 break;
5170 case ITEMID_MERCENARY_RED_POTION:
5171 case ITEMID_MERCENARY_BLUE_POTION:
5172 case ITEMID_M_CENTER_POTION:
5173 case ITEMID_M_AWAKENING_POTION:
5174 case ITEMID_M_BERSERK_POTION:
5175 if( sd->md == NULL || sd->md->db == NULL )
5176 return 0;
5177 if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAYNIGHTFEVER])
5178 return 0;
5179 if( nameid == ITEMID_M_AWAKENING_POTION && sd->md->db->lv < 40 )
5180 return 0;
5181 if( nameid == ITEMID_M_BERSERK_POTION && sd->md->db->lv < 80 )
5182 return 0;
5183 break;
5184
5185 case ITEMID_NEURALIZER:
5186 if( !map[sd->bl.m].flag.reset )
5187 return 0;
5188 break;
5189 }
5190
5191 if( nameid >= ITEMID_BOW_MERCENARY_SCROLL1 && nameid <= ITEMID_SPEARMERCENARY_SCROLL10 && sd->md != NULL )
5192 return 0; // Mercenary Scrolls
5193
5194 /**
5195 * Only Rune Knights may use runes
5196 **/
5197 if( itemdb_is_rune(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT )
5198 return 0;
5199 /**
5200 * Only GCross may use poisons
5201 **/
5202 else if( itemdb_is_poison(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_GUILLOTINE_CROSS )
5203 return 0;
5204
5205 if( map[sd->bl.m].flag.ancient && !item->ancient )
5206 return 0; // Ancient WoE items
5207
5208 //Gender check
5209 if(item->sex != 2 && sd->status.sex != item->sex)
5210 return 0;
5211 //Required level check
5212 if(item->elv && sd->status.base_level < (unsigned int)item->elv)
5213 return 0;
5214
5215#ifdef RENEWAL
5216 if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax)
5217 return 0;
5218#endif
5219
5220 //Not equipable by class. [Skotlex]
5221 if (!(
5222 (1<<(sd->class_&MAPID_BASEMASK)) &
5223 (item->class_base[sd->class_&JOBL_2_1?1:(sd->class_&JOBL_2_2?2:0)])
5224 ))
5225 return 0;
5226
5227 if (sd->sc.count && (
5228 sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] ||
5229 (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) ||
5230 sd->sc.data[SC_TRICKDEAD] ||
5231 sd->sc.data[SC_HIDING] ||
5232 sd->sc.data[SC__SHADOWFORM] ||
5233 sd->sc.data[SC__INVISIBILITY] ||
5234 sd->sc.data[SC__MANHOLE] ||
5235 sd->sc.data[SC_KAGEHUMI] ||
5236 (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) ||
5237 sd->sc.data[SC_HEAT_BARREL_AFTER]))
5238 return 0;
5239
5240 if (!pc_isItemClass(sd,item))
5241 return 0;
5242
5243 //Dead Branch & Bloody Branch & Porings Box
5244 if( nameid == ITEMID_BRANCH_OF_DEAD_TREE || nameid == ITEMID_BLOODY_DEAD_BRANCH || nameid == ITEMID_PORING_BOX || nameid == ITEMID_TREASURE_CHEST_SUMMONED_II )
5245 log_branch(sd);
5246
5247 return 1;
5248}
5249
5250/*==========================================
5251 * Last checks to use an item.
5252 * Return:
5253 * 0 = fail
5254 * 1 = success
5255 *------------------------------------------*/
5256int pc_useitem(struct map_session_data *sd,int n)
5257{
5258 unsigned int tick = gettick();
5259 int amount, nameid, char_id = 0;
5260 struct script_code *script;
5261 struct item item;
5262 struct item_data *id;
5263
5264 nullpo_ret(sd);
5265
5266 if( sd->npc_id ){
5267#ifdef RENEWAL
5268 clif_msg(sd, USAGE_FAIL); // TODO look for the client date that has this message.
5269 return 0;
5270#else
5271 if( !sd->npc_item_flag )
5272 return 0;
5273#endif
5274 }
5275 item = sd->status.inventory[n];
5276 id = sd->inventory_data[n];
5277
5278 if (item.nameid <= 0 || item.amount <= 0)
5279 return 0;
5280
5281 if( sd->state.only_walk )
5282 return 0;
5283 // Adelays in pc_useitem();
5284 if (!adelays_canuseitem(sd->status.inventory[n].nameid, sd->ud.canact_tick)){
5285 return 0;
5286 }
5287 // Adelays End.
5288 if( !pc_isUseitem(sd,n) )
5289 return 0;
5290
5291 // Store information for later use before it is lost (via pc_delitem) [Paradox924X]
5292 nameid = id->nameid;
5293
5294 if( item.card[0] == CARD0_CREATE )
5295 { // Do not allow use BG - Ancient Items on invalid maps
5296 char_id = MakeDWord(item.card[2],item.card[3]);
5297 if( battle_config.bg_reserved_char_id && char_id == battle_config.bg_reserved_char_id && !map_bg_items(sd->bl.m) )
5298 return 0;
5299 if( battle_config.ancient_reserved_char_id && char_id == battle_config.ancient_reserved_char_id && !map[sd->bl.m].flag.ancient )
5300 return 0;
5301 if( battle_config.woe_reserved_char_id && char_id == battle_config.woe_reserved_char_id && !map_gvg_items(sd->bl.m) )
5302 return 0;
5303 }
5304
5305 if (nameid != ITEMID_NAUTHIZ && sd->sc.opt1 > 0 && sd->sc.opt1 != OPT1_STONEWAIT && sd->sc.opt1 != OPT1_BURNING)
5306 return 0;
5307
5308 /* Items with delayed consume are not meant to work while in mounts except reins of mount(12622) */
5309 if( id->flag.delay_consume ) {
5310 if( nameid != ITEMID_REINS_OF_MOUNT && &sd->sc && sd->sc.data[SC_ALL_RIDING] )
5311 return 0;
5312 else if( pc_issit(sd) )
5313 return 0;
5314 }
5315 //Since most delay-consume items involve using a "skill-type" target cursor,
5316 //perform a skill-use check before going through. [Skotlex]
5317 //resurrection was picked as testing skill, as a non-offensive, generic skill, it will do.
5318 //FIXME: Is this really needed here? It'll be checked in unit.c after all and this prevents skill items using when silenced [Inkfish]
5319 if( id->flag.delay_consume && ( sd->ud.skilltimer != INVALID_TIMER /*|| !status_check_skilluse(&sd->bl, &sd->bl, ALL_RESURRECTION, 0)*/ ) )
5320 return 0;
5321
5322 if( id->delay > 0 && !pc_has_permission(sd,PC_PERM_ITEM_UNCONDITIONAL) ) {
5323 int i;
5324 ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid );
5325 if( i == MAX_ITEMDELAYS ) /* item not found. try first empty now */
5326 ARR_FIND(0, MAX_ITEMDELAYS, i, !sd->item_delay[i].nameid );
5327 if( i < MAX_ITEMDELAYS ) {
5328 if( sd->item_delay[i].nameid ) {// found
5329 if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) {
5330 int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000;
5331 char e_msg[100];
5332 if( e_tick > 99 )
5333 sprintf(e_msg,msg_txt(sd,379), //Item Failed. [%s] is cooling down. Wait %.1f minutes.
5334 itemdb_jname(item.nameid),
5335 (double)e_tick / 60);
5336 else
5337 sprintf(e_msg,msg_txt(sd,380), //Item Failed. [%s] is cooling down. Wait %d seconds.
5338 itemdb_jname(item.nameid),
5339 e_tick+1);
5340 clif_colormes(sd,color_table[COLOR_RED],e_msg);
5341 return 0; // Delay has not expired yet
5342 }
5343 } else {// not yet used item (all slots are initially empty)
5344 sd->item_delay[i].nameid = nameid;
5345 }
5346 if( !(nameid == ITEMID_REINS_OF_MOUNT && sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR)) )
5347 sd->item_delay[i].tick = tick + sd->inventory_data[n]->delay;
5348 } else {// should not happen
5349 ShowError("pc_useitem: Exceeded item delay array capacity! (nameid=%d, char_id=%d)\n", nameid, sd->status.char_id);
5350 }
5351 //clean up used delays so we can give room for more
5352 for(i = 0; i < MAX_ITEMDELAYS; i++) {
5353 if( DIFF_TICK(sd->item_delay[i].tick, tick) <= 0 ) {
5354 sd->item_delay[i].tick = 0;
5355 sd->item_delay[i].nameid = 0;
5356 }
5357 }
5358 }
5359
5360 /* on restricted maps the item is consumed but the effect is not used */
5361 if (!pc_has_permission(sd,PC_PERM_ITEM_UNCONDITIONAL) && itemdb_isNoEquip(id,sd->bl.m)) {
5362 if( battle_config.allow_consume_restricted_item && !id->flag.delay_consume ) { //need confirmation for delayed consumption items
5363 clif_useitemack(sd,n,item.amount-1,true);
5364 pc_delitem(sd,n,1,1,0,LOG_TYPE_CONSUME);
5365 }
5366 return 0;/* regardless, effect is not run */
5367 }
5368
5369 sd->itemid = item.nameid;
5370 sd->itemindex = n;
5371 if(sd->catch_target_class != -1) //Abort pet catching.
5372 sd->catch_target_class = -1;
5373
5374 amount = item.amount;
5375 script = id->script;
5376 //Check if the item is to be consumed immediately [Skotlex]
5377 if (id->flag.delay_consume)
5378 clif_useitemack(sd, n, amount, true);
5379 else
5380 {
5381 if( item.expire_time == 0 && nameid != ITEMID_REINS_OF_MOUNT )
5382 {
5383 clif_useitemack(sd, n, amount - 1, true);
5384 achievement_validate_item(sd,AT_ITEM_USE,item.nameid,1);
5385 pc_delitem(sd, n, 1, 1, 0, LOG_TYPE_CONSUME); // Rental Usable Items are not deleted until expiration
5386 }
5387 else
5388 clif_useitemack(sd, n, 0, false);
5389 }
5390 if( !map[sd->bl.m].flag.ancient && item.card[0] == CARD0_CREATE && char_id && (char_id == battle_config.bg_reserved_char_id || char_id == battle_config.woe_reserved_char_id || pc_famerank(char_id, MAPID_ALCHEMIST)) )
5391 {
5392 potion_flag = 2; // Famous player's potions have 50% more efficiency
5393 if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ROGUE)
5394 potion_flag = 3; //Even more effective potions.
5395 }
5396
5397 //Update item use time.
5398 sd->canuseitem_tick = tick + battle_config.item_use_interval;
5399 if( itemdb_iscashfood(nameid) )
5400 sd->canusecashfood_tick = tick + battle_config.cashfood_use_interval;
5401
5402 run_script(script,0,sd->bl.id,fake_nd->bl.id);
5403 potion_flag = 0;
5404 return 1;
5405}
5406
5407/*==========================================
5408 * Add item on cart for given index.
5409 * Return:
5410 * 0 = success
5411 * 1 = fail
5412 *------------------------------------------*/
5413int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type)
5414{
5415 struct item_data *data;
5416 int i,w;
5417
5418 nullpo_retr(1, sd);
5419 nullpo_retr(1, item_data);
5420
5421 if(item_data->nameid <= 0 || amount <= 0)
5422 return 1;
5423 data = itemdb_search(item_data->nameid);
5424
5425 if( data->stack.cart && amount > data->stack.amount )
5426 {// item stack limitation
5427 return 1;
5428 }
5429
5430 if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) || (item_data->bound > 1 && !pc_can_give_bounded_items(sd)))
5431 { // Check item trade restrictions [Skotlex]
5432 clif_displaymessage (sd->fd, msg_txt(sd,264));
5433 return 1;
5434 }
5435
5436 if( (w = data->weight*amount) + sd->cart_weight > sd->cart_weight_max )
5437 return 1;
5438
5439 i = MAX_CART;
5440 if( itemdb_isstackable2(data) && !item_data->expire_time )
5441 {
5442 ARR_FIND( 0, MAX_CART, i,
5443 sd->status.cart[i].nameid == item_data->nameid && sd->status.cart[i].bound == item_data->bound &&
5444 sd->status.cart[i].bound == item_data->bound &&
5445 sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] &&
5446 sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3] );
5447 };
5448
5449 if( i < MAX_CART )
5450 {// item already in cart, stack it
5451 if( amount > MAX_AMOUNT - sd->status.cart[i].amount || ( data->stack.cart && amount > data->stack.amount - sd->status.cart[i].amount ) )
5452 return 2; // no slot
5453
5454 sd->status.cart[i].amount+=amount;
5455 clif_cart_additem(sd,i,amount,0);
5456 }
5457 else
5458 {// item not stackable or not present, add it
5459 ARR_FIND( 0, MAX_CART, i, sd->status.cart[i].nameid == 0 );
5460 if( i == MAX_CART )
5461 return 2; // no slot
5462
5463 memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0]));
5464 sd->status.cart[i].amount=amount;
5465 sd->cart_num++;
5466 clif_cart_additem(sd,i,amount,0);
5467 }
5468 sd->status.cart[i].favorite = 0;/* clear */
5469 log_pick_pc(sd, log_type, amount, &sd->status.cart[i]);
5470
5471 sd->cart_weight += w;
5472 clif_updatestatus(sd,SP_CARTINFO);
5473
5474 return 0;
5475}
5476
5477/*==========================================
5478 * Delete item on cart for given index.
5479 * Return:
5480 * 0 = success
5481 * 1 = fail
5482 *------------------------------------------*/
5483int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type)
5484{
5485 nullpo_retr(1, sd);
5486
5487 if(sd->status.cart[n].nameid==0 ||
5488 sd->status.cart[n].amount<amount)
5489 return 1;
5490
5491 log_pick_pc(sd,log_type,-amount,&sd->status.cart[n]);
5492
5493 sd->status.cart[n].amount -= amount;
5494 sd->cart_weight -= itemdb_weight(sd->status.cart[n].nameid)*amount ;
5495 if(sd->status.cart[n].amount <= 0){
5496 memset(&sd->status.cart[n],0,sizeof(sd->status.cart[0]));
5497 sd->cart_num--;
5498 }
5499 if(!type) {
5500 clif_cart_delitem(sd,n,amount);
5501 clif_updatestatus(sd,SP_CARTINFO);
5502 }
5503
5504 return 0;
5505}
5506
5507/*==========================================
5508 * Transfer item from inventory to cart.
5509 * Return:
5510 * 0 = fail
5511 * 1 = succes
5512 *------------------------------------------*/
5513int pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
5514{
5515 struct item *item_data;
5516 short flag;
5517
5518 nullpo_ret(sd);
5519
5520 if (idx < 0 || idx >= MAX_INVENTORY) //Invalid index check [Skotlex]
5521 return 1;
5522
5523 item_data = &sd->status.inventory[idx];
5524
5525 if( item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending )
5526 return 1;
5527
5528 if( (flag = pc_cart_additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0 )
5529 return pc_delitem(sd,idx,amount,0,5,LOG_TYPE_NONE);
5530
5531 return flag;
5532}
5533
5534/*==========================================
5535 * Get number of item in cart.
5536 * Return:
5537 -1 = itemid not found or no amount found
5538 x = remaining itemid on cart after get
5539 *------------------------------------------*/
5540int pc_cartitem_amount(struct map_session_data* sd, int idx, int amount)
5541{
5542 struct item* item_data;
5543
5544 nullpo_retr(-1, sd);
5545
5546 item_data = &sd->status.cart[idx];
5547 if( item_data->nameid == 0 || item_data->amount == 0 )
5548 return -1;
5549
5550 return item_data->amount - amount;
5551}
5552
5553/*==========================================
5554 * Retrieve an item at index idx from cart.
5555 * Return:
5556 * 0 = player not found or (FIXME) succes (from pc_cart_delitem)
5557 * 1 = failure
5558 *------------------------------------------*/
5559int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
5560{
5561 struct item *item_data;
5562 int flag;
5563
5564 nullpo_ret(sd);
5565
5566 if (idx < 0 || idx >= MAX_CART) //Invalid index check [Skotlex]
5567 return 1;
5568
5569 item_data=&sd->status.cart[idx];
5570
5571 if(item_data->nameid==0 || amount < 1 || item_data->amount<amount || sd->state.vending )
5572 return 1;
5573 if((flag = pc_additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0)
5574 return pc_cart_delitem(sd,idx,amount,0,LOG_TYPE_NONE);
5575
5576 clif_additem(sd,0,0,flag);
5577 return 1;
5578}
5579
5580/*==========================================
5581 * Bound Item Check
5582 * Type:
5583 * 1 Account Bound
5584 * 2 Guild Bound
5585 * 3 Party Bound
5586 * 4 Character Bound
5587 *------------------------------------------*/
5588int pc_bound_chk(TBL_PC *sd,int type,int *idxlist)
5589{
5590 int i=0, j=0;
5591 for(i=0;i<MAX_INVENTORY;i++){
5592 if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0 && sd->status.inventory[i].bound == type) {
5593 idxlist[j] = i;
5594 j++;
5595 }
5596 }
5597 return j;
5598}
5599
5600/*==========================================
5601 * Display item stolen msg to player sd
5602 *------------------------------------------*/
5603int pc_show_steal(struct block_list *bl,va_list ap)
5604{
5605 struct map_session_data *sd;
5606 int itemid;
5607
5608 struct item_data *item=NULL;
5609 char output[100];
5610
5611 sd=va_arg(ap,struct map_session_data *);
5612 itemid=va_arg(ap,int);
5613
5614 if((item=itemdb_exists(itemid))==NULL)
5615 sprintf(output,"%s stole an Unknown Item (id: %i).",sd->status.name, itemid);
5616 else
5617 sprintf(output,"%s stole %s.",sd->status.name,item->jname);
5618 clif_displaymessage( ((struct map_session_data *)bl)->fd, output);
5619
5620 return 0;
5621}
5622/*==========================================
5623 * Steal an item from bl (mob).
5624 * Return:
5625 * 0 = fail
5626 * 1 = succes
5627 *------------------------------------------*/
5628int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skill_lv)
5629{
5630 int i,itemid,flag;
5631 double rate;
5632 struct status_data *sd_status, *md_status;
5633 struct mob_data *md;
5634 struct item tmp_item;
5635
5636 if(!sd || !bl || bl->type!=BL_MOB)
5637 return 0;
5638
5639 md = (TBL_MOB *)bl;
5640
5641 if(md->state.steal_flag == UCHAR_MAX || ( md->sc.opt1 && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE ) || md->option.no_expdrop ) //already stolen from / status change check
5642 return 0;
5643
5644 sd_status= status_get_status_data(&sd->bl);
5645 md_status= status_get_status_data(bl);
5646
5647 if( md->master_id || md_status->mode&MD_BOSS || mob_is_treasure(md) ||
5648 map[bl->m].flag.nomobloot || // check noloot map flag [Lorky]
5649 (battle_config.skill_steal_max_tries && //Reached limit of steal attempts. [Lupus]
5650 md->state.steal_flag++ >= battle_config.skill_steal_max_tries)
5651 ) { //Can't steal from
5652 md->state.steal_flag = UCHAR_MAX;
5653 return 0;
5654 }
5655
5656 // base skill success chance (percentual)
5657 //rate = (sd_status->dex - md_status->dex)/2 + skill_lv*6 + 4;
5658 rate = 10 + skill_lv*3;
5659 rate += sd->bonus.add_steal_rate;
5660
5661 if( rate < 1 )
5662 return 0;
5663
5664 // Try dropping one item, in the order from first to last possible slot.
5665 // Droprate is affected by the skill success rate.
5666 for( i = 0; i < MAX_STEAL_DROP; i++ )
5667 if( md->db->dropitem[i].nameid > 0 && itemdb_exists(md->db->dropitem[i].nameid) && rnd() % 10000 < md->db->dropitem[i].p * rate/100. )
5668 break;
5669 if( i == MAX_STEAL_DROP )
5670 return 0;
5671
5672 itemid = md->db->dropitem[i].nameid;
5673 memset(&tmp_item,0,sizeof(tmp_item));
5674 tmp_item.nameid = itemid;
5675 tmp_item.amount = 1;
5676 tmp_item.identify = itemdb_isidentified(itemid);
5677 flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER);
5678
5679 //TODO: Should we disable stealing when the item you stole couldn't be added to your inventory? Perhaps players will figure out a way to exploit this behaviour otherwise?
5680 md->state.steal_flag = UCHAR_MAX; //you can't steal from this mob any more
5681
5682 if(flag) { //Failed to steal due to overweight
5683 clif_additem(sd,0,0,flag);
5684 return 0;
5685 }
5686
5687 if(battle_config.show_steal_in_same_party)
5688 party_foreachsamemap(pc_show_steal,sd,AREA_SIZE,sd,tmp_item.nameid);
5689
5690 //Logs items, Stolen from mobs [Lupus]
5691 log_pick_mob(md, LOG_TYPE_PICKDROP_MONSTER, -1, &tmp_item);
5692
5693 //A Rare Steal Global Announce by Lupus
5694 if(md->db->dropitem[i].p<=battle_config.rare_drop_announce) {
5695 struct item_data *i_data;
5696 char message[128];
5697 i_data = itemdb_search(itemid);
5698 sprintf (message, msg_txt(sd,542), (sd->status.name != NULL)?sd->status.name :"GM", md->db->jname, i_data->jname, (float)md->db->dropitem[i].p/100);
5699 //MSG: "'%s' stole %s's %s (chance: %0.02f%%)"
5700 intif_broadcast(message,strlen(message)+1,0);
5701 }
5702 return 1;
5703}
5704
5705/*==========================================
5706 * Stole zeny from bl (mob)
5707 * return
5708 * 0 = fail
5709 * 1 = success
5710 *------------------------------------------*/
5711int pc_steal_coin(struct map_session_data *sd,struct block_list *target)
5712{
5713 int rate,skill;
5714 struct mob_data *md;
5715 if(!sd || !target || target->type != BL_MOB)
5716 return 0;
5717
5718 md = (TBL_MOB*)target;
5719 if( md->state.steal_coin_flag || md->sc.data[SC_STONE] || md->sc.data[SC_FREEZE] || md->status.mode&MD_BOSS )
5720 return 0;
5721
5722 if( mob_is_treasure(md) )
5723 return 0;
5724
5725 // FIXME: This formula is either custom or outdated.
5726 skill = pc_checkskill(sd,RG_STEALCOIN)*10;
5727 rate = skill + (sd->status.base_level - md->level)*3 + sd->battle_status.dex*2 + sd->battle_status.luk*2;
5728 if(rnd()%1000 < rate)
5729 {
5730 int amount = md->level*10 + rnd()%100;
5731
5732 pc_getzeny(sd, amount, LOG_TYPE_STEAL, NULL);
5733 md->state.steal_coin_flag = 1;
5734 return 1;
5735 }
5736 return 0;
5737}
5738
5739/*==========================================
5740 * Set's a player position.
5741 * Return values:
5742 * 0 - Success.
5743 * 1 - Invalid map index.
5744 * 2 - Map not in this map-server, and failed to locate alternate map-server.
5745 *------------------------------------------*/
5746int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype)
5747{
5748 struct guild *g;
5749 struct party_data *p;
5750 struct guild_castle *gc;
5751 int16 m;
5752 int i, c;
5753
5754 nullpo_ret(sd);
5755
5756 if( !mapindex || !mapindex_id2name(mapindex) ) {
5757 ShowDebug("pc_setpos: Passed mapindex(%d) is invalid!\n", mapindex);
5758 return 1;
5759 }
5760
5761 if( pc_isdead(sd) ) { //Revive dead people before warping them
5762 pc_setstand(sd);
5763 pc_setrestartvalue(sd,1);
5764 }
5765
5766 m = map_mapindex2mapid(mapindex);
5767
5768 if( (map[m].flag.blocked && !pc_has_permission(sd,PC_PERM_WARP_ANYWHERE)) || (map[m].flag.ancient && (sd->md || !pc_class2ancientwoe(sd->status.class_) || pc_checkskill(sd, ALL_INCCARRY))) )
5769 {
5770 mapindex = sd->status.save_point.map;
5771 x = sd->status.save_point.x;
5772 y = sd->status.save_point.y;
5773 m = map_mapindex2mapid(mapindex);
5774 }
5775 else if( map_blocked_woe(m) && (gc = guild_mapindex2gc(map[m].index)) != NULL && (gc->guild_id == 0 || sd->status.guild_id != gc->guild_id) )
5776 { // Non Castle Owners on different WoE times
5777 mapindex = sd->status.save_point.map;
5778 x = sd->status.save_point.x;
5779 y = sd->status.save_point.y;
5780 m = map_mapindex2mapid(mapindex);
5781 }
5782 else if( map[m].guild_max && sd->bl.m != m && sd->status.guild_id && (g = guild_search(sd->status.guild_id)) != NULL )
5783 { // Guild Limit
5784 for( i = c = 0; i < g->max_member && c < map[m].guild_max; i++ )
5785 if( g->member[i].sd && g->member[i].sd->bl.m == m )
5786 c++;
5787
5788 if( c >= map[m].guild_max )
5789 { // No more guild members on this map
5790 mapindex = sd->status.save_point.map;
5791 x = sd->status.save_point.x;
5792 y = sd->status.save_point.y;
5793 m = map_mapindex2mapid(mapindex);
5794 }
5795 }
5796 else if( map[m].party_max && sd->bl.m != m && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL )
5797 { // Party Limit
5798 for( i = c = 0; i < MAX_PARTY && c < map[m].party_max; i++ )
5799 if( p->data[i].sd && p->data[i].sd->bl.m == m )
5800 c++;
5801
5802 if( c >= map[m].party_max )
5803 { // No more party members on this map
5804 mapindex = sd->status.save_point.map;
5805 x = sd->status.save_point.x;
5806 y = sd->status.save_point.y;
5807 m = map_mapindex2mapid(mapindex);
5808 }
5809 }
5810
5811 sd->state.changemap = (sd->mapindex != mapindex);
5812 sd->state.warping = 1;
5813
5814 if(sd->status.party_id && map[sd->bl.m].instance_id && sd->state.changemap && !map[m].instance_id) {
5815 if((p = party_search(sd->status.party_id)) != NULL && p->instance_id )
5816 instance_delusers(p->instance_id);
5817 }
5818 if( sd->state.changemap ) { // Misc map-changing settings
5819 int i;
5820 sd->state.pmap = sd->bl.m;
5821 sd->state.only_walk = 0;
5822 sd->pvpevent_fame = 0;
5823
5824 if (sd->sc.count) { // Cancel some map related stuff.
5825 if (sd->sc.data[SC_JAILED])
5826 return 1; //You may not get out!
5827 status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER);
5828 status_change_end(&sd->bl, SC_WARM, INVALID_TIMER);
5829 status_change_end(&sd->bl, SC_SUN_COMFORT, INVALID_TIMER);
5830 status_change_end(&sd->bl, SC_MOON_COMFORT, INVALID_TIMER);
5831 status_change_end(&sd->bl, SC_STAR_COMFORT, INVALID_TIMER);
5832 status_change_end(&sd->bl, SC_MIRACLE, INVALID_TIMER);
5833 if (sd->sc.data[SC_KNOWLEDGE]) {
5834 struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE];
5835 if (sce->timer != INVALID_TIMER)
5836 delete_timer(sce->timer, status_change_timer);
5837 sce->timer = add_timer(gettick() + skill_get_time(SG_KNOWLEDGE, sce->val1), status_change_timer, sd->bl.id, SC_KNOWLEDGE);
5838 }
5839 status_change_end(&sd->bl, SC_PROPERTYWALK, INVALID_TIMER);
5840 status_change_end(&sd->bl, SC_CLOAKING, INVALID_TIMER);
5841 status_change_end(&sd->bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
5842 if( map[m].flag.ancient )
5843 { // Ancient WoE Deffus
5844 int i;
5845 const enum sc_type scs[] = { SC_SPREGEN, SC_GOSPEL, SC_MAGICPOWER, SC_ASSUMPTIO, SC_SPIRIT, SC_INTRAVISION, SC_INCALLSTATUS, SC_INCSTR, SC_INCAGI, SC_INCVIT, SC_INCINT, SC_INCDEX, SC_INCLUK, SC_INCHIT, SC_INCHITRATE, SC_INCFLEE, SC_INCFLEERATE, SC_INCMHPRATE, SC_INCMSPRATE, SC_INCATKRATE, SC_INCMATKRATE, SC_INCDEFRATE, SC_STRFOOD, SC_AGIFOOD, SC_VITFOOD, SC_INTFOOD, SC_DEXFOOD, SC_LUKFOOD, SC_HITFOOD, SC_FLEEFOOD, SC_BATKFOOD, SC_WATKFOOD, SC_MATKFOOD, SC_SCRESIST, SC_INCCRI, SC_MDEF_RATE, SC_INCHEALRATE, SC_ARMOR_RESIST, SC_SPCOST_RATE, SC_COMMONSC_RESIST, SC_DEF_RATE, SC_KAITE, SC_KAUPE, SC_ITEMSCRIPT, SC_S_LIFEPOTION, SC_L_LIFEPOTION };
5846
5847 for( i = 0; i < ARRAYLENGTH(scs); i++ )
5848 {
5849 if( sd->sc.data[scs[i]] )
5850 status_change_end(&sd->bl, scs[i], -1);
5851 }
5852
5853 // Full Chemical Protection
5854 for( i = 0; i < 4; i++ )
5855 {
5856 if( sd->sc.data[SC_CP_WEAPON + i] && sd->sc.data[SC_CP_WEAPON + i]->val4 == CR_FULLPROTECTION )
5857 status_change_end(&sd->bl, (sc_type)(SC_CP_WEAPON + i), -1);
5858 }
5859 }
5860 }
5861 for( i = 0; i < EQI_MAX; i++ ) {
5862 if( sd->equip_index[ i ] >= 0 )
5863 if( !pc_isequip( sd , sd->equip_index[ i ] ) )
5864 pc_unequipitem( sd , sd->equip_index[ i ] , 2 );
5865 }
5866 if (battle_config.clear_unit_onwarp&BL_PC)
5867 skill_clear_unitgroup(&sd->bl);
5868 party_send_dot_remove(sd); //minimap dot fix [Kevin]
5869 guild_send_dot_remove(sd);
5870 bg_send_dot_remove(sd);
5871 if( battle_config.bg_queue_onlytowns && sd->qd && map[sd->bl.m].flag.town && !map[m].flag.town )
5872 queue_leaveall(sd);
5873 if (sd->regen.state.gc)
5874 sd->regen.state.gc = 0;
5875 // make sure vending is allowed here
5876 if (sd->state.vending && map[m].flag.novending) {
5877 clif_displaymessage (sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
5878 vending_closevending(sd);
5879 }
5880 }
5881
5882 if( m < 0 )
5883 {
5884 uint32 ip;
5885 uint16 port;
5886 //if can't find any map-servers, just abort setting position.
5887 if(!sd->mapindex || map_mapname2ipport(mapindex,&ip,&port))
5888 return 2;
5889
5890 if (sd->npc_id)
5891 npc_event_dequeue(sd);
5892 npc_script_event(sd, NPCE_LOGOUT);
5893 //remove from map, THEN change x/y coordinates
5894 unit_remove_map_pc(sd,clrtype);
5895 sd->mapindex = mapindex;
5896 sd->bl.x=x;
5897 sd->bl.y=y;
5898 pc_clean_skilltree(sd);
5899 chrif_save(sd,2);
5900 chrif_changemapserver(sd, ip, (short)port);
5901
5902 //Free session data from this map server [Kevin]
5903 unit_free_pc(sd);
5904
5905 return 0;
5906 }
5907
5908 if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
5909 {
5910 ShowError("pc_setpos: attempt to place player %s (%d:%d) on invalid coordinates (%s-%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(mapindex),x,y);
5911 x = y = 0; // make it random
5912 }
5913
5914 if( x == 0 && y == 0 )
5915 {// pick a random walkable cell
5916 do {
5917 x=rnd()%(map[m].xs-2)+1;
5918 y=rnd()%(map[m].ys-2)+1;
5919 } while(map_getcell(m,x,y,CELL_CHKNOPASS));
5920 }
5921
5922 if (sd->state.vending && map_getcell(m,x,y,CELL_CHKNOVENDING)) {
5923 clif_displaymessage (sd->fd, msg_txt(sd,204)); // "You can't open a shop on this cell."
5924 vending_closevending(sd);
5925 }
5926
5927 if(sd->bl.prev != NULL){
5928 unit_remove_map_pc(sd,clrtype);
5929 clif_changemap(sd,m,x,y); // [MouseJstr]
5930 } else if(sd->state.active) //Tag player for rewarping after map-loading is done. [Skotlex]
5931 sd->state.rewarp = 1;
5932
5933 sd->state.changeregion = (map[sd->bl.m].region_id != map[m].region_id);
5934 sd->mapindex = mapindex;
5935 sd->bl.m = m;
5936 sd->bl.x = sd->ud.to_x = x;
5937 sd->bl.y = sd->ud.to_y = y;
5938
5939 if( sd->status.guild_id > 0 && map[m].flag.gvg_castle )
5940 { // Increased guild castle regen [Valaris]
5941 struct guild_castle *gc = guild_mapindex2gc(sd->mapindex);
5942 if(gc && gc->guild_id == sd->status.guild_id)
5943 sd->regen.state.gc = 1;
5944 }
5945
5946 if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 )
5947 {
5948 sd->pd->bl.m = m;
5949 sd->pd->bl.x = sd->pd->ud.to_x = x;
5950 sd->pd->bl.y = sd->pd->ud.to_y = y;
5951 sd->pd->ud.dir = sd->ud.dir;
5952 }
5953
5954 if( merc_is_hom_active(sd->hd) )
5955 {
5956 sd->hd->bl.m = m;
5957 sd->hd->bl.x = sd->hd->ud.to_x = x;
5958 sd->hd->bl.y = sd->hd->ud.to_y = y;
5959 sd->hd->ud.dir = sd->ud.dir;
5960 }
5961
5962 if( sd->md )
5963 {
5964 sd->md->bl.m = m;
5965 sd->md->bl.x = sd->md->ud.to_x = x;
5966 sd->md->bl.y = sd->md->ud.to_y = y;
5967 sd->md->ud.dir = sd->ud.dir;
5968 }
5969
5970 pc_cell_basilica(sd);
5971 return 0;
5972}
5973
5974/*==========================================
5975 * Warp player sd to random location on current map.
5976 * May fail if no walkable cell found (1000 attempts).
5977 * Return:
5978 * 0 = fail or FIXME success (from pc_setpos)
5979 * x(1|2) = fail
5980 *------------------------------------------*/
5981int pc_randomwarp(struct map_session_data *sd, clr_type type)
5982{
5983 int x,y,i=0;
5984 int16 m;
5985
5986 nullpo_ret(sd);
5987
5988 m=sd->bl.m;
5989
5990 if (map[sd->bl.m].flag.noteleport) //Teleport forbidden
5991 return 0;
5992
5993 do{
5994 x=rnd()%(map[m].xs-2)+1;
5995 y=rnd()%(map[m].ys-2)+1;
5996 }while(map_getcell(m,x,y,CELL_CHKNOPASS) && (i++)<1000 );
5997
5998 if (i < 1000)
5999 return pc_setpos(sd,map[sd->bl.m].index,x,y,type);
6000
6001 return 0;
6002}
6003
6004/*==========================================
6005 * Records a memo point at sd's current position
6006 * pos - entry to replace, (-1: shift oldest entry out)
6007 *------------------------------------------*/
6008int pc_memo(struct map_session_data* sd, int pos)
6009{
6010 int skill;
6011
6012 nullpo_ret(sd);
6013
6014 // check mapflags
6015 if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) {
6016 clif_skill_teleportmessage(sd, 1); // "Saved point cannot be memorized."
6017 return 0;
6018 }
6019
6020 // check inputs
6021 if( pos < -1 || pos >= MAX_MEMOPOINTS )
6022 return 0; // invalid input
6023
6024 // check required skill level
6025 skill = pc_checkskill(sd, AL_WARP);
6026 if( skill < 1 ) {
6027 clif_skill_memomessage(sd,2); // "You haven't learned Warp."
6028 return 0;
6029 }
6030 if( skill < 2 || skill - 2 < pos ) {
6031 clif_skill_memomessage(sd,1); // "Skill Level is not high enough."
6032 return 0;
6033 }
6034
6035 if( pos == -1 )
6036 {
6037 int i;
6038 // prevent memo-ing the same map multiple times
6039 ARR_FIND( 0, MAX_MEMOPOINTS, i, sd->status.memo_point[i].map == map_id2index(sd->bl.m) );
6040 memmove(&sd->status.memo_point[1], &sd->status.memo_point[0], (min(i,MAX_MEMOPOINTS-1))*sizeof(struct point));
6041 pos = 0;
6042 }
6043
6044 if( map[sd->bl.m].instance_id ) {
6045 clif_displaymessage( sd->fd, msg_txt(sd,384) ); // You cannot create a memo in an instance.
6046 return 0;
6047 }
6048
6049 sd->status.memo_point[pos].map = map_id2index(sd->bl.m);
6050 sd->status.memo_point[pos].x = sd->bl.x;
6051 sd->status.memo_point[pos].y = sd->bl.y;
6052
6053 clif_skill_memomessage(sd, 0);
6054
6055 return 1;
6056}
6057
6058//
6059// Skills
6060//
6061/*==========================================
6062 * Return player sd skill_lv learned for given skill
6063 *------------------------------------------*/
6064int pc_checkskill(struct map_session_data *sd,uint16 skill_id)
6065{
6066 if(sd == NULL) return 0;
6067 if( skill_id >= GD_SKILLBASE && skill_id < GD_MAX ) {
6068 struct guild *g;
6069
6070 if( sd->status.guild_id>0 && (g=sd->guild)!=NULL)
6071 return guild_checkskill(g,skill_id);
6072 return 0;
6073 } else if(skill_id >= ARRAYLENGTH(sd->status.skill) ) {
6074 ShowError("pc_checkskill: Invalid skill id %d (char_id=%d).\n", skill_id, sd->status.char_id);
6075 return 0;
6076 }
6077
6078 if(sd->status.skill[skill_id].id == skill_id)
6079 return (sd->status.skill[skill_id].lv);
6080
6081 return 0;
6082}
6083
6084/**
6085 * Chk if we still have the correct weapon to continue the skill (actually status)
6086 * If not ending it
6087 * @param sd
6088 * @return 0:error, 1:check done
6089 */
6090static void pc_checkallowskill(struct map_session_data *sd)
6091{
6092 const enum sc_type scw_list[] = {
6093 SC_TWOHANDQUICKEN,
6094 SC_ONEHAND,
6095 SC_AURABLADE,
6096 SC_PARRYING,
6097 SC_SPEARQUICKEN,
6098 SC_ADRENALINE,
6099 SC_ADRENALINE2,
6100 SC_DANCING,
6101 SC_GATLINGFEVER,
6102 SC_FEARBREEZE
6103 };
6104 uint8 i;
6105 nullpo_retv(sd);
6106
6107 if(!sd->sc.count)
6108 return;
6109
6110 for (i = 0; i < ARRAYLENGTH(scw_list); i++)
6111 { // Skills requiring specific weapon types
6112 if( scw_list[i] == SC_DANCING && !battle_config.dancing_weaponswitch_fix )
6113 continue;
6114 if(sd->sc.data[scw_list[i]] &&
6115 !pc_check_weapontype(sd,skill_get_weapontype(status_sc2skill(scw_list[i]))))
6116 status_change_end(&sd->bl, scw_list[i], INVALID_TIMER);
6117 }
6118
6119 if(sd->sc.data[SC_SPURT] && sd->status.weapon)
6120 // Spurt requires bare hands (feet, in fact xD)
6121 status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER);
6122
6123 if(sd->status.shield <= 0) { // Skills requiring a shield
6124 const enum sc_type scs_list[] = {
6125 SC_AUTOGUARD,
6126 SC_DEFENDER,
6127 SC_REFLECTSHIELD,
6128 SC_REFLECTDAMAGE
6129 };
6130 for (i = 0; i < ARRAYLENGTH(scs_list); i++)
6131 if(sd->sc.data[scs_list[i]])
6132 status_change_end(&sd->bl, scs_list[i], INVALID_TIMER);
6133 }
6134}
6135
6136/*==========================================
6137 * Return equiped itemid? on player sd at pos
6138 * Return
6139 * -1 : mean nothing equiped
6140 * idx : (this index could be used in inventory to found item_data)
6141 *------------------------------------------*/
6142short pc_checkequip(struct map_session_data *sd,int pos)
6143{
6144 uint8 i;
6145
6146 nullpo_retr(-1, sd);
6147
6148 for(i=0;i<EQI_MAX;i++){
6149 if(pos & equip_pos[i])
6150 return sd->equip_index[i];
6151 }
6152
6153 return -1;
6154}
6155
6156/*==========================================
6157 * Check if sd as nameid equiped somewhere
6158 * @sd : the player session
6159 * @nameid : id of the item to check
6160 * @min : : see pc.h enum equip_index from ? to @max
6161 * @max : see pc.h enum equip_index for @min to ?
6162 * -return true,false
6163 *------------------------------------------*/
6164bool pc_checkequip2(struct map_session_data *sd,int nameid, int min, int max){
6165 int i;
6166 for(i=min;i<max;i++){
6167 if(equip_pos[i]){
6168 int idx = sd->equip_index[i];
6169 if (sd->status.inventory[idx].nameid == nameid)
6170 return true;
6171 }
6172 }
6173 return false;
6174}
6175
6176/*==========================================
6177 * Convert's from the client's lame Job ID system
6178 * to the map server's 'makes sense' system. [Skotlex]
6179 *------------------------------------------*/
6180int pc_jobid2mapid(unsigned short b_class)
6181{
6182 switch(b_class)
6183 {
6184 //Novice And 1-1 Jobs
6185 case JOB_NOVICE: return MAPID_NOVICE;
6186 case JOB_SWORDMAN: return MAPID_SWORDMAN;
6187 case JOB_MAGE: return MAPID_MAGE;
6188 case JOB_ARCHER: return MAPID_ARCHER;
6189 case JOB_ACOLYTE: return MAPID_ACOLYTE;
6190 case JOB_MERCHANT: return MAPID_MERCHANT;
6191 case JOB_THIEF: return MAPID_THIEF;
6192 case JOB_TAEKWON: return MAPID_TAEKWON;
6193 case JOB_WEDDING: return MAPID_WEDDING;
6194 case JOB_GUNSLINGER: return MAPID_GUNSLINGER;
6195 case JOB_NINJA: return MAPID_NINJA;
6196 case JOB_XMAS: return MAPID_XMAS;
6197 case JOB_SUMMER: return MAPID_SUMMER;
6198 case JOB_HANBOK: return MAPID_HANBOK;
6199 case JOB_OKTOBERFEST: return MAPID_OKTOBERFEST;
6200 case JOB_GANGSI: return MAPID_GANGSI;
6201 //2-1 Jobs
6202 case JOB_SUPER_NOVICE: return MAPID_SUPER_NOVICE;
6203 case JOB_KNIGHT: return MAPID_KNIGHT;
6204 case JOB_WIZARD: return MAPID_WIZARD;
6205 case JOB_HUNTER: return MAPID_HUNTER;
6206 case JOB_PRIEST: return MAPID_PRIEST;
6207 case JOB_BLACKSMITH: return MAPID_BLACKSMITH;
6208 case JOB_ASSASSIN: return MAPID_ASSASSIN;
6209 case JOB_STAR_GLADIATOR: return MAPID_STAR_GLADIATOR;
6210 case JOB_KAGEROU:
6211 case JOB_OBORO: return MAPID_KAGEROUOBORO;
6212 case JOB_REBELLION: return MAPID_REBELLION;
6213 case JOB_DEATH_KNIGHT: return MAPID_DEATH_KNIGHT;
6214 //2-2 Jobs
6215 case JOB_CRUSADER: return MAPID_CRUSADER;
6216 case JOB_SAGE: return MAPID_SAGE;
6217 case JOB_BARD:
6218 case JOB_DANCER: return MAPID_BARDDANCER;
6219 case JOB_MONK: return MAPID_MONK;
6220 case JOB_ALCHEMIST: return MAPID_ALCHEMIST;
6221 case JOB_ROGUE: return MAPID_ROGUE;
6222 case JOB_SOUL_LINKER: return MAPID_SOUL_LINKER;
6223 case JOB_DARK_COLLECTOR: return MAPID_DARK_COLLECTOR;
6224 //Trans Novice And Trans 1-1 Jobs
6225 case JOB_NOVICE_HIGH: return MAPID_NOVICE_HIGH;
6226 case JOB_SWORDMAN_HIGH: return MAPID_SWORDMAN_HIGH;
6227 case JOB_MAGE_HIGH: return MAPID_MAGE_HIGH;
6228 case JOB_ARCHER_HIGH: return MAPID_ARCHER_HIGH;
6229 case JOB_ACOLYTE_HIGH: return MAPID_ACOLYTE_HIGH;
6230 case JOB_MERCHANT_HIGH: return MAPID_MERCHANT_HIGH;
6231 case JOB_THIEF_HIGH: return MAPID_THIEF_HIGH;
6232 //Trans 2-1 Jobs
6233 case JOB_LORD_KNIGHT: return MAPID_LORD_KNIGHT;
6234 case JOB_HIGH_WIZARD: return MAPID_HIGH_WIZARD;
6235 case JOB_SNIPER: return MAPID_SNIPER;
6236 case JOB_HIGH_PRIEST: return MAPID_HIGH_PRIEST;
6237 case JOB_WHITESMITH: return MAPID_WHITESMITH;
6238 case JOB_ASSASSIN_CROSS: return MAPID_ASSASSIN_CROSS;
6239 //Trans 2-2 Jobs
6240 case JOB_PALADIN: return MAPID_PALADIN;
6241 case JOB_PROFESSOR: return MAPID_PROFESSOR;
6242 case JOB_CLOWN:
6243 case JOB_GYPSY: return MAPID_CLOWNGYPSY;
6244 case JOB_CHAMPION: return MAPID_CHAMPION;
6245 case JOB_CREATOR: return MAPID_CREATOR;
6246 case JOB_STALKER: return MAPID_STALKER;
6247 //Baby Novice And Baby 1-1 Jobs
6248 case JOB_BABY: return MAPID_BABY;
6249 case JOB_BABY_SWORDMAN: return MAPID_BABY_SWORDMAN;
6250 case JOB_BABY_MAGE: return MAPID_BABY_MAGE;
6251 case JOB_BABY_ARCHER: return MAPID_BABY_ARCHER;
6252 case JOB_BABY_ACOLYTE: return MAPID_BABY_ACOLYTE;
6253 case JOB_BABY_MERCHANT: return MAPID_BABY_MERCHANT;
6254 case JOB_BABY_THIEF: return MAPID_BABY_THIEF;
6255 //Baby 2-1 Jobs
6256 case JOB_SUPER_BABY: return MAPID_SUPER_BABY;
6257 case JOB_BABY_KNIGHT: return MAPID_BABY_KNIGHT;
6258 case JOB_BABY_WIZARD: return MAPID_BABY_WIZARD;
6259 case JOB_BABY_HUNTER: return MAPID_BABY_HUNTER;
6260 case JOB_BABY_PRIEST: return MAPID_BABY_PRIEST;
6261 case JOB_BABY_BLACKSMITH: return MAPID_BABY_BLACKSMITH;
6262 case JOB_BABY_ASSASSIN: return MAPID_BABY_ASSASSIN;
6263 //Baby 2-2 Jobs
6264 case JOB_BABY_CRUSADER: return MAPID_BABY_CRUSADER;
6265 case JOB_BABY_SAGE: return MAPID_BABY_SAGE;
6266 case JOB_BABY_BARD:
6267 case JOB_BABY_DANCER: return MAPID_BABY_BARDDANCER;
6268 case JOB_BABY_MONK: return MAPID_BABY_MONK;
6269 case JOB_BABY_ALCHEMIST: return MAPID_BABY_ALCHEMIST;
6270 case JOB_BABY_ROGUE: return MAPID_BABY_ROGUE;
6271 //3-1 Jobs
6272 case JOB_SUPER_NOVICE_E: return MAPID_SUPER_NOVICE_E;
6273 case JOB_RUNE_KNIGHT: return MAPID_RUNE_KNIGHT;
6274 case JOB_WARLOCK: return MAPID_WARLOCK;
6275 case JOB_RANGER: return MAPID_RANGER;
6276 case JOB_ARCH_BISHOP: return MAPID_ARCH_BISHOP;
6277 case JOB_MECHANIC: return MAPID_MECHANIC;
6278 case JOB_GUILLOTINE_CROSS: return MAPID_GUILLOTINE_CROSS;
6279 //3-2 Jobs
6280 case JOB_ROYAL_GUARD: return MAPID_ROYAL_GUARD;
6281 case JOB_SORCERER: return MAPID_SORCERER;
6282 case JOB_MINSTREL:
6283 case JOB_WANDERER: return MAPID_MINSTRELWANDERER;
6284 case JOB_SURA: return MAPID_SURA;
6285 case JOB_GENETIC: return MAPID_GENETIC;
6286 case JOB_SHADOW_CHASER: return MAPID_SHADOW_CHASER;
6287 //Trans 3-1 Jobs
6288 case JOB_RUNE_KNIGHT_T: return MAPID_RUNE_KNIGHT_T;
6289 case JOB_WARLOCK_T: return MAPID_WARLOCK_T;
6290 case JOB_RANGER_T: return MAPID_RANGER_T;
6291 case JOB_ARCH_BISHOP_T: return MAPID_ARCH_BISHOP_T;
6292 case JOB_MECHANIC_T: return MAPID_MECHANIC_T;
6293 case JOB_GUILLOTINE_CROSS_T: return MAPID_GUILLOTINE_CROSS_T;
6294 //Trans 3-2 Jobs
6295 case JOB_ROYAL_GUARD_T: return MAPID_ROYAL_GUARD_T;
6296 case JOB_SORCERER_T: return MAPID_SORCERER_T;
6297 case JOB_MINSTREL_T:
6298 case JOB_WANDERER_T: return MAPID_MINSTRELWANDERER_T;
6299 case JOB_SURA_T: return MAPID_SURA_T;
6300 case JOB_GENETIC_T: return MAPID_GENETIC_T;
6301 case JOB_SHADOW_CHASER_T: return MAPID_SHADOW_CHASER_T;
6302 //Baby 3-1 Jobs
6303 case JOB_SUPER_BABY_E: return MAPID_SUPER_BABY_E;
6304 case JOB_BABY_RUNE: return MAPID_BABY_RUNE;
6305 case JOB_BABY_WARLOCK: return MAPID_BABY_WARLOCK;
6306 case JOB_BABY_RANGER: return MAPID_BABY_RANGER;
6307 case JOB_BABY_BISHOP: return MAPID_BABY_BISHOP;
6308 case JOB_BABY_MECHANIC: return MAPID_BABY_MECHANIC;
6309 case JOB_BABY_CROSS: return MAPID_BABY_CROSS;
6310 //Baby 3-2 Jobs
6311 case JOB_BABY_GUARD: return MAPID_BABY_GUARD;
6312 case JOB_BABY_SORCERER: return MAPID_BABY_SORCERER;
6313 case JOB_BABY_MINSTREL:
6314 case JOB_BABY_WANDERER: return MAPID_BABY_MINSTRELWANDERER;
6315 case JOB_BABY_SURA: return MAPID_BABY_SURA;
6316 case JOB_BABY_GENETIC: return MAPID_BABY_GENETIC;
6317 case JOB_BABY_CHASER: return MAPID_BABY_CHASER;
6318 default:
6319 return -1;
6320 }
6321}
6322
6323//Reverts the map-style class id to the client-style one.
6324int pc_mapid2jobid(unsigned short class_, int sex)
6325{
6326 switch(class_)
6327 {
6328 //Novice And 1-1 Jobs
6329 case MAPID_NOVICE: return JOB_NOVICE;
6330 case MAPID_SWORDMAN: return JOB_SWORDMAN;
6331 case MAPID_MAGE: return JOB_MAGE;
6332 case MAPID_ARCHER: return JOB_ARCHER;
6333 case MAPID_ACOLYTE: return JOB_ACOLYTE;
6334 case MAPID_MERCHANT: return JOB_MERCHANT;
6335 case MAPID_THIEF: return JOB_THIEF;
6336 case MAPID_TAEKWON: return JOB_TAEKWON;
6337 case MAPID_WEDDING: return JOB_WEDDING;
6338 case MAPID_GUNSLINGER: return JOB_GUNSLINGER;
6339 case MAPID_NINJA: return JOB_NINJA;
6340 case MAPID_XMAS: return JOB_XMAS;
6341 case MAPID_SUMMER: return JOB_SUMMER;
6342 case MAPID_HANBOK: return JOB_HANBOK;
6343 case MAPID_OKTOBERFEST: return JOB_OKTOBERFEST;
6344 case MAPID_GANGSI: return JOB_GANGSI;
6345 //2-1 Jobs
6346 case MAPID_SUPER_NOVICE: return JOB_SUPER_NOVICE;
6347 case MAPID_KNIGHT: return JOB_KNIGHT;
6348 case MAPID_WIZARD: return JOB_WIZARD;
6349 case MAPID_HUNTER: return JOB_HUNTER;
6350 case MAPID_PRIEST: return JOB_PRIEST;
6351 case MAPID_BLACKSMITH: return JOB_BLACKSMITH;
6352 case MAPID_ASSASSIN: return JOB_ASSASSIN;
6353 case MAPID_STAR_GLADIATOR: return JOB_STAR_GLADIATOR;
6354 case MAPID_KAGEROUOBORO: return sex?JOB_KAGEROU:JOB_OBORO;
6355 case MAPID_REBELLION: return JOB_REBELLION;
6356 case MAPID_DEATH_KNIGHT: return JOB_DEATH_KNIGHT;
6357 //2-2 Jobs
6358 case MAPID_CRUSADER: return JOB_CRUSADER;
6359 case MAPID_SAGE: return JOB_SAGE;
6360 case MAPID_BARDDANCER: return sex?JOB_BARD:JOB_DANCER;
6361 case MAPID_MONK: return JOB_MONK;
6362 case MAPID_ALCHEMIST: return JOB_ALCHEMIST;
6363 case MAPID_ROGUE: return JOB_ROGUE;
6364 case MAPID_SOUL_LINKER: return JOB_SOUL_LINKER;
6365 case MAPID_DARK_COLLECTOR: return JOB_DARK_COLLECTOR;
6366 //Trans Novice And Trans 2-1 Jobs
6367 case MAPID_NOVICE_HIGH: return JOB_NOVICE_HIGH;
6368 case MAPID_SWORDMAN_HIGH: return JOB_SWORDMAN_HIGH;
6369 case MAPID_MAGE_HIGH: return JOB_MAGE_HIGH;
6370 case MAPID_ARCHER_HIGH: return JOB_ARCHER_HIGH;
6371 case MAPID_ACOLYTE_HIGH: return JOB_ACOLYTE_HIGH;
6372 case MAPID_MERCHANT_HIGH: return JOB_MERCHANT_HIGH;
6373 case MAPID_THIEF_HIGH: return JOB_THIEF_HIGH;
6374 //Trans 2-1 Jobs
6375 case MAPID_LORD_KNIGHT: return JOB_LORD_KNIGHT;
6376 case MAPID_HIGH_WIZARD: return JOB_HIGH_WIZARD;
6377 case MAPID_SNIPER: return JOB_SNIPER;
6378 case MAPID_HIGH_PRIEST: return JOB_HIGH_PRIEST;
6379 case MAPID_WHITESMITH: return JOB_WHITESMITH;
6380 case MAPID_ASSASSIN_CROSS: return JOB_ASSASSIN_CROSS;
6381 //Trans 2-2 Jobs
6382 case MAPID_PALADIN: return JOB_PALADIN;
6383 case MAPID_PROFESSOR: return JOB_PROFESSOR;
6384 case MAPID_CLOWNGYPSY: return sex?JOB_CLOWN:JOB_GYPSY;
6385 case MAPID_CHAMPION: return JOB_CHAMPION;
6386 case MAPID_CREATOR: return JOB_CREATOR;
6387 case MAPID_STALKER: return JOB_STALKER;
6388 //Baby Novice And Baby 1-1 Jobs
6389 case MAPID_BABY: return JOB_BABY;
6390 case MAPID_BABY_SWORDMAN: return JOB_BABY_SWORDMAN;
6391 case MAPID_BABY_MAGE: return JOB_BABY_MAGE;
6392 case MAPID_BABY_ARCHER: return JOB_BABY_ARCHER;
6393 case MAPID_BABY_ACOLYTE: return JOB_BABY_ACOLYTE;
6394 case MAPID_BABY_MERCHANT: return JOB_BABY_MERCHANT;
6395 case MAPID_BABY_THIEF: return JOB_BABY_THIEF;
6396 //Baby 2-1 Jobs
6397 case MAPID_SUPER_BABY: return JOB_SUPER_BABY;
6398 case MAPID_BABY_KNIGHT: return JOB_BABY_KNIGHT;
6399 case MAPID_BABY_WIZARD: return JOB_BABY_WIZARD;
6400 case MAPID_BABY_HUNTER: return JOB_BABY_HUNTER;
6401 case MAPID_BABY_PRIEST: return JOB_BABY_PRIEST;
6402 case MAPID_BABY_BLACKSMITH: return JOB_BABY_BLACKSMITH;
6403 case MAPID_BABY_ASSASSIN: return JOB_BABY_ASSASSIN;
6404 //Baby 2-2 Jobs
6405 case MAPID_BABY_CRUSADER: return JOB_BABY_CRUSADER;
6406 case MAPID_BABY_SAGE: return JOB_BABY_SAGE;
6407 case MAPID_BABY_BARDDANCER: return sex?JOB_BABY_BARD:JOB_BABY_DANCER;
6408 case MAPID_BABY_MONK: return JOB_BABY_MONK;
6409 case MAPID_BABY_ALCHEMIST: return JOB_BABY_ALCHEMIST;
6410 case MAPID_BABY_ROGUE: return JOB_BABY_ROGUE;
6411 //3-1 Jobs
6412 case MAPID_SUPER_NOVICE_E: return JOB_SUPER_NOVICE_E;
6413 case MAPID_RUNE_KNIGHT: return JOB_RUNE_KNIGHT;
6414 case MAPID_WARLOCK: return JOB_WARLOCK;
6415 case MAPID_RANGER: return JOB_RANGER;
6416 case MAPID_ARCH_BISHOP: return JOB_ARCH_BISHOP;
6417 case MAPID_MECHANIC: return JOB_MECHANIC;
6418 case MAPID_GUILLOTINE_CROSS: return JOB_GUILLOTINE_CROSS;
6419 //3-2 Jobs
6420 case MAPID_ROYAL_GUARD: return JOB_ROYAL_GUARD;
6421 case MAPID_SORCERER: return JOB_SORCERER;
6422 case MAPID_MINSTRELWANDERER: return sex?JOB_MINSTREL:JOB_WANDERER;
6423 case MAPID_SURA: return JOB_SURA;
6424 case MAPID_GENETIC: return JOB_GENETIC;
6425 case MAPID_SHADOW_CHASER: return JOB_SHADOW_CHASER;
6426 //Trans 3-1 Jobs
6427 case MAPID_RUNE_KNIGHT_T: return JOB_RUNE_KNIGHT_T;
6428 case MAPID_WARLOCK_T: return JOB_WARLOCK_T;
6429 case MAPID_RANGER_T: return JOB_RANGER_T;
6430 case MAPID_ARCH_BISHOP_T: return JOB_ARCH_BISHOP_T;
6431 case MAPID_MECHANIC_T: return JOB_MECHANIC_T;
6432 case MAPID_GUILLOTINE_CROSS_T: return JOB_GUILLOTINE_CROSS_T;
6433 //Trans 3-2 Jobs
6434 case MAPID_ROYAL_GUARD_T: return JOB_ROYAL_GUARD_T;
6435 case MAPID_SORCERER_T: return JOB_SORCERER_T;
6436 case MAPID_MINSTRELWANDERER_T: return sex?JOB_MINSTREL_T:JOB_WANDERER_T;
6437 case MAPID_SURA_T: return JOB_SURA_T;
6438 case MAPID_GENETIC_T: return JOB_GENETIC_T;
6439 case MAPID_SHADOW_CHASER_T: return JOB_SHADOW_CHASER_T;
6440 //Baby 3-1 Jobs
6441 case MAPID_SUPER_BABY_E: return JOB_SUPER_BABY_E;
6442 case MAPID_BABY_RUNE: return JOB_BABY_RUNE;
6443 case MAPID_BABY_WARLOCK: return JOB_BABY_WARLOCK;
6444 case MAPID_BABY_RANGER: return JOB_BABY_RANGER;
6445 case MAPID_BABY_BISHOP: return JOB_BABY_BISHOP;
6446 case MAPID_BABY_MECHANIC: return JOB_BABY_MECHANIC;
6447 case MAPID_BABY_CROSS: return JOB_BABY_CROSS;
6448 //Baby 3-2 Jobs
6449 case MAPID_BABY_GUARD: return JOB_BABY_GUARD;
6450 case MAPID_BABY_SORCERER: return JOB_BABY_SORCERER;
6451 case MAPID_BABY_MINSTRELWANDERER: return sex?JOB_BABY_MINSTREL:JOB_BABY_WANDERER;
6452 case MAPID_BABY_SURA: return JOB_BABY_SURA;
6453 case MAPID_BABY_GENETIC: return JOB_BABY_GENETIC;
6454 case MAPID_BABY_CHASER: return JOB_BABY_CHASER;
6455 default:
6456 return -1;
6457 }
6458}
6459
6460/*====================================================
6461 * This function return the name of the job (by [Yor])
6462 *----------------------------------------------------*/
6463const char* job_name(int class_)
6464{
6465 switch (class_) {
6466 case JOB_NOVICE:
6467 case JOB_SWORDMAN:
6468 case JOB_MAGE:
6469 case JOB_ARCHER:
6470 case JOB_ACOLYTE:
6471 case JOB_MERCHANT:
6472 case JOB_THIEF:
6473 return msg_txt(NULL,550 - JOB_NOVICE+class_);
6474
6475 case JOB_KNIGHT:
6476 case JOB_PRIEST:
6477 case JOB_WIZARD:
6478 case JOB_BLACKSMITH:
6479 case JOB_HUNTER:
6480 case JOB_ASSASSIN:
6481 return msg_txt(NULL,557 - JOB_KNIGHT+class_);
6482
6483 case JOB_KNIGHT2:
6484 return msg_txt(NULL,557);
6485
6486 case JOB_CRUSADER:
6487 case JOB_MONK:
6488 case JOB_SAGE:
6489 case JOB_ROGUE:
6490 case JOB_ALCHEMIST:
6491 case JOB_BARD:
6492 case JOB_DANCER:
6493 return msg_txt(NULL,563 - JOB_CRUSADER+class_);
6494
6495 case JOB_CRUSADER2:
6496 return msg_txt(NULL,563);
6497
6498 case JOB_WEDDING:
6499 case JOB_SUPER_NOVICE:
6500 case JOB_GUNSLINGER:
6501 case JOB_NINJA:
6502 case JOB_XMAS:
6503 return msg_txt(NULL,570 - JOB_WEDDING+class_);
6504
6505 case JOB_SUMMER:
6506 return msg_txt(NULL,621);
6507
6508 case JOB_HANBOK:
6509 return msg_txt(NULL,694);
6510
6511 case JOB_OKTOBERFEST:
6512 return msg_txt(NULL,696);
6513
6514 case JOB_NOVICE_HIGH:
6515 case JOB_SWORDMAN_HIGH:
6516 case JOB_MAGE_HIGH:
6517 case JOB_ARCHER_HIGH:
6518 case JOB_ACOLYTE_HIGH:
6519 case JOB_MERCHANT_HIGH:
6520 case JOB_THIEF_HIGH:
6521 return msg_txt(NULL,575 - JOB_NOVICE_HIGH+class_);
6522
6523 case JOB_LORD_KNIGHT:
6524 case JOB_HIGH_PRIEST:
6525 case JOB_HIGH_WIZARD:
6526 case JOB_WHITESMITH:
6527 case JOB_SNIPER:
6528 case JOB_ASSASSIN_CROSS:
6529 return msg_txt(NULL,582 - JOB_LORD_KNIGHT+class_);
6530
6531 case JOB_LORD_KNIGHT2:
6532 return msg_txt(NULL,582);
6533
6534 case JOB_PALADIN:
6535 case JOB_CHAMPION:
6536 case JOB_PROFESSOR:
6537 case JOB_STALKER:
6538 case JOB_CREATOR:
6539 case JOB_CLOWN:
6540 case JOB_GYPSY:
6541 return msg_txt(NULL,588 - JOB_PALADIN + class_);
6542
6543 case JOB_PALADIN2:
6544 return msg_txt(NULL,588);
6545
6546 case JOB_BABY:
6547 case JOB_BABY_SWORDMAN:
6548 case JOB_BABY_MAGE:
6549 case JOB_BABY_ARCHER:
6550 case JOB_BABY_ACOLYTE:
6551 case JOB_BABY_MERCHANT:
6552 case JOB_BABY_THIEF:
6553 return msg_txt(NULL,595 - JOB_BABY + class_);
6554
6555 case JOB_BABY_KNIGHT:
6556 case JOB_BABY_PRIEST:
6557 case JOB_BABY_WIZARD:
6558 case JOB_BABY_BLACKSMITH:
6559 case JOB_BABY_HUNTER:
6560 case JOB_BABY_ASSASSIN:
6561 return msg_txt(NULL,602 - JOB_BABY_KNIGHT + class_);
6562
6563 case JOB_BABY_KNIGHT2:
6564 return msg_txt(NULL,602);
6565
6566 case JOB_BABY_CRUSADER:
6567 case JOB_BABY_MONK:
6568 case JOB_BABY_SAGE:
6569 case JOB_BABY_ROGUE:
6570 case JOB_BABY_ALCHEMIST:
6571 case JOB_BABY_BARD:
6572 case JOB_BABY_DANCER:
6573 return msg_txt(NULL,608 - JOB_BABY_CRUSADER + class_);
6574
6575 case JOB_BABY_CRUSADER2:
6576 return msg_txt(NULL,608);
6577
6578 case JOB_SUPER_BABY:
6579 return msg_txt(NULL,615);
6580
6581 case JOB_TAEKWON:
6582 return msg_txt(NULL,616);
6583 case JOB_STAR_GLADIATOR:
6584 case JOB_STAR_GLADIATOR2:
6585 return msg_txt(NULL,617);
6586 case JOB_SOUL_LINKER:
6587 return msg_txt(NULL,618);
6588
6589 case JOB_GANGSI:
6590 case JOB_DEATH_KNIGHT:
6591 case JOB_DARK_COLLECTOR:
6592 return msg_txt(NULL,622 - JOB_GANGSI+class_);
6593
6594 case JOB_RUNE_KNIGHT:
6595 case JOB_WARLOCK:
6596 case JOB_RANGER:
6597 case JOB_ARCH_BISHOP:
6598 case JOB_MECHANIC:
6599 case JOB_GUILLOTINE_CROSS:
6600 return msg_txt(NULL,625 - JOB_RUNE_KNIGHT+class_);
6601
6602 case JOB_RUNE_KNIGHT_T:
6603 case JOB_WARLOCK_T:
6604 case JOB_RANGER_T:
6605 case JOB_ARCH_BISHOP_T:
6606 case JOB_MECHANIC_T:
6607 case JOB_GUILLOTINE_CROSS_T:
6608 return msg_txt(NULL,681 - JOB_RUNE_KNIGHT_T+class_);
6609
6610 case JOB_ROYAL_GUARD:
6611 case JOB_SORCERER:
6612 case JOB_MINSTREL:
6613 case JOB_WANDERER:
6614 case JOB_SURA:
6615 case JOB_GENETIC:
6616 case JOB_SHADOW_CHASER:
6617 return msg_txt(NULL,631 - JOB_ROYAL_GUARD+class_);
6618
6619 case JOB_ROYAL_GUARD_T:
6620 case JOB_SORCERER_T:
6621 case JOB_MINSTREL_T:
6622 case JOB_WANDERER_T:
6623 case JOB_SURA_T:
6624 case JOB_GENETIC_T:
6625 case JOB_SHADOW_CHASER_T:
6626 return msg_txt(NULL,687 - JOB_ROYAL_GUARD_T+class_);
6627
6628 case JOB_RUNE_KNIGHT2:
6629 case JOB_RUNE_KNIGHT_T2:
6630 return msg_txt(NULL,625);
6631
6632 case JOB_ROYAL_GUARD2:
6633 case JOB_ROYAL_GUARD_T2:
6634 return msg_txt(NULL,631);
6635
6636 case JOB_RANGER2:
6637 case JOB_RANGER_T2:
6638 return msg_txt(NULL,627);
6639
6640 case JOB_MECHANIC2:
6641 case JOB_MECHANIC_T2:
6642 return msg_txt(NULL,629);
6643
6644 case JOB_BABY_RUNE:
6645 case JOB_BABY_WARLOCK:
6646 case JOB_BABY_RANGER:
6647 case JOB_BABY_BISHOP:
6648 case JOB_BABY_MECHANIC:
6649 case JOB_BABY_CROSS:
6650 case JOB_BABY_GUARD:
6651 case JOB_BABY_SORCERER:
6652 case JOB_BABY_MINSTREL:
6653 case JOB_BABY_WANDERER:
6654 case JOB_BABY_SURA:
6655 case JOB_BABY_GENETIC:
6656 case JOB_BABY_CHASER:
6657 return msg_txt(NULL,638 - JOB_BABY_RUNE+class_);
6658
6659 case JOB_BABY_RUNE2:
6660 return msg_txt(NULL,638);
6661
6662 case JOB_BABY_GUARD2:
6663 return msg_txt(NULL,644);
6664
6665 case JOB_BABY_RANGER2:
6666 return msg_txt(NULL,640);
6667
6668 case JOB_BABY_MECHANIC2:
6669 return msg_txt(NULL,642);
6670
6671 case JOB_SUPER_NOVICE_E:
6672 case JOB_SUPER_BABY_E:
6673 return msg_txt(NULL,651 - JOB_SUPER_NOVICE_E+class_);
6674
6675 case JOB_KAGEROU:
6676 case JOB_OBORO:
6677 return msg_txt(NULL,653 - JOB_KAGEROU+class_);
6678
6679 case JOB_REBELLION:
6680 return msg_txt(NULL,695);
6681
6682 default:
6683 return msg_txt(NULL,655);
6684 }
6685}
6686
6687/*====================================================
6688 * Timered function to make id follow a target.
6689 * @id = bl.id (player only atm)
6690 * target is define in sd->followtarget (bl.id)
6691 * used by pc_follow
6692 *----------------------------------------------------*/
6693int pc_follow_timer(int tid, unsigned int tick, int id, intptr_t data)
6694{
6695 struct map_session_data *sd;
6696 struct block_list *tbl;
6697
6698 sd = map_id2sd(id);
6699 nullpo_ret(sd);
6700
6701 if (sd->followtimer != tid){
6702 ShowError("pc_follow_timer %d != %d\n",sd->followtimer,tid);
6703 sd->followtimer = INVALID_TIMER;
6704 return 0;
6705 }
6706
6707 sd->followtimer = INVALID_TIMER;
6708 tbl = map_id2bl(sd->followtarget);
6709
6710 if (tbl == NULL || pc_isdead(sd) || status_isdead(tbl))
6711 {
6712 pc_stop_following(sd);
6713 return 0;
6714 }
6715
6716 // either player or target is currently detached from map blocks (could be teleporting),
6717 // but still connected to this map, so we'll just increment the timer and check back later
6718 if (sd->bl.prev != NULL && tbl->prev != NULL &&
6719 sd->ud.skilltimer == INVALID_TIMER && sd->ud.attacktimer == INVALID_TIMER && sd->ud.walktimer == INVALID_TIMER)
6720 {
6721 if((sd->bl.m == tbl->m) && unit_can_reach_bl(&sd->bl,tbl, AREA_SIZE, 0, NULL, NULL)) {
6722 if (!check_distance_bl(&sd->bl, tbl, 5))
6723 unit_walktobl(&sd->bl, tbl, 5, 0);
6724 } else
6725 pc_setpos(sd, map_id2index(tbl->m), tbl->x, tbl->y, CLR_TELEPORT);
6726 }
6727 sd->followtimer = add_timer(
6728 tick + 1000, // increase time a bit to loosen up map's load
6729 pc_follow_timer, sd->bl.id, 0);
6730 return 0;
6731}
6732
6733int pc_stop_following (struct map_session_data *sd)
6734{
6735 nullpo_ret(sd);
6736
6737 if (sd->followtimer != INVALID_TIMER) {
6738 delete_timer(sd->followtimer,pc_follow_timer);
6739 sd->followtimer = INVALID_TIMER;
6740 }
6741 sd->followtarget = -1;
6742 sd->ud.target_to = 0;
6743
6744 unit_stop_walking(&sd->bl, 1);
6745
6746 return 0;
6747}
6748
6749int pc_follow(struct map_session_data *sd,int target_id)
6750{
6751 struct block_list *bl = map_id2bl(target_id);
6752 if (bl == NULL /*|| bl->type != BL_PC*/)
6753 return 1;
6754 if (sd->followtimer != INVALID_TIMER)
6755 pc_stop_following(sd);
6756
6757 sd->followtarget = target_id;
6758 pc_follow_timer(INVALID_TIMER, gettick(), sd->bl.id, 0);
6759
6760 return 0;
6761}
6762
6763int pc_checkbaselevelup(struct map_session_data *sd) {
6764 unsigned int next = pc_nextbaseexp(sd);
6765
6766 if (!next || sd->status.base_exp < next)
6767 return 0;
6768
6769 do {
6770 sd->status.base_exp -= next;
6771 //Kyoki pointed out that the max overcarry exp is the exp needed for the previous level -1. [Skotlex]
6772 if(!battle_config.multi_level_up && sd->status.base_exp > next-1)
6773 sd->status.base_exp = next-1;
6774
6775 next = pc_gets_status_point(sd->status.base_level);
6776 sd->status.base_level ++;
6777 sd->status.status_point += next;
6778
6779 } while ((next=pc_nextbaseexp(sd)) > 0 && sd->status.base_exp >= next);
6780
6781 if (battle_config.pet_lv_rate && sd->pd) //<Skotlex> update pet's level
6782 status_calc_pet(sd->pd,0);
6783
6784 clif_updatestatus(sd,SP_STATUSPOINT);
6785 clif_updatestatus(sd,SP_BASELEVEL);
6786 clif_updatestatus(sd,SP_BASEEXP);
6787 clif_updatestatus(sd,SP_NEXTBASEEXP);
6788 status_calc_pc(sd,0);
6789 status_percent_heal(&sd->bl,100,100);
6790
6791 if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
6792 sc_start(&sd->bl,&sd->bl,status_skill2sc(PR_KYRIE),100,1,skill_get_time(PR_KYRIE,1));
6793 sc_start(&sd->bl,&sd->bl,status_skill2sc(PR_IMPOSITIO),100,1,skill_get_time(PR_IMPOSITIO,1));
6794 sc_start(&sd->bl,&sd->bl,status_skill2sc(PR_MAGNIFICAT),100,1,skill_get_time(PR_MAGNIFICAT,1));
6795 sc_start(&sd->bl,&sd->bl,status_skill2sc(PR_GLORIA),100,1,skill_get_time(PR_GLORIA,1));
6796 sc_start(&sd->bl,&sd->bl,status_skill2sc(PR_SUFFRAGIUM),100,1,skill_get_time(PR_SUFFRAGIUM,1));
6797 if (sd->state.snovice_dead_flag)
6798 sd->state.snovice_dead_flag = 0; //Reenable steelbody resurrection on dead.
6799 } else if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) {
6800 sc_start(&sd->bl,&sd->bl,status_skill2sc(AL_INCAGI),100,10,600000);
6801 sc_start(&sd->bl,&sd->bl,status_skill2sc(AL_BLESSING),100,10,600000);
6802 }
6803 clif_misceffect(&sd->bl,0);
6804 npc_script_event(sd, NPCE_BASELVUP); //LORDALFA - LVLUPEVENT
6805
6806 if(sd->status.party_id)
6807 party_send_levelup(sd);
6808
6809 pc_baselevelchanged(sd);
6810 return 1;
6811}
6812
6813void pc_baselevelchanged(struct map_session_data *sd) {
6814#ifdef RENEWAL
6815 int i;
6816 for( i = 0; i < EQI_MAX; i++ ) {
6817 if( sd->equip_index[i] >= 0 ) {
6818 if( sd->inventory_data[ sd->equip_index[i] ]->elvmax && sd->status.base_level > (unsigned int)sd->inventory_data[ sd->equip_index[i] ]->elvmax )
6819 pc_unequipitem(sd, sd->equip_index[i], 3);
6820 }
6821 }
6822#endif
6823
6824}
6825int pc_checkjoblevelup(struct map_session_data *sd)
6826{
6827 unsigned int next = pc_nextjobexp(sd);
6828
6829 nullpo_ret(sd);
6830 if(!next || sd->status.job_exp < next)
6831 return 0;
6832
6833 do {
6834 sd->status.job_exp -= next;
6835 //Kyoki pointed out that the max overcarry exp is the exp needed for the previous level -1. [Skotlex]
6836 if(!battle_config.multi_level_up && sd->status.job_exp > next-1)
6837 sd->status.job_exp = next-1;
6838
6839 sd->status.job_level ++;
6840 sd->status.skill_point ++;
6841
6842 } while ((next=pc_nextjobexp(sd)) > 0 && sd->status.job_exp >= next);
6843
6844 clif_updatestatus(sd,SP_JOBLEVEL);
6845 clif_updatestatus(sd,SP_JOBEXP);
6846 clif_updatestatus(sd,SP_NEXTJOBEXP);
6847 clif_updatestatus(sd,SP_SKILLPOINT);
6848 status_calc_pc(sd,0);
6849 clif_misceffect(&sd->bl,1);
6850 if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd))
6851 clif_status_change(&sd->bl,SI_DEVIL, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL.
6852
6853 npc_script_event(sd, NPCE_JOBLVUP);
6854 return 1;
6855}
6856
6857/*==========================================
6858 * Alters experienced based on self bonuses that do not get even shared to the party.
6859 *------------------------------------------*/
6860static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src)
6861{
6862 int bonus = 0;
6863 struct status_data *status = status_get_status_data(src);
6864 struct region_data* rd;
6865 unsigned int ebonus = 0, jbonus = 0;
6866
6867 if( sd->expaddrace[status->race] )
6868 bonus += sd->expaddrace[status->race];
6869 if( sd->expaddrace[RC_ALL] )
6870 bonus += sd->expaddrace[RC_ALL];
6871 if( sd->expaddclass[status->class_] )
6872 bonus += sd->expaddclass[status->class_];
6873 if( sd->expaddclass[CLASS_ALL] )
6874 bonus += sd->expaddclass[CLASS_ALL];
6875
6876 if (battle_config.pk_mode &&
6877 (int)(status_get_lv(src) - sd->status.base_level) >= 20)
6878 bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris]
6879
6880 if (sd->sc.data[SC_EXPBOOST]) {
6881 bonus += sd->sc.data[SC_EXPBOOST]->val1;
6882 if( battle_config.vip_bm_increase && pc_isvip(sd) ) // Increase Battle Manual EXP rate for VIP.
6883 bonus += ( sd->sc.data[SC_EXPBOOST]->val1 / battle_config.vip_bm_increase );
6884 }
6885
6886 if( sd->status.iprank )
6887 bonus += (sd->status.iprank * 2);
6888
6889 if( pc_isPremium(sd) && battle_config.premium_bonusexp )
6890 bonus += battle_config.premium_bonusexp;
6891
6892 if( sd->state.pvpmode && battle_config.pvpmode_expbonus )
6893 {
6894 int rank;
6895 if( (rank = pc_pvpfamerank(sd->status.char_id)) && rand()%100 < ((MAX_FAME_LIST + 1 - rank) * 4) )
6896 bonus += battle_config.pvpmode_expbonus;
6897 }
6898
6899 if (sd->sc.data[SC_JEXPBOOST])
6900 jbonus += sd->sc.data[SC_JEXPBOOST]->val1;
6901
6902 if( sd->status.guild_id && (rd = region_search(map[sd->bl.m].region_id)) != NULL && sd->status.guild_id == rd->guild_id )
6903 {
6904 ebonus += rd->bonus_bexp;
6905 jbonus += rd->bonus_jexp;
6906 }
6907
6908 if( !bonus && !ebonus && !jbonus )
6909 return;
6910
6911 *base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * (bonus + ebonus)/100., 1, UINT_MAX);
6912 *job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * (bonus + jbonus)/100., 1, UINT_MAX);
6913
6914 return;
6915}
6916/*==========================================
6917 * Give x exp at sd player and calculate remaining exp for next lvl
6918 *------------------------------------------*/
6919int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp,unsigned int job_exp,bool quest)
6920{
6921 char output[256];
6922 float nextbp=0, nextjp=0;
6923 unsigned int nextb=0, nextj=0;
6924 nullpo_ret(sd);
6925
6926 if(sd->bl.prev == NULL || pc_isdead(sd))
6927 return 0;
6928
6929 if(!battle_config.pvp_exp && map[sd->bl.m].flag.pvp) // [MouseJstr]
6930 return 0; // no exp on pvp maps
6931
6932 // Increase base EXP rate for VIP.
6933 if (src && src->type&BL_MOB && (battle_config.vip_base_exp_increase && (sd && pc_isvip(sd))))
6934 base_exp = (unsigned int)cap_value(base_exp * (battle_config.vip_base_exp_increase)/100., 1, UINT_MAX);
6935
6936 if( src && src->type&BL_MOB && (sd && pc_readaccountreg(sd, "#isVIP") == 1) ) {
6937 if( battle_config.cstm_vip_bexp_inc )
6938 base_exp += (unsigned int)cap_value(base_exp * (battle_config.cstm_vip_bexp_inc)/100., 1, UINT_MAX);
6939 if( battle_config.cstm_vip_jexp_inc )
6940 job_exp += (unsigned int)cap_value(job_exp * (battle_config.cstm_vip_jexp_inc)/100., 1, UINT_MAX);
6941 }
6942
6943 /**
6944 * Map of the Week [fTakano]
6945 **/
6946 if( src && src->type == BL_MOB && map[src->m].flag.map_of_the_week ) {
6947 base_exp += (unsigned int)cap_value( base_exp * (battle_config.motw_base_rate)/100, 1, UINT_MAX );
6948 job_exp += (unsigned int)cap_value( job_exp * (battle_config.motw_job_rate)/100, 1, UINT_MAX );
6949 }
6950
6951 if( src )
6952 pc_calcexp(sd, &base_exp, &job_exp, src);
6953
6954 if(sd->status.guild_id>0)
6955 base_exp-=guild_payexp(sd,base_exp);
6956
6957 nextb = pc_nextbaseexp(sd);
6958 nextj = pc_nextjobexp(sd);
6959
6960 if(sd->state.showexp || battle_config.max_exp_gain_rate){
6961 if (nextb > 0)
6962 nextbp = (float) base_exp / (float) nextb;
6963 if (nextj > 0)
6964 nextjp = (float) job_exp / (float) nextj;
6965
6966 if(battle_config.max_exp_gain_rate) {
6967 if (nextbp > battle_config.max_exp_gain_rate/1000.) {
6968 //Note that this value should never be greater than the original
6969 //base_exp, therefore no overflow checks are needed. [Skotlex]
6970 base_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextb);
6971 if (sd->state.showexp)
6972 nextbp = (float) base_exp / (float) nextb;
6973 }
6974 if (nextjp > battle_config.max_exp_gain_rate/1000.) {
6975 job_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextj);
6976 if (sd->state.showexp)
6977 nextjp = (float) job_exp / (float) nextj;
6978 }
6979 }
6980 }
6981
6982 //Cap exp to the level up requirement of the previous level when you are at max level, otherwise cap at UINT_MAX (this is required for some S. Novice bonuses). [Skotlex]
6983 if (base_exp) {
6984 nextb = nextb?UINT_MAX:pc_thisbaseexp(sd);
6985 if(sd->status.base_exp > nextb - base_exp)
6986 sd->status.base_exp = nextb;
6987 else
6988 sd->status.base_exp += base_exp;
6989 pc_checkbaselevelup(sd);
6990 clif_updatestatus(sd,SP_BASEEXP);
6991 }
6992
6993 if (job_exp) {
6994 nextj = nextj?UINT_MAX:pc_thisjobexp(sd);
6995 if(sd->status.job_exp > nextj - job_exp)
6996 sd->status.job_exp = nextj;
6997 else
6998 sd->status.job_exp += job_exp;
6999 pc_checkjoblevelup(sd);
7000 clif_updatestatus(sd,SP_JOBEXP);
7001 }
7002
7003 if(base_exp)
7004 clif_displayexp(sd, base_exp, SP_BASEEXP, quest);
7005 if(job_exp)
7006 clif_displayexp(sd, job_exp, SP_JOBEXP, quest);
7007 sd->custom_data.session_base_exp += base_exp;
7008 sd->custom_data.session_job_exp += job_exp;
7009
7010 if(sd->state.showexp) {
7011 sprintf(output,
7012 "Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100);
7013 clif_disp_onlyself(sd,output,strlen(output));
7014 }
7015
7016 if( sd->state.showgain )
7017 {
7018 unsigned int nextb, nextj, bexp_ps, jexp_ps, nextbt, nextjt;
7019 int session_time, day = 0, hour = 0, minute = 0, second = 0;
7020
7021 if( (session_time = (int)(last_tick - sd->custom_data.session_start)) <= 0 )
7022 return 1;
7023
7024 nextb = pc_nextbaseexp(sd);
7025 nextj = pc_nextjobexp(sd);
7026
7027 if( nextb )
7028 { // Next Base lvl information
7029 if( (bexp_ps = sd->custom_data.session_base_exp / session_time) < 1 )
7030 sprintf(output, msg_txt(sd,869), bexp_ps);
7031 else if( (nextbt = (nextb - sd->status.base_exp) / bexp_ps) < 604800 )
7032 {
7033 atcommand_expinfo_sub(nextbt, &day, &hour, &minute, &second);
7034 if( day )
7035 sprintf(output, msg_txt(sd,870), bexp_ps, day, hour, minute, second);
7036 else
7037 sprintf(output, msg_txt(sd,871), bexp_ps, hour, minute, second);
7038 }
7039 else
7040 sprintf(output, msg_txt(sd,869), bexp_ps);
7041
7042 clif_disp_onlyself(sd, output, strlen(output));
7043 }
7044
7045 if( nextj )
7046 { // Next Job lvl information
7047 if( (jexp_ps = sd->custom_data.session_job_exp / session_time) < 1 )
7048 sprintf(output, msg_txt(sd,872), jexp_ps);
7049 else if( (nextjt = (nextj - sd->status.job_exp) / jexp_ps) < 604800 )
7050 {
7051 atcommand_expinfo_sub(nextjt, &day, &hour, &minute, &second);
7052 if( day )
7053 sprintf(output, msg_txt(sd,873), jexp_ps, day, hour, minute, second);
7054 else
7055 sprintf(output, msg_txt(sd,874), jexp_ps, hour, minute, second);
7056 }
7057 else
7058 sprintf(output, msg_txt(sd,872), jexp_ps);
7059
7060 clif_disp_onlyself(sd, output, strlen(output));
7061 }
7062 }
7063
7064 return 1;
7065}
7066
7067/*==========================================
7068 * Returns max level for this character.
7069 *------------------------------------------*/
7070unsigned int pc_maxbaselv(struct map_session_data *sd){
7071 return job_info[pc_class2idx(sd->status.class_)].max_level[0];
7072}
7073
7074unsigned int pc_maxjoblv(struct map_session_data *sd){
7075 return job_info[pc_class2idx(sd->status.class_)].max_level[1];
7076}
7077
7078/*==========================================
7079 * base level exp lookup.
7080 *------------------------------------------*/
7081
7082//Base exp needed for next level.
7083unsigned int pc_nextbaseexp(struct map_session_data *sd){
7084 nullpo_ret(sd);
7085 if(sd->status.base_level>=pc_maxbaselv(sd) || sd->status.base_level==0)
7086 return 0;
7087 return job_info[pc_class2idx(sd->status.class_)].exp_table[0][sd->status.base_level-1];
7088}
7089
7090//Base exp needed for this level.
7091unsigned int pc_thisbaseexp(struct map_session_data *sd){
7092 if(sd->status.base_level>pc_maxbaselv(sd) || sd->status.base_level<=1)
7093 return 0;
7094 return job_info[pc_class2idx(sd->status.class_)].exp_table[0][sd->status.base_level-2];
7095}
7096
7097
7098/*==========================================
7099 * job level exp lookup
7100 * Return:
7101 * 0 = not found
7102 * x = exp for level
7103 *------------------------------------------*/
7104
7105//Job exp needed for next level.
7106unsigned int pc_nextjobexp(struct map_session_data *sd){
7107 nullpo_ret(sd);
7108 if(sd->status.job_level>=pc_maxjoblv(sd) || sd->status.job_level==0)
7109 return 0;
7110 return job_info[pc_class2idx(sd->status.class_)].exp_table[1][sd->status.job_level-1];
7111}
7112
7113//Job exp needed for this level.
7114unsigned int pc_thisjobexp(struct map_session_data *sd){
7115 if(sd->status.job_level>pc_maxjoblv(sd) || sd->status.job_level<=1)
7116 return 0;
7117 return job_info[pc_class2idx(sd->status.class_)].exp_table[1][sd->status.job_level-2];
7118}
7119
7120/// Returns the value of the specified stat.
7121static int pc_getstat(struct map_session_data* sd, int type)
7122{
7123 nullpo_retr(-1, sd);
7124
7125 switch( type ) {
7126 case SP_STR: return sd->status.str;
7127 case SP_AGI: return sd->status.agi;
7128 case SP_VIT: return sd->status.vit;
7129 case SP_INT: return sd->status.int_;
7130 case SP_DEX: return sd->status.dex;
7131 case SP_LUK: return sd->status.luk;
7132 default:
7133 return -1;
7134 }
7135}
7136
7137/// Sets the specified stat to the specified value.
7138/// Returns the new value.
7139static int pc_setstat(struct map_session_data* sd, int type, int val)
7140{
7141 nullpo_retr(-1, sd);
7142
7143 switch( type ) {
7144 case SP_STR: sd->status.str = val; break;
7145 case SP_AGI: sd->status.agi = val; break;
7146 case SP_VIT: sd->status.vit = val; break;
7147 case SP_INT: sd->status.int_ = val; break;
7148 case SP_DEX: sd->status.dex = val; break;
7149 case SP_LUK: sd->status.luk = val; break;
7150 default:
7151 return -1;
7152 }
7153
7154 return val;
7155}
7156
7157// Calculates the number of status points PC gets when leveling up (from level to level+1)
7158int pc_gets_status_point(int level)
7159{
7160 if (battle_config.use_statpoint_table) //Use values from "db/statpoint.txt"
7161 return (stats_point_table[level+1] - stats_point_table[level]);
7162 else //Default increase
7163 return ((level+15) / 5);
7164}
7165
7166/// Returns the number of stat points needed to change the specified stat by val.
7167/// If val is negative, returns the number of stat points that would be needed to
7168/// raise the specified stat from (current value - val) to current value.
7169int pc_need_status_point(struct map_session_data* sd, int type, int val)
7170{
7171 int low, high, sp = 0, max = 0;
7172
7173 if ( val == 0 )
7174 return 0;
7175
7176 low = pc_getstat(sd,type);
7177 max = pc_maxparameter(sd,(enum e_params)(type-SP_STR));
7178
7179 if ( low >= max && val > 0 )
7180 return 0; // Official servers show '0' when max is reached
7181
7182 high = low + val;
7183
7184 if ( val < 0 )
7185 swap(low, high);
7186
7187 for ( ; low < high; low++ )
7188#ifdef RENEWAL // renewal status point cost formula
7189 sp += (low < 100) ? (2 + (low - 1) / 10) : (16 + 4 * ((low - 100) / 5));
7190#else
7191 sp += ( 1 + (low + 9) / 10 );
7192#endif
7193
7194 return sp;
7195}
7196
7197/// Raises a stat by 1.
7198/// Obeys max_parameter limits.
7199/// Subtracts stat points.
7200///
7201/// @param type The stat to change (see enum _sp)
7202int pc_statusup(struct map_session_data* sd, int type)
7203{
7204 int max, need, val;
7205
7206 nullpo_ret(sd);
7207
7208 // check conditions
7209 need = pc_need_status_point(sd,type,1);
7210 if( type < SP_STR || type > SP_LUK || need < 0 || need > sd->status.status_point )
7211 {
7212 clif_statusupack(sd,type,0,0);
7213 return 1;
7214 }
7215
7216 // check limits
7217 max = pc_maxparameter(sd,(enum e_params)(type-SP_STR));
7218
7219 if( pc_getstat(sd,type) >= max )
7220 {
7221 clif_statusupack(sd,type,0,0);
7222 return 1;
7223 }
7224
7225 // set new values
7226 val = pc_setstat(sd, type, pc_getstat(sd,type) + 1);
7227 sd->status.status_point -= need;
7228
7229 status_calc_pc(sd,0);
7230
7231 // update increase cost indicator
7232 if( need != pc_need_status_point(sd,type,1) )
7233 clif_updatestatus(sd, SP_USTR + type-SP_STR);
7234
7235 // update statpoint count
7236 clif_updatestatus(sd,SP_STATUSPOINT);
7237
7238 // update stat value
7239 clif_statusupack(sd,type,1,val); // required
7240 if( val > 255 )
7241 clif_updatestatus(sd,type); // send after the 'ack' to override the truncated value
7242
7243 return 0;
7244}
7245
7246/// Raises a stat by the specified amount.
7247/// Obeys max_parameter limits.
7248/// Does not subtract stat points.
7249///
7250/// @param type The stat to change (see enum _sp)
7251/// @param val The stat increase amount.
7252int pc_statusup2(struct map_session_data* sd, int type, int val)
7253{
7254 int max, need;
7255 nullpo_ret(sd);
7256
7257 if( type < SP_STR || type > SP_LUK )
7258 {
7259 clif_statusupack(sd,type,0,0);
7260 return 1;
7261 }
7262
7263 need = pc_need_status_point(sd,type,1);
7264 max = pc_maxparameter(sd,(enum e_params)(type-SP_STR)); // set new value
7265
7266 val = pc_setstat(sd, type, cap_value(pc_getstat(sd,type) + val, 1, max));
7267
7268 status_calc_pc(sd,0);
7269
7270 // update increase cost indicator
7271 if( need != pc_need_status_point(sd,type,1) )
7272 clif_updatestatus(sd, SP_USTR + type-SP_STR);
7273
7274 // update stat value
7275 clif_statusupack(sd,type,1,val); // required
7276 if( val > 255 )
7277 clif_updatestatus(sd,type); // send after the 'ack' to override the truncated value
7278
7279 return 0;
7280}
7281
7282/*==========================================
7283 * Update skill_lv for player sd
7284 * Skill point allocation
7285 *------------------------------------------*/
7286int pc_skillup(struct map_session_data *sd,uint16 skill_id)
7287{
7288 nullpo_ret(sd);
7289
7290 if( skill_id >= GD_SKILLBASE && skill_id < GD_SKILLBASE+MAX_GUILDSKILL )
7291 {
7292 guild_skillup(sd, skill_id);
7293 return 0;
7294 }
7295
7296 if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL && sd->hd )
7297 {
7298 merc_hom_skillup(sd->hd, skill_id);
7299 return 0;
7300 }
7301
7302 if(skill_id >= MAX_SKILL )
7303 return 0;
7304
7305 if( sd->status.skill_point > 0 &&
7306 sd->status.skill[skill_id].id &&
7307 sd->status.skill[skill_id].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
7308 sd->status.skill[skill_id].lv < skill_tree_get_max(skill_id, sd->status.class_) )
7309 {
7310 int lv,range, upgradable;
7311 sd->status.skill[skill_id].lv++;
7312 sd->status.skill_point--;
7313 if( !skill_get_inf(skill_id) )
7314 status_calc_pc(sd,0); // Only recalculate for passive skills.
7315 else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) )
7316 pc_calc_skilltree(sd); // Required to grant all TK Ranger skills.
7317 else
7318 pc_check_skilltree(sd, skill_id); // Check if a new skill can Lvlup
7319
7320 lv = sd->status.skill[skill_id].lv;
7321 range = skill_get_range2(&sd->bl, skill_id, lv);
7322 upgradable = (lv < skill_tree_get_max(sd->status.skill[skill_id].id, sd->status.class_)) ? 1 : 0;
7323 clif_skillup(sd,skill_id,lv,range,upgradable);
7324 clif_updatestatus(sd,SP_SKILLPOINT);
7325 if( skill_id == GN_REMODELING_CART ) /* cart weight info was updated by status_calc_pc */
7326 clif_updatestatus(sd,SP_CARTINFO);
7327 if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown
7328 clif_skillinfoblock(sd);
7329 }
7330
7331 return 0;
7332}
7333
7334/*==========================================
7335 * /allskill
7336 *------------------------------------------*/
7337int pc_allskillup(struct map_session_data *sd)
7338{
7339 int i;
7340
7341 nullpo_ret(sd);
7342
7343 for(i=0;i<MAX_SKILL;i++){
7344 if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) {
7345 sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
7346 sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
7347 if (sd->status.skill[i].lv == 0)
7348 sd->status.skill[i].id = 0;
7349 }
7350 }
7351
7352 if (pc_has_permission(sd, PC_PERM_ALL_SKILL))
7353 { //Get ALL skills except npc/guild ones. [Skotlex]
7354 //and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage]
7355 for(i=0;i<MAX_SKILL;i++){
7356 switch( i ) {
7357 case SG_DEVIL:
7358 case MO_TRIPLEATTACK:
7359 case RG_SNATCHER:
7360 continue;
7361 default:
7362 if( !(skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) )
7363 if ( ( sd->status.skill[i].lv = skill_get_max(i) ) )//Nonexistant skills should return a max of 0 anyway.
7364 sd->status.skill[i].id = i;
7365 }
7366 }
7367 } else {
7368 int id;
7369 for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[pc_class2idx(sd->status.class_)][i].id)>0;i++){
7370 int inf2 = skill_get_inf2(id);
7371 if (
7372 (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
7373 (inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) ||
7374 id==SG_DEVIL
7375 )
7376 continue; //Cannot be learned normally.
7377
7378 sd->status.skill[id].id = id;
7379 sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); // celest
7380 }
7381 }
7382 status_calc_pc(sd,0);
7383 //Required because if you could level up all skills previously,
7384 //the update will not be sent as only the lv variable changes.
7385 clif_skillinfoblock(sd);
7386 return 0;
7387}
7388
7389/*==========================================
7390 * /resetlvl
7391 *------------------------------------------*/
7392int pc_resetlvl(struct map_session_data* sd,int type)
7393{
7394 int i;
7395
7396 nullpo_ret(sd);
7397
7398 if (type != 3) //Also reset skills
7399 pc_resetskill(sd, 0);
7400
7401 if(type == 1){
7402 sd->status.skill_point=0;
7403 sd->status.base_level=1;
7404 sd->status.job_level=1;
7405 sd->status.base_exp=0;
7406 sd->status.job_exp=0;
7407 if(sd->sc.option !=0)
7408 sd->sc.option = 0;
7409
7410 sd->status.str=1;
7411 sd->status.agi=1;
7412 sd->status.vit=1;
7413 sd->status.int_=1;
7414 sd->status.dex=1;
7415 sd->status.luk=1;
7416 if(sd->status.class_ == JOB_NOVICE_HIGH) {
7417 sd->status.status_point=100; // not 88 [celest]
7418 // give platinum skills upon changing
7419 pc_skill(sd,142,1,0);
7420 pc_skill(sd,143,1,0);
7421 }
7422 }
7423
7424 if(type == 2){
7425 sd->status.skill_point=0;
7426 sd->status.base_level=1;
7427 sd->status.job_level=1;
7428 sd->status.base_exp=0;
7429 sd->status.job_exp=0;
7430 }
7431 if(type == 3){
7432 sd->status.base_level=1;
7433 sd->status.base_exp=0;
7434 }
7435 if(type == 4){
7436 sd->status.job_level=1;
7437 sd->status.job_exp=0;
7438 }
7439
7440 clif_updatestatus(sd,SP_STATUSPOINT);
7441 clif_updatestatus(sd,SP_STR);
7442 clif_updatestatus(sd,SP_AGI);
7443 clif_updatestatus(sd,SP_VIT);
7444 clif_updatestatus(sd,SP_INT);
7445 clif_updatestatus(sd,SP_DEX);
7446 clif_updatestatus(sd,SP_LUK);
7447 clif_updatestatus(sd,SP_BASELEVEL);
7448 clif_updatestatus(sd,SP_JOBLEVEL);
7449 clif_updatestatus(sd,SP_STATUSPOINT);
7450 clif_updatestatus(sd,SP_BASEEXP);
7451 clif_updatestatus(sd,SP_JOBEXP);
7452 clif_updatestatus(sd,SP_NEXTBASEEXP);
7453 clif_updatestatus(sd,SP_NEXTJOBEXP);
7454 clif_updatestatus(sd,SP_SKILLPOINT);
7455
7456 clif_updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris
7457 clif_updatestatus(sd,SP_UAGI);
7458 clif_updatestatus(sd,SP_UVIT);
7459 clif_updatestatus(sd,SP_UINT);
7460 clif_updatestatus(sd,SP_UDEX);
7461 clif_updatestatus(sd,SP_ULUK); // End Addition
7462
7463 for(i=0;i<EQI_MAX;i++) { // unequip items that can't be equipped by base 1 [Valaris]
7464 if(sd->equip_index[i] >= 0)
7465 if(!pc_isequip(sd,sd->equip_index[i]))
7466 pc_unequipitem(sd,sd->equip_index[i],2);
7467 }
7468
7469 if ((type == 1 || type == 2 || type == 3) && sd->status.party_id)
7470 party_send_levelup(sd);
7471
7472 status_calc_pc(sd,0);
7473 clif_skillinfoblock(sd);
7474
7475 return 0;
7476}
7477/*==========================================
7478 * /resetstate
7479 *------------------------------------------*/
7480int pc_resetstate(struct map_session_data* sd)
7481{
7482 nullpo_ret(sd);
7483
7484 if (battle_config.use_statpoint_table)
7485 { // New statpoint table used here - Dexity
7486 if (sd->status.base_level > MAX_LEVEL)
7487 { //statp[] goes out of bounds, can't reset!
7488 ShowError("pc_resetstate: Can't reset stats of %d:%d, the base level (%d) is greater than the max level supported (%d)\n",
7489 sd->status.account_id, sd->status.char_id, sd->status.base_level, MAX_LEVEL);
7490 return 0;
7491 }
7492
7493 sd->status.status_point = stats_point_table[sd->status.base_level] + (sd->class_&JOBL_UPPER ? 52 : 0); // extra 52+48=100 stat points
7494 }
7495 else
7496 {
7497 int add=0;
7498 add += pc_need_status_point(sd, SP_STR, 1-pc_getstat(sd, SP_STR));
7499 add += pc_need_status_point(sd, SP_AGI, 1-pc_getstat(sd, SP_AGI));
7500 add += pc_need_status_point(sd, SP_VIT, 1-pc_getstat(sd, SP_VIT));
7501 add += pc_need_status_point(sd, SP_INT, 1-pc_getstat(sd, SP_INT));
7502 add += pc_need_status_point(sd, SP_DEX, 1-pc_getstat(sd, SP_DEX));
7503 add += pc_need_status_point(sd, SP_LUK, 1-pc_getstat(sd, SP_LUK));
7504
7505 sd->status.status_point+=add;
7506 }
7507
7508 pc_setstat(sd, SP_STR, 1);
7509 pc_setstat(sd, SP_AGI, 1);
7510 pc_setstat(sd, SP_VIT, 1);
7511 pc_setstat(sd, SP_INT, 1);
7512 pc_setstat(sd, SP_DEX, 1);
7513 pc_setstat(sd, SP_LUK, 1);
7514
7515 clif_updatestatus(sd,SP_STR);
7516 clif_updatestatus(sd,SP_AGI);
7517 clif_updatestatus(sd,SP_VIT);
7518 clif_updatestatus(sd,SP_INT);
7519 clif_updatestatus(sd,SP_DEX);
7520 clif_updatestatus(sd,SP_LUK);
7521
7522 clif_updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris
7523 clif_updatestatus(sd,SP_UAGI);
7524 clif_updatestatus(sd,SP_UVIT);
7525 clif_updatestatus(sd,SP_UINT);
7526 clif_updatestatus(sd,SP_UDEX);
7527 clif_updatestatus(sd,SP_ULUK); // End Addition
7528
7529 clif_updatestatus(sd,SP_STATUSPOINT);
7530
7531 if( sd->mission_mobid ) { //bugreport:2200
7532 sd->mission_mobid = 0;
7533 sd->mission_count = 0;
7534 pc_setglobalreg(sd,"TK_MISSION_ID", 0);
7535 }
7536
7537 status_calc_pc(sd,0);
7538
7539 return 1;
7540}
7541
7542/*==========================================
7543 * /resetskill
7544 * if flag&1, perform block resync and status_calc call.
7545 * if flag&2, just count total amount of skill points used by player, do not really reset.
7546 * if flag&4, just reset the skills if the player class is a bard/dancer type (for changesex.)
7547 *------------------------------------------*/
7548int pc_resetskill(struct map_session_data* sd, int flag)
7549{
7550 int i, skill_point=0;
7551 nullpo_ret(sd);
7552
7553 if( flag&4 && (sd->class_&MAPID_UPPERMASK) != MAPID_BARDDANCER )
7554 return 0;
7555
7556 if( !(flag&2) ) { //Remove stuff lost when resetting skills.
7557
7558 /**
7559 * It has been confirmed on official server that when you reset skills with a ranked tweakwon your skills are not reset (because you have all of them anyway)
7560 **/
7561 if( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) )
7562 return 0;
7563
7564 if( pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd) )
7565 clif_status_load(&sd->bl, SI_DEVIL, 0); //Remove perma blindness due to skill-reset. [Skotlex]
7566 i = sd->sc.option;
7567 if( i&OPTION_RIDING && pc_checkskill(sd, KN_RIDING) )
7568 i &= ~OPTION_RIDING;
7569 if( i&OPTION_FALCON && pc_checkskill(sd, HT_FALCON) )
7570 i &= ~OPTION_FALCON;
7571 if( i&OPTION_DRAGON && pc_checkskill(sd, RK_DRAGONTRAINING) )
7572 i &= ~OPTION_DRAGON;
7573 if( i&OPTION_WUG && pc_checkskill(sd, RA_WUGMASTERY) )
7574 i &= ~OPTION_WUG;
7575 if( i&OPTION_WUGRIDER && pc_checkskill(sd, RA_WUGRIDER) )
7576 i &= ~OPTION_WUGRIDER;
7577 if( i&OPTION_MADOGEAR && ( sd->class_&MAPID_THIRDMASK ) == MAPID_MECHANIC )
7578 i &= ~OPTION_MADOGEAR;
7579#ifndef NEW_CARTS
7580 if( i&OPTION_CART && pc_checkskill(sd, MC_PUSHCART) )
7581 i &= ~OPTION_CART;
7582#else
7583 if( sd->sc.data[SC_PUSH_CART] )
7584 pc_setcart(sd, 0);
7585#endif
7586 if( i != sd->sc.option )
7587 pc_setoption(sd, i);
7588
7589 if( merc_is_hom_active(sd->hd) && pc_checkskill(sd, AM_CALLHOMUN) )
7590 merc_hom_vaporize(sd, HOM_ST_ACTIVE);
7591 }
7592
7593 for( i = 1; i < MAX_SKILL; i++ )
7594 {
7595 int lv = sd->status.skill[i].lv;
7596 int inf2;
7597 if (lv < 1) continue;
7598
7599 inf2 = skill_get_inf2(i);
7600
7601 if( inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL) ) //Avoid reseting wedding/linker skills.
7602 continue;
7603
7604 // Don't reset trick dead if not a novice/baby
7605 if( i == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
7606 {
7607 sd->status.skill[i].lv = 0;
7608 sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
7609 continue;
7610 }
7611
7612 // do not reset basic skill
7613 if( i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
7614 continue;
7615
7616 if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED )
7617 continue;
7618
7619 if( flag&4 && !skill_ischangesex(i) )
7620 continue;
7621
7622 if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn )
7623 { //Only handle quest skills in a special way when you can't learn them manually
7624 if( battle_config.quest_skill_reset && !(flag&2) )
7625 { //Wipe them
7626 sd->status.skill[i].lv = 0;
7627 sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
7628 }
7629 continue;
7630 }
7631 if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT )
7632 skill_point += lv;
7633 else
7634 if( sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0 )
7635 skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
7636
7637 if( !(flag&2) )
7638 {// reset
7639 sd->status.skill[i].lv = 0;
7640 sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
7641 }
7642 }
7643
7644 if( flag&2 || !skill_point ) return skill_point;
7645
7646 sd->status.skill_point += skill_point;
7647
7648 if( flag&1 )
7649 {
7650 clif_updatestatus(sd,SP_SKILLPOINT);
7651 clif_skillinfoblock(sd);
7652 status_calc_pc(sd,0);
7653 }
7654
7655 return skill_point;
7656}
7657
7658/*==========================================
7659 * /resetfeel [Komurka]
7660 *------------------------------------------*/
7661int pc_resetfeel(struct map_session_data* sd)
7662{
7663 int i;
7664 nullpo_ret(sd);
7665
7666 for (i=0; i<MAX_PC_FEELHATE; i++)
7667 {
7668 sd->feel_map[i].m = -1;
7669 sd->feel_map[i].index = 0;
7670 pc_setglobalreg(sd,sg_info[i].feel_var,0);
7671 }
7672
7673 return 0;
7674}
7675
7676int pc_resethate(struct map_session_data* sd)
7677{
7678 int i;
7679 nullpo_ret(sd);
7680
7681 for (i=0; i<3; i++)
7682 {
7683 sd->hate_mob[i] = -1;
7684 pc_setglobalreg(sd,sg_info[i].hate_var,0);
7685 }
7686 return 0;
7687}
7688
7689int pc_skillatk_bonus(struct map_session_data *sd, uint16 skill_id)
7690{
7691 int i, bonus = 0;
7692 nullpo_ret(sd);
7693
7694 ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == skill_id);
7695 if( i < ARRAYLENGTH(sd->skillatk) ) bonus = sd->skillatk[i].val;
7696
7697 if(sd->sc.data[SC_PYROTECHNIC_OPTION] || sd->sc.data[SC_AQUAPLAY_OPTION])
7698 bonus += 10;
7699
7700 return bonus;
7701}
7702
7703int pc_skillheal_bonus(struct map_session_data *sd, uint16 skill_id) {
7704 int i, bonus = sd->bonus.add_heal_rate;
7705
7706 if( bonus ) {
7707 switch( skill_id ) {
7708 case AL_HEAL: if( !(battle_config.skill_add_heal_rate&1) ) bonus = 0; break;
7709 case PR_SANCTUARY: if( !(battle_config.skill_add_heal_rate&2) ) bonus = 0; break;
7710 case AM_POTIONPITCHER: if( !(battle_config.skill_add_heal_rate&4) ) bonus = 0; break;
7711 case CR_SLIMPITCHER: if( !(battle_config.skill_add_heal_rate&8) ) bonus = 0; break;
7712 case BA_APPLEIDUN: if( !(battle_config.skill_add_heal_rate&16)) bonus = 0; break;
7713 }
7714 }
7715
7716 ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == skill_id);
7717
7718 if( i < ARRAYLENGTH(sd->skillheal) )
7719 bonus += sd->skillheal[i].val;
7720
7721 return bonus;
7722}
7723
7724int pc_skillheal2_bonus(struct map_session_data *sd, uint16 skill_id) {
7725 int i, bonus = sd->bonus.add_heal2_rate;
7726
7727 ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == skill_id);
7728
7729 if( i < ARRAYLENGTH(sd->skillheal2) )
7730 bonus += sd->skillheal2[i].val;
7731
7732 return bonus;
7733}
7734
7735void pc_respawn(struct map_session_data* sd, clr_type clrtype)
7736{
7737 if( !pc_isdead(sd) )
7738 return; // not applicable
7739 if( sd->bg_id && bg_member_respawn(sd) )
7740 return; // member revived by battleground
7741
7742 pc_setstand(sd);
7743 pc_setrestartvalue(sd,3);
7744 if( pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype) )
7745 clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
7746}
7747
7748static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data)
7749{
7750 struct map_session_data *sd = map_id2sd(id);
7751 if( sd != NULL )
7752 {
7753 sd->pvp_point=0;
7754 pc_respawn(sd,CLR_OUTSIGHT);
7755 }
7756
7757 return 0;
7758}
7759
7760/*==========================================
7761 * Invoked when a player has received damage
7762 *------------------------------------------*/
7763void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int hp, unsigned int sp)
7764{
7765 struct block_list *s_bl;
7766
7767 if (sp) clif_updatestatus(sd,SP_SP);
7768 if (hp) clif_updatestatus(sd,SP_HP);
7769 else return;
7770
7771 if( !src || src == &sd->bl )
7772 return;
7773
7774 if( pc_issit(sd) ) {
7775 pc_setstand(sd);
7776 skill_sit(sd,0);
7777 }
7778
7779 if( sd->progressbar.npc_id )
7780 clif_progressbar_abort(sd);
7781
7782 if( sd->state.pvpmode && src->type == BL_PC && ((TBL_PC*)src)->state.pvpmode )
7783 {
7784 // [Zephyrus] Actualizacion de Timer de dañ¯ VP, en PK Mode
7785 struct map_session_data *pk = (TBL_PC*)src;
7786 sd->idlepvp = last_tick;
7787 pk->idlepvp = last_tick;
7788 }
7789
7790 if( sd->status.pet_id > 0 && sd->pd && battle_config.pet_damage_support )
7791 pet_target_check(sd,src,1);
7792
7793 if( !(src && (s_bl = battle_get_master(src)) != NULL) )
7794 s_bl = src;
7795
7796 if( sd->status.ele_id > 0 )
7797 elemental_set_target(sd,src);
7798 if( s_bl && s_bl->type == BL_PC && guild_wardamage(sd) )
7799 sd->canescape_tick = gettick();
7800
7801 sd->canlog_tick = gettick();
7802}
7803
7804int pc_close_npc_timer(int tid, unsigned int tick, int id, intptr_t data)
7805{
7806 TBL_PC *sd = map_id2sd(id);
7807 if(sd) pc_close_npc(sd,data);
7808 return 0;
7809}
7810/*
7811 * Method to properly close npc for player and clear anything related
7812 * @flag == 1 : produce close button
7813 * @flag == 2 : directly close it
7814 */
7815void pc_close_npc(struct map_session_data *sd,int flag)
7816{
7817 nullpo_retv(sd);
7818
7819 if (sd->npc_id || sd->npc_shopid) {
7820 if (sd->state.using_fake_npc) {
7821 clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
7822 sd->state.using_fake_npc = 0;
7823 }
7824
7825 if (sd->st) {
7826 if(sd->st->state == RUN){ //wait ending code execution
7827 add_timer(gettick()+500,pc_close_npc_timer,sd->bl.id,flag);
7828 return;
7829 }
7830 sd->st->state = ((flag==1 && sd->st->mes_active)?CLOSE:END);
7831 sd->st->mes_active = 0;
7832 }
7833 sd->state.menu_or_input = 0;
7834 sd->npc_menu = 0;
7835 sd->npc_shopid = 0;
7836#ifdef SECURE_NPCTIMEOUT
7837 sd->npc_idle_timer = INVALID_TIMER;
7838#endif
7839 clif_scriptclose(sd,sd->npc_id);
7840 clif_scriptclear(sd,sd->npc_id); // [Ind/Hercules]
7841 if(sd->st && sd->st->state == END ) {// free attached scripts that are waiting
7842 script_free_state(sd->st);
7843 sd->st = NULL;
7844 sd->npc_id = 0;
7845 }
7846 }
7847}
7848
7849void pc_record_mobkills(struct map_session_data *sd, struct mob_data *md)
7850{
7851 struct guild *g;
7852 struct guild_castle *gc;
7853 struct battleground_data *bg;
7854 int type = 0;
7855
7856 if( !sd ) return;
7857 if( map[sd->bl.m].flag.battleground && sd->bg_id )
7858 {
7859 int i;
7860 if( (bg = bg_team_search(sd->bg_id)) == NULL )
7861 return;
7862 ARR_FIND(0,MAX_BG_MEMBERS,i,bg->members[i].sd == sd);
7863 if( i >= MAX_BG_MEMBERS )
7864 return;
7865 type = bg->members[i].ranked ? 2 : 3;
7866 }
7867
7868 if( map_allowed_woe(sd->bl.m) )
7869 {
7870 switch( md->mob_id )
7871 {
7872 case MOBID_EMPERIUM:
7873 add2limit(sd->status.wstats.emperium_kill, 1, USHRT_MAX);
7874 if( (g = guild_search(sd->status.guild_id)) && (gc = guild_mapindex2gc(map[sd->bl.m].index)) )
7875 {
7876 add2limit(g->castle[gc->castle_id].emperium, 1, USHRT_MAX);
7877 g->castle[gc->castle_id].changed = true;
7878 }
7879 break;
7880 case 1905:
7881 add2limit(sd->status.wstats.barricade_kill, 1, USHRT_MAX);
7882 break;
7883 case MOBID_GUARIDAN_STONE1:
7884 case MOBID_GUARIDAN_STONE2:
7885 add2limit(sd->status.wstats.gstone_kill, 1, USHRT_MAX);
7886 break;
7887 case 1285:
7888 case 1286:
7889 case 1287:
7890 case 1899:
7891 case 1900:
7892 add2limit(sd->status.wstats.guardian_kill, 1, USHRT_MAX);
7893 break;
7894 }
7895 }
7896 else if( map[sd->bl.m].flag.battleground )
7897 {
7898 switch( md->mob_id )
7899 {
7900 case 2000:
7901 case 2001:
7902 case 2002:
7903 case 2003:
7904 case 2004:
7905 add2limit(sd->status.bgstats.boss_killed, 1, USHRT_MAX);
7906 achievement_validate_bg(sd,ATB_BOSS_KILLS,1);
7907 pc_addfame(sd,25,type);
7908 break;
7909 case 2005:
7910 case 2006:
7911 add2limit(sd->status.bgstats.gstone_kill, 1, USHRT_MAX);
7912 achievement_validate_bg(sd,ATB_CON_GSTONE,1);
7913 pc_addfame(sd,10,type);
7914 break;
7915 case 2007:
7916 if( map[sd->bl.m].flag.battleground == 2 )
7917 {
7918 add2limit(sd->status.bgstats.ru_captures, 1, USHRT_MAX);
7919 achievement_validate_bg(sd,ATB_RU_CAPTURE,1);
7920 }
7921 else
7922 {
7923 add2limit(sd->status.bgstats.emperium_kill, 1, USHRT_MAX);
7924 achievement_validate_bg(sd,ATB_CON_EMPERIUM,1);
7925 }
7926 pc_addfame(sd,30,type);
7927 break;
7928 case 1911:
7929 if( !strcmpi(map[sd->bl.m].name,"bat_a03") )
7930 {
7931 add2limit(sd->status.bgstats.boss_flags, 1, USHRT_MAX);
7932 achievement_validate_bg(sd,ATB_BOSS_FLAGS,1);
7933 pc_addfame(sd,5,type);
7934 }
7935 break;
7936 case 1906:
7937 if( strcmpi(map[sd->bl.m].name,"bat_a01") )
7938 {
7939 add2limit(sd->status.bgstats.barricade_kill, 1, USHRT_MAX);
7940 achievement_validate_bg(sd,ATB_CON_BARRICADE,1);
7941 pc_addfame(sd,1,type);
7942 }
7943 break;
7944 }
7945 }
7946
7947 if( map[sd->bl.m].flag.gvg_castle && ((md->mob_id >= 1324 && md->mob_id <= 1363) || (md->mob_id >= 1938 && md->mob_id <= 1946)) && (g = guild_search(sd->status.guild_id)) && (gc = guild_mapindex2gc(map[sd->bl.m].index)) )
7948 {
7949 add2limit(g->castle[gc->castle_id].treasure, 1, USHRT_MAX); // Treasure opened on Castle
7950 g->castle[gc->castle_id].changed = true;
7951 if( !(agit_flag || agit2_flag) )
7952 {
7953 intif_guild_save_score(g->guild_id, gc->castle_id, &g->castle[gc->castle_id]);
7954 g->castle[gc->castle_id].changed = false;
7955 }
7956 }
7957}
7958
7959void pc_record_maxdamage(struct block_list *src, struct block_list *dst, int damage)
7960{
7961 struct block_list *s_bl;
7962 struct map_session_data *sd;
7963
7964 if( !src || !dst || src == dst || dst->type != BL_PC || damage <= 0 )
7965 return;
7966
7967 if( (s_bl = battle_get_master(src)) == NULL )
7968 s_bl = src;
7969
7970 if( s_bl->type != BL_PC )
7971 return;
7972
7973 if( (sd = BL_CAST(BL_PC, s_bl)) != NULL )
7974 {
7975 if( map[src->m].flag.battleground && sd->bg_id && sd->status.bgstats.top_damage < damage )
7976 sd->status.bgstats.top_damage = damage;
7977 else if( map_allowed_woe(src->m) && sd->status.wstats.top_damage < damage )
7978 sd->status.wstats.top_damage = damage;
7979 }
7980}
7981
7982void pc_record_damage(struct block_list *src, struct block_list *dst, int damage)
7983{
7984 struct block_list *s_bl;
7985 struct map_session_data *sd;
7986
7987 if( !src || !dst || src == dst || damage <= 0 )
7988 return;
7989
7990 if( (s_bl = battle_get_master(src)) == NULL )
7991 s_bl = src;
7992
7993 if( s_bl->type != BL_PC )
7994 return;
7995
7996 sd = BL_CAST(BL_PC, s_bl);
7997
7998 switch( dst->type )
7999 {
8000 case BL_PC:
8001 achievement_validate_damage(sd,damage);
8002 if( map[src->m].flag.battleground && sd->bg_id )
8003 {
8004 add2limit(sd->status.bgstats.damage_done, damage, UINT_MAX);
8005 add2limit(((TBL_PC*)dst)->status.bgstats.damage_received, damage, UINT_MAX);
8006 }
8007 else if( map_allowed_woe(src->m) )
8008 {
8009 add2limit(sd->status.wstats.damage_done, damage, UINT_MAX);
8010 add2limit(((TBL_PC*)dst)->status.wstats.damage_received, damage, UINT_MAX);
8011 }
8012 break;
8013 case BL_MOB:
8014 {
8015 struct mob_data *md = BL_CAST(BL_MOB, dst);
8016 if( map[src->m].flag.battleground && sd->bg_id && md->mob_id >= 2100 && md->mob_id <= 2104 )
8017 add2limit(sd->status.bgstats.boss_damage, damage, UINT_MAX);
8018 else if( map_allowed_woe(src->m) && md->guardian_data )
8019 {
8020 switch( md->mob_id )
8021 {
8022 case MOBID_EMPERIUM:
8023 add2limit(sd->status.wstats.emperium_damage, damage, UINT_MAX);
8024 break;
8025 case 1905:
8026 add2limit(sd->status.wstats.barricade_damage, damage, UINT_MAX);
8027 break;
8028 case MOBID_GUARIDAN_STONE1:
8029 case MOBID_GUARIDAN_STONE2:
8030 add2limit(sd->status.wstats.gstone_damage, damage, UINT_MAX);
8031 break;
8032 default:
8033 add2limit(sd->status.wstats.guardian_damage, damage, UINT_MAX);
8034 break;
8035 }
8036 }
8037 break;
8038 }
8039 }
8040}
8041
8042void pc_calc_ranking(struct map_session_data *tsd, struct map_session_data *ssd, uint16 skill_id)
8043{
8044 int m, i, Elo;
8045 char output[256];
8046
8047 if( !tsd || !ssd || tsd == ssd )
8048 return;
8049
8050 m = ssd->bl.m;
8051 achievement_validate_killer(ssd);
8052
8053 if( map_allowed_woe(m) )
8054 {
8055 /*==========================================
8056 * Guild Ranking - War of Emperium
8057 *------------------------------------------*/
8058 struct guild *tg, *sg;
8059 struct guild_castle *gc = guild_mapindex2gc(map[m].index);
8060
8061 if( gc == NULL || gc->guild_id <= 0 )
8062 return;
8063
8064 if( (tg = guild_search(tsd->status.guild_id)) == NULL || (sg = guild_search(ssd->status.guild_id)) == NULL )
8065 return;
8066
8067 i = gc->castle_id;
8068 Elo = (int)(10. / (1 + pow(10., (int)(sg->castle[i].offensive_score - tg->castle[i].offensive_score) / 2000.)));
8069 add2limit(sg->castle[i].offensive_score, Elo, 4000);
8070 sub2limit(tg->castle[i].offensive_score, Elo, 0);
8071
8072 // Single Player Ranking WoE
8073 Elo = (int)(50. / (1 + pow(10., (int)(ssd->status.wstats.score - tsd->status.wstats.score) / 2000.)));
8074 add2limit(ssd->status.wstats.score, Elo, 4000);
8075 sub2limit(tsd->status.wstats.score, Elo, 0);
8076 add2limit(ssd->status.wstats.kill_count, 1, USHRT_MAX);
8077 add2limit(tsd->status.wstats.death_count, 1, USHRT_MAX);
8078
8079 log_woe_kill(ssd,tsd,skill_id);
8080
8081 if( tsd->status.guild_id == gc->guild_id )
8082 { // Offensive Ranking - Killing Castle Owners
8083 add2limit(sg->castle[i].off.kill_count, 1, UINT_MAX);
8084 add2limit(tg->castle[i].def.death_count, 1, UINT_MAX);
8085 }
8086 else if( guild_isallied(gc->guild_id, tsd->status.guild_id) )
8087 { // Offensive Ranking - Killing Castle Allied
8088 add2limit(sg->castle[i].off.kill_count, 1, UINT_MAX);
8089 add2limit(tg->castle[i].ali.death_count, 1, UINT_MAX);
8090 }
8091 else if( ssd->status.guild_id == gc->guild_id )
8092 { // Defensive Ranking - Killing Castle Invaders
8093 add2limit(sg->castle[i].def.kill_count, 1, UINT_MAX);
8094 add2limit(tg->castle[i].off.death_count, 1, UINT_MAX);
8095 }
8096 else if( guild_isallied(gc->guild_id, ssd->status.guild_id) )
8097 { // Defensive Ranking - Allied killing Invaders
8098 add2limit(sg->castle[i].ali.kill_count, 1, UINT_MAX);
8099 add2limit(tg->castle[i].off.death_count, 1, UINT_MAX);
8100 }
8101 else
8102 { // Killing other guilds invaders
8103 add2limit(sg->castle[i].ext.kill_count, 1, UINT_MAX);
8104 add2limit(tg->castle[i].ext.death_count, 1, UINT_MAX);
8105 }
8106
8107 tg->castle[i].changed = true;
8108 sg->castle[i].changed = true;
8109 }
8110 else if( map_pvpevent(m) )
8111 {
8112 /*==========================================
8113 * PVP Event Ranking
8114 *------------------------------------------*/
8115 struct party_data *p;
8116 struct map_session_data *s_pl[MAX_PARTY], *t_pl[MAX_PARTY], *p_sd;
8117 struct fame_list b_fame_list[MAX_FAME_LIST];
8118 int j;
8119
8120 unsigned int s_rate = 0, t_rate = 0;
8121 int sc = 1, tc = 1, s_Elo, t_Elo, diff_lv, cash = 0;
8122
8123 // Validate Kill Area
8124 if( map[m].pvpe_area )
8125 {
8126 if( ssd->bl.x < map[m].pvpe_x1 || ssd->bl.x > map[m].pvpe_x2 || ssd->bl.y < map[m].pvpe_y1 || ssd->bl.y > map[m].pvpe_y2 )
8127 return; // Killer not on Area
8128 if( tsd->bl.x < map[m].pvpe_x1 || tsd->bl.x > map[m].pvpe_x2 || tsd->bl.y < map[m].pvpe_y1 || tsd->bl.y > map[m].pvpe_y2 )
8129 return; // Killed not on Area
8130 }
8131
8132 diff_lv = ssd->status.base_level - tsd->status.base_level;
8133 if( diff_lv < 0 ) diff_lv = -1 * diff_lv;
8134 if( diff_lv > 15 ) return;
8135
8136 // Source
8137 if( ssd->status.party_id && (p = party_search(ssd->status.party_id)) != NULL )
8138 {
8139 for( i = sc = 0; i < MAX_PARTY; i++ )
8140 {
8141 if( (s_pl[sc] = p->data[i].sd) == NULL || s_pl[sc]->bl.m != m )
8142 continue;
8143 if( pc_isdead(s_pl[sc]) && s_pl[sc] != ssd )
8144 continue;
8145 if( map[m].pvpe_area && ( s_pl[sc]->bl.x < map[m].pvpe_x1 || s_pl[sc]->bl.x > map[m].pvpe_x2 || s_pl[sc]->bl.y < map[m].pvpe_y1 || s_pl[sc]->bl.y > map[m].pvpe_y2 ) )
8146 continue; // Party member not on Area
8147
8148 s_rate += s_pl[sc]->status.pvp.score;
8149 sc++;
8150 }
8151 if( sc < 1 ) return;
8152 }
8153 else
8154 {
8155 s_pl[0] = ssd;
8156 s_rate = s_pl[0]->status.pvp.score;
8157 }
8158
8159 s_rate /= sc; // Average Source Rate
8160
8161 // Target
8162 if( tsd->status.party_id && (p = party_search(tsd->status.party_id)) != NULL )
8163 {
8164 for( i = tc = 0; i < MAX_PARTY; i++ )
8165 {
8166 if( (t_pl[tc] = p->data[i].sd) == NULL || t_pl[tc]->bl.m != m )
8167 continue;
8168 if( pc_isdead(t_pl[tc]) && t_pl[tc] != tsd )
8169 continue;
8170 if( map[m].pvpe_area && ( t_pl[tc]->bl.x < map[m].pvpe_x1 || t_pl[tc]->bl.x > map[m].pvpe_x2 || t_pl[tc]->bl.y < map[m].pvpe_y1 || t_pl[tc]->bl.y > map[m].pvpe_y2 ) )
8171 continue; // Party member not on Area
8172 t_rate += t_pl[tc]->status.pvp.score;
8173 tc++;
8174 }
8175 if( tc < 1 ) return;
8176 }
8177 else
8178 {
8179 t_pl[0] = tsd;
8180 t_rate = t_pl[0]->status.pvp.score;
8181 }
8182
8183 memcpy(&b_fame_list, pvpevent_fame_list, sizeof(struct fame_list));
8184 t_rate /= sc; // Average Target Rate
8185
8186 Elo = (int)(50. / (1 + pow(10., (int)(s_rate - t_rate) / 2000.)));
8187 s_Elo = Elo / sc;
8188
8189 if( battle_config.pvpevent_cashperkill )
8190 cash = 1 + ( (tsd->status.base_level * battle_config.pvpevent_cashperkill) / (10 * sc) );
8191
8192 for( i = 0; i < sc; i++ )
8193 {
8194 add2limit(s_pl[i]->status.pvp.score, s_Elo, 4000);
8195 add2limit(s_pl[i]->pvpevent_fame, s_Elo, UINT_MAX);
8196
8197 sprintf(output, "[%s] Killed by [%s] - Received %d / %d = %d Points. Stats PvP-Elo %d | Score %d.", tsd->status.name, ssd->status.name, Elo, sc, s_Elo, s_pl[i]->status.pvp.score, s_pl[i]->pvpevent_fame);
8198 clif_disp_onlyself(s_pl[i], output, strlen(output));
8199
8200 pc_pvpevent_addfame(s_pl[i], false);
8201 if( cash )
8202 { // Receiving Cash per Kill
8203 pc_getcash(s_pl[i], 0, cash, LOG_TYPE_NPC); // Kafra Points
8204 clif_emotion(&s_pl[i]->bl, 8); // e_cash
8205 }
8206 }
8207
8208 for( i = 0; i < MAX_FAME_LIST; i++ )
8209 { // Announces Fame List
8210 if( b_fame_list[i].id != 0 && (p_sd = map_charid2sd(b_fame_list[i].id)) != NULL )
8211 {
8212 ARR_FIND(0, MAX_FAME_LIST, j, pvpevent_fame_list[j].id == b_fame_list[i].id); // Search Previous Position
8213 if( j != i )
8214 {
8215 if( j == MAX_FAME_LIST )
8216 sprintf(output, "-- You have been removed from Top %d PVP Event Fame List --", MAX_FAME_LIST);
8217 else if( j < i )
8218 sprintf(output, "-- Going UP to Position %d on Top %d PVP Event Fame List --", j + 1, MAX_FAME_LIST);
8219 else
8220 sprintf(output, "-- Going Down to Position %d on Top %d PVP Event Fame List --", j + 1, MAX_FAME_LIST);
8221
8222 clif_disp_onlyself(p_sd, output, strlen(output));
8223 }
8224 }
8225
8226 if( pvpevent_fame_list[i].id != 0 && (p_sd = map_charid2sd(pvpevent_fame_list[i].id)) != NULL )
8227 {
8228 ARR_FIND(0, MAX_FAME_LIST, j, pvpevent_fame_list[i].id == b_fame_list[j].id);
8229 if( j == MAX_FAME_LIST )
8230 {
8231 sprintf(output, "-- Entering Top %d PVP Event Fame List at position %d --", MAX_FAME_LIST, i + 1);
8232 clif_disp_onlyself(p_sd, output, strlen(output));
8233 }
8234 }
8235 }
8236
8237 if( memcmp(&pvpevent_fame_list, &b_fame_list, sizeof(pvpevent_fame_list)) )
8238 {
8239 i = 0;
8240 while( i < MAX_FAME_LIST && pvpevent_fame_list[i].id )
8241 {
8242 mapreg_setregstr(add_str("$pvpevent_name$")+(i<<24), pvpevent_fame_list[i].name);
8243 mapreg_setreg(add_str("$pvpevent_id")+(i<<24), pvpevent_fame_list[i].id);
8244 mapreg_setreg(add_str("$pvpevent_fame")+(i<<24), pvpevent_fame_list[i].fame);
8245 i++;
8246 }
8247
8248 mapreg_setreg(add_str("$pvpevent_count"),i);
8249 }
8250
8251 t_Elo = Elo / tc;
8252 for( i = 0; i < tc; i++ )
8253 sub2limit(t_pl[i]->status.pvp.score, t_Elo, 0);
8254
8255 add2limit(ssd->status.pvp.kill_count, 1, USHRT_MAX);
8256 add2limit(tsd->status.pvp.death_count, 1, USHRT_MAX);
8257 }
8258 else if( ssd->bg_id && map[m].flag.battleground && tsd->bg_id )
8259 {
8260 /*==========================================
8261 * BattleGround Ranking
8262 *------------------------------------------*/
8263 struct battleground_data *s_bg, *t_bg;
8264 struct map_session_data *s_pl[MAX_BG_MEMBERS], *t_pl[MAX_BG_MEMBERS];
8265 unsigned int s_rate = 0, t_rate = 0;
8266 int sc, tc, s_Elo, t_Elo;
8267
8268 if( (s_bg = bg_team_search(ssd->bg_id)) == NULL || (t_bg = bg_team_search(tsd->bg_id)) == NULL )
8269 return;
8270
8271 // Source
8272 for( i = sc = 0; i < MAX_BG_MEMBERS; i++ )
8273 {
8274 if( (s_pl[sc] = s_bg->members[i].sd) == NULL || s_pl[sc]->bl.m != m )
8275 continue;
8276 s_rate += s_pl[sc]->status.bgstats.score;
8277 sc++;
8278 }
8279 if( sc < 1 ) return;
8280 else s_rate /= sc; // Avergate Source Rate
8281
8282 // Target
8283 for( i = tc = 0; i < MAX_BG_MEMBERS; i++ )
8284 {
8285 if( (t_pl[tc] = t_bg->members[i].sd) == NULL || t_pl[tc]->bl.m != m )
8286 continue;
8287 t_rate += t_pl[tc]->status.bgstats.score;
8288 tc++;
8289 }
8290 if( tc < 1 ) return;
8291 else t_rate /= tc; // Avergate Target Rate
8292
8293 Elo = (int)(50. / (1 + pow(10., (int)(s_rate - t_rate) / 2000.)));
8294 s_Elo = Elo / sc;
8295 for( i = 0; i < sc; i++ )
8296 add2limit(s_pl[i]->status.bgstats.score, s_Elo, 4000);
8297
8298 t_Elo = Elo / tc;
8299 for( i = 0; i < tc; i++ )
8300 sub2limit(t_pl[i]->status.bgstats.score, t_Elo, 0);
8301
8302 log_bg_kill(ssd,tsd,skill_id);
8303
8304 add2limit(ssd->status.bgstats.kill_count, 1, USHRT_MAX);
8305 add2limit(tsd->status.bgstats.death_count, 1, USHRT_MAX);
8306 ssd->bg_kills++; // This BG Kills
8307 }
8308 else if( ssd->state.pvpmode && tsd->state.pvpmode )
8309 {
8310 /*==========================================
8311 * PVP Mode Ranking
8312 *------------------------------------------*/
8313 struct party_data *p;
8314 struct map_session_data *s_pl[MAX_PARTY];
8315 unsigned int s_rate = 0, t_rate = 0;
8316 int sc = 1, tc = 1;
8317 int s_Elo;
8318
8319 // Source
8320 if( ssd->status.party_id && (p = party_search(ssd->status.party_id)) != NULL )
8321 {
8322 for( i = sc = 0; i < MAX_PARTY; i++ )
8323 {
8324 if( (s_pl[sc] = p->data[i].sd) == NULL || s_pl[sc]->bl.m != m )
8325 continue;
8326 if( pc_isdead(s_pl[sc]) && s_pl[sc] != ssd )
8327 continue;
8328
8329 s_rate += s_pl[sc]->status.pk.score;
8330 sc++;
8331 }
8332 if( sc < 1 ) return;
8333 }
8334 else
8335 {
8336 s_pl[0] = ssd;
8337 s_rate = s_pl[0]->status.pk.score;
8338 }
8339
8340 s_rate /= sc; // Average Source Rate
8341
8342 // Target
8343 if( tsd->status.party_id && (p = party_search(tsd->status.party_id)) != NULL )
8344 {
8345 for( i = tc = 0; i < MAX_PARTY; i++ )
8346 {
8347 if( p->data[i].sd == NULL || p->data[i].sd->bl.m != m )
8348 continue;
8349 if( pc_isdead(p->data[i].sd) && p->data[i].sd != tsd )
8350 continue;
8351 t_rate += p->data[i].sd->status.pk.score;
8352 tc++;
8353 }
8354 if( tc < 1 ) return;
8355 }
8356 else
8357 t_rate = tsd->status.pk.score;
8358
8359 t_rate /= sc; // Average Target Rate
8360 Elo = (int)(50. / (1 + pow(10., (int)(s_rate - t_rate) / 1000.)));
8361 s_Elo = Elo / sc;
8362
8363 for( i = 0; i < sc; i++ )
8364 pc_addfame(s_pl[i], s_Elo, 1);
8365
8366 add2limit(ssd->status.pk.kill_count, 1, USHRT_MAX);
8367 add2limit(tsd->status.pk.death_count, 1, USHRT_MAX);
8368 }
8369
8370 if( ssd->state.battleinfo )
8371 {
8372 sprintf(output,"( You Kill the %s [%s] using <%s> )", job_name(tsd->status.class_), tsd->status.name, ( skill_id ? skill_get_desc(skill_id) : "Melee/Reflect/Effect" ));
8373 clif_disp_onlyself(ssd,output,strlen(output));
8374 }
8375 if( tsd->state.battleinfo )
8376 {
8377 sprintf(output,"( The %s [%s] kill you using <%s> )", job_name(ssd->status.class_), ssd->status.name, ( skill_id ? skill_get_desc(skill_id) : "Melee/Reflect/Effect" ));
8378 clif_disp_onlyself(tsd,output,strlen(output));
8379 }
8380}
8381
8382/*==========================================
8383 * Invoked when a player has negative current hp
8384 *------------------------------------------*/
8385int pc_dead(struct map_session_data *sd,struct block_list *src,uint16 skill_id)
8386{
8387 int i=0,k=0;
8388 unsigned int tick = gettick();
8389 short flag = 0;
8390 int drop_skull_rate = sd->status.base_level; // Declaracion para sistema de porcentaje de drop trofeo [Tab]
8391
8392 // Activate Steel body if a super novice dies at 99+% exp [celest]
8393 // Super Novices have no kill or die functions attached when saved by their angel
8394 if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && !sd->state.snovice_dead_flag) {
8395 unsigned int next = pc_nextbaseexp(sd);
8396 if( next == 0 ) next = pc_thisbaseexp(sd);
8397 if( get_percentage(sd->status.base_exp,next) >= 99 ) {
8398 sd->state.snovice_dead_flag = 1;
8399 pc_setrestartvalue(sd,1);
8400 status_percent_heal(&sd->bl, 100, 100);
8401 clif_resurrection(&sd->bl, 1);
8402 if(battle_config.pc_invincible_time)
8403 pc_setinvincibletimer(sd, battle_config.pc_invincible_time);
8404 sc_start(&sd->bl,&sd->bl,status_skill2sc(MO_STEELBODY),100,5,skill_get_time(MO_STEELBODY,5));
8405 if(map_flag_gvg(sd->bl.m))
8406 pc_respawn_timer(INVALID_TIMER, gettick(), sd->bl.id, 0);
8407 return 0;
8408 }
8409 }
8410
8411 for(k = 0; k < 5; k++)
8412 if (sd->devotion[k]){
8413 struct map_session_data *devsd = map_id2sd(sd->devotion[k]);
8414 if (devsd)
8415 status_change_end(&devsd->bl, SC_DEVOTION, INVALID_TIMER);
8416 sd->devotion[k] = 0;
8417 }
8418 if(sd->shadowform_id) { //if we were target of shadowform
8419 status_change_end(map_id2bl(sd->shadowform_id), SC__SHADOWFORM, INVALID_TIMER);
8420 sd->shadowform_id = 0; //should be remove on status end anyway
8421 }
8422
8423 if(sd->status.pet_id > 0 && sd->pd) {
8424 struct pet_data *pd = sd->pd;
8425 if( !map[sd->bl.m].flag.noexppenalty && !flag )
8426 {
8427 pet_set_intimate(pd, pd->pet.intimate - pd->petDB->die);
8428 if( pd->pet.intimate < 0 )
8429 pd->pet.intimate = 0;
8430 clif_send_petdata(sd,sd->pd,1,pd->pet.intimate);
8431 }
8432 if( sd->pd->target_id ) // Unlock all targets...
8433 pet_unlocktarget(sd->pd);
8434 }
8435
8436 if (sd->status.hom_id > 0) {
8437 if(battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE])
8438 merc_hom_vaporize(sd, HOM_ST_ACTIVE);
8439 }
8440
8441 if( sd->md )
8442 merc_delete(sd->md, 3); // Your mercenary soldier has ran away.
8443
8444 if( sd->ed )
8445 elemental_delete(sd->ed, 0);
8446
8447 // Leave duel if you die [LuzZza]
8448 if(battle_config.duel_autoleave_when_die) {
8449 if(sd->duel_group > 0)
8450 duel_leave(sd->duel_group, sd);
8451 if(sd->duel_invite > 0)
8452 duel_reject(sd->duel_invite, sd);
8453 }
8454
8455 pc_close_npc(sd,2); //close npc if we were using one
8456
8457 /* e.g. not killed thru pc_damage */
8458 if( pc_issit(sd) ) {
8459 clif_status_load(&sd->bl,SI_SIT,0);
8460 }
8461
8462 if( map[sd->bl.m].flag.diecounter )
8463 {
8464 if( --map[sd->bl.m].pjmuertos < 1 )
8465 {
8466 clif_broadcast(&sd->bl, "Ganan las fuerzas invasoras", strlen("Ganan las fuerzas invasoras") + 1, 0, ALL_SAMEMAP);
8467 map[sd->bl.m].flag.diecounter = 0;
8468 }
8469 }
8470
8471 if( map[sd->bl.m].flag.residentevil )
8472 {
8473 int zombiernd[4] = { 1297, 1041, 1015, 1036 };
8474 char tmp_name[NAME_LENGTH];
8475 snprintf(tmp_name, NAME_LENGTH, "Zombie %s", sd->status.name);
8476 mob_once_spawn_especial(sd, "this", sd->bl.x, sd->bl.y, tmp_name, zombiernd[rand()%4], 1, "", 0, 0, 0, false, 1, 0, false, false, !(map[sd->bl.m].flag.residentevil == 2), 0, 0, 0, false, 0, 0);
8477 }
8478
8479 pc_setdead(sd);
8480 // eAmod - Moved KillerID after master killer is found
8481
8482 //Reset menu skills/item skills
8483 if ((sd->skillitem) != 0)
8484 sd->skillitem = sd->skillitemlv = 0;
8485 if ((sd->menuskill_id) != 0)
8486 sd->menuskill_id = sd->menuskill_val = 0;
8487 //Reset ticks.
8488 sd->hp_loss.tick = sd->sp_loss.tick = sd->hp_regen.tick = sd->sp_regen.tick = 0;
8489
8490 if ( sd->spiritball !=0 )
8491 pc_delspiritball(sd,sd->spiritball,0);
8492
8493 for(i = 1; i < 5; i++)
8494 pc_del_talisman(sd, sd->talisman[i], i);
8495
8496 if (src)
8497 switch (src->type) {
8498 case BL_MOB:
8499 {
8500 struct mob_data *md=(struct mob_data *)src;
8501 if(md->target_id==sd->bl.id)
8502 mob_unlocktarget(md,tick);
8503 if(battle_config.mobs_level_up && md->status.hp &&
8504 (unsigned int)md->level < pc_maxbaselv(sd) && !md->option.is_event &&
8505 !md->guardian_data && !md->special_state.ai// Guardians/summons should not level. [Skotlex]
8506 ) { // monster level up [Valaris]
8507 clif_misceffect(&md->bl,0);
8508 md->level++;
8509 status_calc_mob(md, 0);
8510 status_percent_heal(src,10,0);
8511 }
8512
8513 if( md->option.is_event )
8514 flag = 1;
8515
8516 src = battle_get_master(src); // Maybe Player Summon
8517 }
8518 break;
8519 case BL_PET: //Pass on to master...
8520 case BL_HOM:
8521 case BL_MER:
8522 case BL_SKILL:
8523 src = battle_get_master(src);
8524 break;
8525 }
8526
8527 pc_setglobalreg(sd,"PC_DIE_COUNTER",sd->die_counter+1);
8528 pc_setparam(sd, SP_KILLERRID, src?src->id:0);
8529
8530 // (!) NPC Events and BG Events moved to status.c to avoid issues (by rAthena)
8531
8532 if (src && src->type == BL_PC) {
8533 struct map_session_data *ssd = (struct map_session_data *)src;
8534 pc_calc_ranking(sd, ssd, skill_id); // Ranking System
8535 pc_setparam(ssd, SP_KILLEDRID, sd->bl.id);
8536 npc_script_event(ssd, NPCE_KILLPC);
8537
8538 if( ssd->status.guild_id && guild_wardamage(sd) )
8539 flag = 2;
8540
8541 if (battle_config.pk_mode&2) {
8542 ssd->status.manner -= 5;
8543 if(ssd->status.manner < 0)
8544 sc_start(&sd->bl,src,SC_NOCHAT,100,0,0);
8545#if 0
8546 // PK/Karma system code (not enabled yet) [celest]
8547 // originally from Kade Online, so i don't know if any of these is correct ^^;
8548 // note: karma is measured REVERSE, so more karma = more 'evil' / less honourable,
8549 // karma going down = more 'good' / more honourable.
8550 // The Karma System way...
8551
8552 if (sd->status.karma > ssd->status.karma) { // If player killed was more evil
8553 sd->status.karma--;
8554 ssd->status.karma--;
8555 }
8556 else if (sd->status.karma < ssd->status.karma) // If player killed was more good
8557 ssd->status.karma++;
8558
8559
8560 // or the PK System way...
8561
8562 if (sd->status.karma > 0) // player killed is dishonourable?
8563 ssd->status.karma--; // honour points earned
8564 sd->status.karma++; // honour points lost
8565
8566 // To-do: Receive exp on certain occasions
8567#endif
8568 }
8569 }
8570
8571 if(battle_config.bone_drop==2
8572 || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp))
8573 {
8574 struct item item_tmp;
8575 memset(&item_tmp,0,sizeof(item_tmp));
8576 item_tmp.nameid=ITEMID_SKULL_;
8577 item_tmp.identify=1;
8578 item_tmp.card[0]=CARD0_CREATE;
8579 item_tmp.card[1]=0;
8580 item_tmp.card[2]=GetWord(sd->status.char_id,0); // CharId
8581 item_tmp.card[3]=GetWord(sd->status.char_id,1);
8582 map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0,0);
8583 }
8584
8585 //Remove bonus_script when dead
8586 pc_bonus_script_clear(sd,BONUS_FLAG_REM_ON_DEAD);
8587
8588 // Graveyard System
8589 if( battle_config.pc_graveyard && src && (src->type == BL_PC || src->type == BL_MOB) && !map_flag_vs(src->m) )
8590 {
8591 struct npc_data* nd;
8592 if( sd->graveyard_npc_id && (nd = map_id2nd(sd->graveyard_npc_id)) != NULL )
8593 npc_unload(nd,true);
8594 sd->graveyard_npc_id = 0;
8595 npc_duplicate4graveyard(&sd->bl,src);
8596 }
8597
8598 // PVPMode OFF
8599 if( sd->state.pvpmode ) pc_pvpmodeoff(sd, 1, 1);
8600
8601 // changed penalty options, added death by player if pk_mode [Valaris]
8602 if(battle_config.death_penalty_type
8603 && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty
8604 && !map[sd->bl.m].flag.noexppenalty && !map_flag_gvg3(sd->bl.m)
8605 && flag != 1 // No Exp penalty if killed by noexp mob.
8606 && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_LIFEINSURANCE])
8607 {
8608 uint32 base_penalty = battle_config.death_penalty_base;
8609 uint32 job_penalty = battle_config.death_penalty_job;
8610 uint32 zeny_penalty = battle_config.zeny_penalty;
8611
8612#ifdef VIP_ENABLE
8613 if(pc_isvip(sd)){
8614 base_penalty *= battle_config.vip_exp_penalty_base;
8615 job_penalty *= battle_config.vip_exp_penalty_job;
8616 }
8617 else {
8618 base_penalty *= battle_config.vip_exp_penalty_base_normal;
8619 job_penalty *= battle_config.vip_exp_penalty_job_normal;
8620 }
8621#endif
8622 if( pc_readaccountreg(sd,"#isVIP") == 1 ) {
8623 base_penalty *= battle_config.cstm_vip_bexp_penalty;
8624 job_penalty *= battle_config.cstm_vip_jexp_penalty;
8625 } else {
8626 base_penalty *= battle_config.cstm_non_vip_bexp_penalty;
8627 job_penalty *= battle_config.cstm_non_vip_jexp_penalty;
8628 }
8629
8630 if (base_penalty > 0) {
8631 switch (battle_config.death_penalty_type) {
8632 case 1: base_penalty = (uint32) ( pc_nextbaseexp(sd) * ( base_penalty / 10000. ) ); break;
8633 case 2: base_penalty = (uint32) ( sd->status.base_exp * ( base_penalty / 10000. ) ); break;
8634 }
8635 if (base_penalty > 0){ //recheck after altering to speedup
8636 if (battle_config.pk_mode && src && src->type==BL_PC)
8637 base_penalty*=2;
8638 sd->status.base_exp -= min(sd->status.base_exp, base_penalty);
8639 clif_updatestatus(sd,SP_BASEEXP);
8640 }
8641 }
8642
8643 if(job_penalty > 0) {
8644 switch (battle_config.death_penalty_type) {
8645 case 1: job_penalty = (uint32) ( pc_nextjobexp(sd) * ( job_penalty / 10000. ) ); break;
8646 case 2: job_penalty = (uint32) ( sd->status.job_exp * ( job_penalty /10000. ) ); break;
8647 }
8648 if(job_penalty) {
8649 if (battle_config.pk_mode && src && src->type==BL_PC)
8650 job_penalty*=2;
8651 sd->status.job_exp -= min(sd->status.job_exp, job_penalty);
8652 clif_updatestatus(sd,SP_JOBEXP);
8653 }
8654 }
8655
8656 if( zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) {
8657 zeny_penalty = (uint32)( sd->status.zeny * ( zeny_penalty / 10000. ) );
8658 if(zeny_penalty)
8659 pc_payzeny(sd, zeny_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL);
8660 }
8661 }
8662
8663 if(map[sd->bl.m].flag.pvp_nightmaredrop && pc_checkskill(sd,BS_HILTBINDING) <= 0) { // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker]
8664 int j;
8665 for(j=0;j<MAX_DROP_PER_MAP;j++){
8666 int id = map[sd->bl.m].drop_list[j].drop_id;
8667 int type = map[sd->bl.m].drop_list[j].drop_type;
8668 int per = map[sd->bl.m].drop_list[j].drop_per;
8669 if(id == 0)
8670 continue;
8671 if(id == -1){
8672 int eq_num=0,eq_n[MAX_INVENTORY];
8673 memset(eq_n,0,sizeof(eq_n));
8674 for(i=0;i<MAX_INVENTORY;i++) {
8675 if( (type == 1 && !sd->status.inventory[i].equip)
8676 || (type == 2 && sd->status.inventory[i].equip)
8677 || type == 3)
8678 {
8679 int k;
8680 ARR_FIND( 0, MAX_INVENTORY, k, eq_n[k] <= 0 );
8681 if( k < MAX_INVENTORY )
8682 eq_n[k] = i;
8683
8684 eq_num++;
8685 }
8686 }
8687 if(eq_num > 0){
8688 int n = eq_n[rnd()%eq_num];
8689 if(rnd()%10000 < per) {
8690 if(sd->status.inventory[n].equip)
8691 pc_unequipitem(sd,n,3);
8692 pc_dropitem(sd,n,1);
8693 }
8694 }
8695 }
8696 else if(id > 0) {
8697 for(i=0;i<MAX_INVENTORY;i++){
8698 if(sd->status.inventory[i].nameid == id
8699 && rnd()%10000 < per
8700 && ((type == 1 && !sd->status.inventory[i].equip)
8701 || (type == 2 && sd->status.inventory[i].equip)
8702 || type == 3) ){
8703 if(sd->status.inventory[i].equip)
8704 pc_unequipitem(sd,i,3);
8705 pc_dropitem(sd,i,1);
8706 break;
8707 }
8708 }
8709 }
8710 }
8711 }
8712 // pvp
8713 // disable certain pvp functions on pk_mode [Valaris]
8714 if( map[sd->bl.m].flag.pvp && !battle_config.pk_mode && !map[sd->bl.m].flag.pvp_nocalcrank ) {
8715 sd->pvp_point -= 5;
8716 sd->pvp_lost++;
8717 if( src && src->type == BL_PC ) {
8718 struct map_session_data *ssd = (struct map_session_data *)src;
8719 ssd->pvp_point++;
8720 ssd->pvp_won++;
8721 }
8722 if( sd->pvp_point < 0 ) {
8723 add_timer(tick+1000, pc_respawn_timer,sd->bl.id,0);
8724 return 1|8;
8725 }
8726 }
8727 //GvG
8728 if( map_flag_gvg(sd->bl.m) || map_pvpevent(sd->bl.m) ) {
8729 add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0);
8730 return 1|8;
8731 }
8732 else if( sd->bg_id ) {
8733 struct battleground_data *bg = bg_team_search(sd->bg_id);
8734 if( bg && bg->mapindex > 0 ) { // Respawn by BG
8735 add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0);
8736 return 1|8;
8737 }
8738 }
8739
8740 sd->canescape_tick = gettick() - 10000;
8741
8742 //Reset "can log out" tick.
8743 if( battle_config.prevent_logout )
8744 sd->canlog_tick = gettick() - battle_config.prevent_logout;
8745 return 1;
8746}
8747
8748void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) {
8749 if(hp) clif_updatestatus(sd,SP_HP);
8750 if(sp) clif_updatestatus(sd,SP_SP);
8751
8752 pc_setstand(sd);
8753 if(battle_config.pc_invincible_time > 0)
8754 pc_setinvincibletimer(sd, battle_config.pc_invincible_time);
8755
8756 if( sd->state.gmaster_flag ) {
8757 guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->state.gmaster_flag,GD_LEADERSHIP));
8758 guild_guildaura_refresh(sd,GD_GLORYWOUNDS,guild_checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS));
8759 guild_guildaura_refresh(sd,GD_SOULCOLD,guild_checkskill(sd->state.gmaster_flag,GD_SOULCOLD));
8760 guild_guildaura_refresh(sd,GD_HAWKEYES,guild_checkskill(sd->state.gmaster_flag,GD_HAWKEYES));
8761 }
8762}
8763// script
8764//
8765/*==========================================
8766 * script reading pc status registry
8767 *------------------------------------------*/
8768int pc_readparam(struct map_session_data* sd,int type)
8769{
8770 int val = 0;
8771
8772 nullpo_ret(sd);
8773
8774 switch(type) {
8775 case SP_SKILLPOINT: val = sd->status.skill_point; break;
8776 case SP_STATUSPOINT: val = sd->status.status_point; break;
8777 case SP_ZENY: val = sd->status.zeny; break;
8778 case SP_BASELEVEL: val = sd->status.base_level; break;
8779 case SP_JOBLEVEL: val = sd->status.job_level; break;
8780 case SP_CLASS: val = sd->status.class_; break;
8781 case SP_BASEJOB: val = pc_mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex); break; //Base job, extracting upper type.
8782 case SP_UPPER: val = sd->class_&JOBL_UPPER?1:(sd->class_&JOBL_BABY?2:0); break;
8783 case SP_BASECLASS: val = pc_mapid2jobid(sd->class_&MAPID_BASEMASK, sd->status.sex); break; //Extract base class tree. [Skotlex]
8784 case SP_SEX: val = sd->status.sex; break;
8785 case SP_WEIGHT: val = sd->weight; break;
8786 case SP_MAXWEIGHT: val = sd->max_weight; break;
8787 case SP_BASEEXP: val = sd->status.base_exp; break;
8788 case SP_JOBEXP: val = sd->status.job_exp; break;
8789 case SP_NEXTBASEEXP: val = pc_nextbaseexp(sd); break;
8790 case SP_NEXTJOBEXP: val = pc_nextjobexp(sd); break;
8791 case SP_HP: val = sd->battle_status.hp; break;
8792 case SP_MAXHP: val = sd->battle_status.max_hp; break;
8793 case SP_SP: val = sd->battle_status.sp; break;
8794 case SP_MAXSP: val = sd->battle_status.max_sp; break;
8795 case SP_STR: val = sd->status.str; break;
8796 case SP_AGI: val = sd->status.agi; break;
8797 case SP_VIT: val = sd->status.vit; break;
8798 case SP_INT: val = sd->status.int_; break;
8799 case SP_DEX: val = sd->status.dex; break;
8800 case SP_LUK: val = sd->status.luk; break;
8801 case SP_KARMA: val = sd->status.karma; break;
8802 case SP_MANNER: val = sd->status.manner; break;
8803 case SP_FAME: val = sd->status.fame; break;
8804 case SP_KILLERRID: val = sd->killerrid; break;
8805 case SP_KILLEDRID: val = sd->killedrid; break;
8806 case SP_SITTING: val = pc_issit(sd)?1:0; break;
8807 case SP_CHARMOVE: val = sd->status.character_moves; break;
8808 case SP_CRITICAL: val = sd->battle_status.cri/10; break;
8809 case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break;
8810 case SP_BASE_ATK: val = sd->battle_status.batk; break;
8811 case SP_DEF1: val = sd->battle_status.def; break;
8812 case SP_DEF2: val = sd->battle_status.def2; break;
8813 case SP_MDEF1: val = sd->battle_status.mdef; break;
8814 case SP_MDEF2: val = sd->battle_status.mdef2; break;
8815 case SP_HIT: val = sd->battle_status.hit; break;
8816 case SP_FLEE1: val = sd->battle_status.flee; break;
8817 case SP_FLEE2: val = sd->battle_status.flee2; break;
8818 case SP_DEFELE: val = sd->battle_status.def_ele; break;
8819#ifndef RENEWAL_CAST
8820 case SP_VARCASTRATE:
8821#endif
8822 case SP_CASTRATE:
8823 val = sd->castrate+=val;
8824 break;
8825 case SP_MAXHPRATE: val = sd->hprate; break;
8826 case SP_MAXSPRATE: val = sd->sprate; break;
8827 case SP_SPRATE: val = sd->dsprate; break;
8828 case SP_SPEED_RATE: val = sd->bonus.speed_rate; break;
8829 case SP_SPEED_ADDRATE: val = sd->bonus.speed_add_rate; break;
8830 case SP_ASPD_RATE:
8831#ifndef RENEWAL_ASPD
8832 val = sd->battle_status.aspd_rate;
8833#else
8834 val = sd->battle_status.aspd_rate2;
8835#endif
8836 break;
8837 case SP_HP_RECOV_RATE: val = sd->hprecov_rate; break;
8838 case SP_SP_RECOV_RATE: val = sd->sprecov_rate; break;
8839 case SP_CRITICAL_DEF: val = sd->bonus.critical_def; break;
8840 case SP_NEAR_ATK_DEF: val = sd->bonus.near_attack_def_rate; break;
8841 case SP_LONG_ATK_DEF: val = sd->bonus.long_attack_def_rate; break;
8842 case SP_DOUBLE_RATE: val = sd->bonus.double_rate; break;
8843 case SP_DOUBLE_ADD_RATE: val = sd->bonus.double_add_rate; break;
8844 case SP_MATK_RATE: val = sd->matk_rate; break;
8845 case SP_ATK_RATE: val = sd->bonus.atk_rate; break;
8846 case SP_MAGIC_ATK_DEF: val = sd->bonus.magic_def_rate; break;
8847 case SP_MISC_ATK_DEF: val = sd->bonus.misc_def_rate; break;
8848 case SP_PERFECT_HIT_RATE:val = sd->bonus.perfect_hit; break;
8849 case SP_PERFECT_HIT_ADD_RATE: val = sd->bonus.perfect_hit_add; break;
8850 case SP_CRITICAL_RATE: val = sd->critical_rate; break;
8851 case SP_HIT_RATE: val = sd->hit_rate; break;
8852 case SP_FLEE_RATE: val = sd->flee_rate; break;
8853 case SP_FLEE2_RATE: val = sd->flee2_rate; break;
8854 case SP_DEF_RATE: val = sd->def_rate; break;
8855 case SP_DEF2_RATE: val = sd->def2_rate; break;
8856 case SP_MDEF_RATE: val = sd->mdef_rate; break;
8857 case SP_MDEF2_RATE: val = sd->mdef2_rate; break;
8858 case SP_RESTART_FULL_RECOVER: val = sd->special_state.restart_full_recover?1:0; break;
8859 case SP_NO_CASTCANCEL: val = sd->special_state.no_castcancel?1:0; break;
8860 case SP_NO_CASTCANCEL2: val = sd->special_state.no_castcancel2?1:0; break;
8861 case SP_NO_SIZEFIX: val = sd->special_state.no_sizefix?1:0; break;
8862 case SP_NO_MAGIC_DAMAGE: val = sd->special_state.no_magic_damage; break;
8863 case SP_NO_WEAPON_DAMAGE:val = sd->special_state.no_weapon_damage; break;
8864 case SP_NO_MISC_DAMAGE: val = sd->special_state.no_misc_damage; break;
8865 case SP_NO_GEMSTONE: val = sd->special_state.no_gemstone?1:0; break;
8866 case SP_INTRAVISION: val = sd->special_state.intravision?1:0; break;
8867 case SP_NO_KNOCKBACK: val = sd->special_state.no_knockback?1:0; break;
8868 case SP_SPLASH_RANGE: val = sd->bonus.splash_range; break;
8869 case SP_SPLASH_ADD_RANGE:val = sd->bonus.splash_add_range; break;
8870 case SP_SHORT_WEAPON_DAMAGE_RETURN: val = sd->bonus.short_weapon_damage_return; break;
8871 case SP_LONG_WEAPON_DAMAGE_RETURN: val = sd->bonus.long_weapon_damage_return; break;
8872 case SP_MAGIC_DAMAGE_RETURN: val = sd->bonus.magic_damage_return; break;
8873 case SP_PERFECT_HIDE: val = sd->special_state.perfect_hiding?1:0; break;
8874 case SP_UNBREAKABLE: val = sd->bonus.unbreakable; break;
8875 case SP_UNBREAKABLE_WEAPON: val = (sd->bonus.unbreakable_equip&EQP_WEAPON)?1:0; break;
8876 case SP_UNBREAKABLE_ARMOR: val = (sd->bonus.unbreakable_equip&EQP_ARMOR)?1:0; break;
8877 case SP_UNBREAKABLE_HELM: val = (sd->bonus.unbreakable_equip&EQP_HELM)?1:0; break;
8878 case SP_UNBREAKABLE_SHIELD: val = (sd->bonus.unbreakable_equip&EQP_SHIELD)?1:0; break;
8879 case SP_UNBREAKABLE_GARMENT: val = (sd->bonus.unbreakable_equip&EQP_GARMENT)?1:0; break;
8880 case SP_UNBREAKABLE_SHOES: val = (sd->bonus.unbreakable_equip&EQP_SHOES)?1:0; break;
8881 case SP_CLASSCHANGE: val = sd->bonus.classchange; break;
8882 case SP_LONG_ATK_RATE: val = sd->bonus.long_attack_atk_rate; break;
8883 case SP_BREAK_WEAPON_RATE: val = sd->bonus.break_weapon_rate; break;
8884 case SP_BREAK_ARMOR_RATE: val = sd->bonus.break_armor_rate; break;
8885 case SP_ADD_STEAL_RATE: val = sd->bonus.add_steal_rate; break;
8886 case SP_DELAYRATE: val = sd->delayrate; break;
8887 case SP_CRIT_ATK_RATE: val = sd->bonus.crit_atk_rate; break;
8888 case SP_UNSTRIPABLE_WEAPON: val = (sd->bonus.unstripable_equip&EQP_WEAPON)?1:0; break;
8889 case SP_UNSTRIPABLE:
8890 case SP_UNSTRIPABLE_ARMOR:
8891 val = (sd->bonus.unstripable_equip&EQP_ARMOR)?1:0;
8892 break;
8893 case SP_UNSTRIPABLE_HELM: val = (sd->bonus.unstripable_equip&EQP_HELM)?1:0; break;
8894 case SP_UNSTRIPABLE_SHIELD: val = (sd->bonus.unstripable_equip&EQP_SHIELD)?1:0; break;
8895 case SP_SP_GAIN_VALUE: val = sd->bonus.sp_gain_value; break;
8896 case SP_HP_GAIN_VALUE: val = sd->bonus.hp_gain_value; break;
8897 case SP_MAGIC_SP_GAIN_VALUE: val = sd->bonus.magic_sp_gain_value; break;
8898 case SP_MAGIC_HP_GAIN_VALUE: val = sd->bonus.magic_hp_gain_value; break;
8899 case SP_ADD_HEAL_RATE: val = sd->bonus.add_heal_rate; break;
8900 case SP_ADD_HEAL2_RATE: val = sd->bonus.add_heal2_rate; break;
8901 case SP_ADD_ITEM_HEAL_RATE: val = sd->bonus.itemhealrate2; break;
8902 case SP_EMATK: val = sd->bonus.ematk; break;
8903 case SP_FIXCASTRATE: val = sd->bonus.fixcastrate; break;
8904 case SP_ADD_FIXEDCAST: val = sd->bonus.add_fixcast; break;
8905#ifdef RENEWAL_CAST
8906 case SP_VARCASTRATE: val = sd->bonus.varcastrate; break;
8907 case SP_ADD_VARIABLECAST:val = sd->bonus.add_varcast; break;
8908#endif
8909 }
8910
8911 return val;
8912}
8913
8914/*==========================================
8915 * script set pc status registry
8916 *------------------------------------------*/
8917bool pc_setparam(struct map_session_data *sd,int type,int val)
8918{
8919 nullpo_retr(false,sd);
8920
8921 switch(type){
8922 case SP_BASELEVEL:
8923 if ((unsigned int)val > pc_maxbaselv(sd)) //Capping to max
8924 val = pc_maxbaselv(sd);
8925 if ((unsigned int)val > sd->status.base_level) {
8926 int i = 0;
8927 int stat=0;
8928 for (i = 0; i < (int)((unsigned int)val - sd->status.base_level); i++)
8929 stat += pc_gets_status_point(sd->status.base_level + i);
8930 sd->status.status_point += stat;
8931 }
8932 sd->status.base_level = (unsigned int)val;
8933 sd->status.base_exp = 0;
8934 // clif_updatestatus(sd, SP_BASELEVEL); // Gets updated at the bottom
8935 clif_updatestatus(sd, SP_NEXTBASEEXP);
8936 clif_updatestatus(sd, SP_STATUSPOINT);
8937 clif_updatestatus(sd, SP_BASEEXP);
8938 status_calc_pc(sd, 0);
8939 if(sd->status.party_id)
8940 {
8941 party_send_levelup(sd);
8942 }
8943 break;
8944 case SP_JOBLEVEL:
8945 if ((unsigned int)val >= sd->status.job_level) {
8946 if ((unsigned int)val > pc_maxjoblv(sd)) val = pc_maxjoblv(sd);
8947 sd->status.skill_point += val - sd->status.job_level;
8948 clif_updatestatus(sd, SP_SKILLPOINT);
8949 }
8950 sd->status.job_level = (unsigned int)val;
8951 sd->status.job_exp = 0;
8952 // clif_updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom
8953 clif_updatestatus(sd, SP_NEXTJOBEXP);
8954 clif_updatestatus(sd, SP_JOBEXP);
8955 status_calc_pc(sd, 0);
8956 break;
8957 case SP_SKILLPOINT:
8958 sd->status.skill_point = val;
8959 break;
8960 case SP_STATUSPOINT:
8961 sd->status.status_point = val;
8962 break;
8963 case SP_ZENY:
8964 if( val < 0 )
8965 return false;// can't set negative zeny
8966 log_zeny(sd, LOG_TYPE_SCRIPT, sd, -(sd->status.zeny - cap_value(val, 0, MAX_ZENY)));
8967 sd->status.zeny = cap_value(val, 0, MAX_ZENY);
8968 break;
8969 case SP_BASEEXP:
8970 if(pc_nextbaseexp(sd) > 0) {
8971 sd->status.base_exp = val;
8972 pc_checkbaselevelup(sd);
8973 }
8974 break;
8975 case SP_JOBEXP:
8976 if(pc_nextjobexp(sd) > 0) {
8977 sd->status.job_exp = val;
8978 pc_checkjoblevelup(sd);
8979 }
8980 break;
8981 case SP_SEX:
8982 sd->status.sex = val ? SEX_MALE : SEX_FEMALE;
8983 break;
8984 case SP_WEIGHT:
8985 sd->weight = val;
8986 break;
8987 case SP_MAXWEIGHT:
8988 sd->max_weight = val;
8989 break;
8990 case SP_HP:
8991 sd->battle_status.hp = cap_value(val, 1, (int)sd->battle_status.max_hp);
8992 break;
8993 case SP_MAXHP:
8994 sd->battle_status.max_hp = cap_value(val, 1, battle_config.max_hp);
8995
8996 if( sd->battle_status.max_hp < sd->battle_status.hp )
8997 {
8998 sd->battle_status.hp = sd->battle_status.max_hp;
8999 clif_updatestatus(sd, SP_HP);
9000 }
9001 break;
9002 case SP_SP:
9003 sd->battle_status.sp = cap_value(val, 0, (int)sd->battle_status.max_sp);
9004 break;
9005 case SP_MAXSP:
9006 sd->battle_status.max_sp = cap_value(val, 1, battle_config.max_sp);
9007
9008 if( sd->battle_status.max_sp < sd->battle_status.sp )
9009 {
9010 sd->battle_status.sp = sd->battle_status.max_sp;
9011 clif_updatestatus(sd, SP_SP);
9012 }
9013 break;
9014 case SP_STR:
9015 sd->status.str = cap_value(val, 1, pc_maxparameter(sd,PARAM_STR));
9016 break;
9017 case SP_AGI:
9018 sd->status.agi = cap_value(val, 1, pc_maxparameter(sd,PARAM_AGI));
9019 break;
9020 case SP_VIT:
9021 sd->status.vit = cap_value(val, 1, pc_maxparameter(sd,PARAM_VIT));
9022 break;
9023 case SP_INT:
9024 sd->status.int_ = cap_value(val, 1, pc_maxparameter(sd,PARAM_INT));
9025 break;
9026 case SP_DEX:
9027 sd->status.dex = cap_value(val, 1, pc_maxparameter(sd,PARAM_DEX));
9028 break;
9029 case SP_LUK:
9030 sd->status.luk = cap_value(val, 1, pc_maxparameter(sd,PARAM_LUK));
9031 break;
9032 case SP_KARMA:
9033 sd->status.karma = val;
9034 break;
9035 case SP_MANNER:
9036 sd->status.manner = val;
9037 break;
9038 case SP_FAME:
9039 sd->status.fame = val;
9040 break;
9041 case SP_KILLERRID:
9042 sd->killerrid = val;
9043 return true;
9044 case SP_KILLEDRID:
9045 sd->killedrid = val;
9046 return true;
9047 case SP_CHARMOVE:
9048 sd->status.character_moves = val;
9049 return true;
9050 default:
9051 ShowError("pc_setparam: Attempted to set unknown parameter '%d'.\n", type);
9052 return false;
9053 }
9054 clif_updatestatus(sd,type);
9055
9056 return true;
9057}
9058
9059/*==========================================
9060 * HP/SP Healing. If flag is passed, the heal type is through clif_heal, otherwise update status.
9061 *------------------------------------------*/
9062void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int type)
9063{
9064 if (type) {
9065 if (hp)
9066 clif_heal(sd->fd,SP_HP,hp);
9067 if (sp)
9068 clif_heal(sd->fd,SP_SP,sp);
9069 } else {
9070 if(hp)
9071 clif_updatestatus(sd,SP_HP);
9072 if(sp)
9073 clif_updatestatus(sd,SP_SP);
9074 }
9075 return;
9076}
9077
9078/*==========================================
9079 * HP/SP Recovery
9080 * Heal player hp and/or sp linearly.
9081 * Calculate bonus by status.
9082 *------------------------------------------*/
9083int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
9084{
9085 int bonus;
9086
9087 if(hp) {
9088 int i;
9089 bonus = 100 + (sd->battle_status.vit<<1)
9090 + pc_checkskill(sd,SM_RECOVERY)*10
9091 + pc_checkskill(sd,AM_LEARNINGPOTION)*5;
9092 // A potion produced by an Alchemist in the Fame Top 10 gets +50% effect [DracoRPG]
9093 if (potion_flag > 1)
9094 bonus += bonus*(potion_flag-1)*50/100;
9095 //All item bonuses.
9096 bonus += sd->bonus.itemhealrate2;
9097 //Item Group bonuses
9098 bonus += bonus*itemdb_group_bonus(sd, itemid)/100;
9099 //Individual item bonuses.
9100 for(i = 0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid; i++)
9101 {
9102 if (sd->itemhealrate[i].nameid == itemid) {
9103 bonus += bonus*sd->itemhealrate[i].rate/100;
9104 break;
9105 }
9106 }
9107 if(bonus!=100)
9108 hp = hp * bonus / 100;
9109
9110 // Recovery Potion
9111 if( sd->sc.data[SC_INCHEALRATE] )
9112 hp += (int)(hp * sd->sc.data[SC_INCHEALRATE]->val1/100.);
9113
9114 if( sd->status.guild_id && map_allowed_woe(sd->bl.m) )
9115 add2limit(sd->status.wstats.hp_heal_potions, 1, UINT_MAX);
9116 else if( map[sd->bl.m].flag.battleground && sd->bg_id )
9117 add2limit(sd->status.bgstats.hp_heal_potions, 1, UINT_MAX);
9118 }
9119 if(sp) {
9120 bonus = 100 + (sd->battle_status.int_<<1)
9121 + pc_checkskill(sd,MG_SRECOVERY)*10
9122 + pc_checkskill(sd,AM_LEARNINGPOTION)*5;
9123 if (potion_flag > 1)
9124 bonus += bonus*(potion_flag-1)*50/100;
9125 if(bonus != 100)
9126 sp = sp * bonus / 100;
9127
9128 if( sd->status.guild_id && map_allowed_woe(sd->bl.m) )
9129 add2limit(sd->status.wstats.sp_heal_potions, 1, UINT_MAX);
9130 else if( map[sd->bl.m].flag.battleground && sd->bg_id )
9131 add2limit(sd->status.bgstats.sp_heal_potions, 1, UINT_MAX);
9132 }
9133 if( sd->sc.count ) {
9134 if ( sd->sc.data[SC_CRITICALWOUND] ) {
9135 hp -= hp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100;
9136 sp -= sp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100;
9137 }
9138
9139 if ( sd->sc.data[SC_DEATHHURT] ) {
9140 hp -= hp * 20 / 100;
9141 sp -= sp * 20 / 100;
9142 }
9143
9144 if( sd->sc.data[SC_VITALITYACTIVATION] ){
9145 hp += hp / 2; // 1.5 times
9146 sp -= sp / 2;
9147 }
9148
9149 if( sd->sc.data[SC_WATER_INSIGNIA] && sd->sc.data[SC_WATER_INSIGNIA]->val1 == 2 ) {
9150 hp += hp / 10;
9151 sp += sp / 10;
9152 }
9153#ifdef RENEWAL
9154 if( sd->sc.data[SC_EXTREMITYFIST2] )
9155 sp = 0;
9156#endif
9157 }
9158
9159 return status_heal(&sd->bl, hp, sp, 1);
9160}
9161
9162/*==========================================
9163 * HP/SP Recovery
9164 * Heal player hp nad/or sp by rate
9165 *------------------------------------------*/
9166int pc_percentheal(struct map_session_data *sd,int hp,int sp)
9167{
9168 nullpo_ret(sd);
9169
9170 if (hp > 100) hp = 100;
9171 else if (hp <-100) hp = -100;
9172
9173 if (sp > 100) sp = 100;
9174 else if (sp <-100) sp = -100;
9175
9176 if(hp >= 0 && sp >= 0) //Heal
9177 return status_percent_heal(&sd->bl, hp, sp);
9178
9179 if(hp <= 0 && sp <= 0) //Damage (negative rates indicate % of max rather than current), and only kill target IF the specified amount is 100%
9180 return status_percent_damage(NULL, &sd->bl, hp, sp, hp==-100);
9181
9182 //Crossed signs
9183 if(hp) {
9184 if(hp > 0)
9185 status_percent_heal(&sd->bl, hp, 0);
9186 else
9187 status_percent_damage(NULL, &sd->bl, hp, 0, hp==-100);
9188 }
9189
9190 if(sp) {
9191 if(sp > 0)
9192 status_percent_heal(&sd->bl, 0, sp);
9193 else
9194 status_percent_damage(NULL, &sd->bl, 0, sp, false);
9195 }
9196 return 0;
9197}
9198
9199static int jobchange_killclone(struct block_list *bl, va_list ap)
9200{
9201 struct mob_data *md;
9202 int flag;
9203 md = (struct mob_data *)bl;
9204 nullpo_ret(md);
9205 flag = va_arg(ap, int);
9206
9207 if (md->master_id && md->special_state.clone && md->master_id == flag)
9208 status_kill(&md->bl);
9209 return 1;
9210}
9211
9212/*==========================================
9213 * Called when player changes job
9214 * Rewrote to make it tidider [Celest]
9215 *------------------------------------------*/
9216int pc_jobchange(struct map_session_data *sd,int job, int upper)
9217{
9218 int i, fame_flag=0;
9219 int b_class;
9220
9221 nullpo_ret(sd);
9222
9223 if (job < 0)
9224 return 1;
9225
9226 //Normalize job.
9227 b_class = pc_jobid2mapid(job);
9228 if (b_class == -1)
9229 return 1;
9230 switch (upper) {
9231 case 1:
9232 b_class|= JOBL_UPPER;
9233 break;
9234 case 2:
9235 b_class|= JOBL_BABY;
9236 break;
9237 }
9238 //This will automatically adjust bard/dancer classes to the correct gender
9239 //That is, if you try to jobchange into dancer, it will turn you to bard.
9240 job = pc_mapid2jobid(b_class, sd->status.sex);
9241 if (job == -1)
9242 return 1;
9243
9244 if ((unsigned short)b_class == sd->class_)
9245 return 1; //Nothing to change.
9246
9247 // changing from 1st to 2nd job
9248 if ((b_class&JOBL_2) && !(sd->class_&JOBL_2) && (b_class&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) {
9249 sd->change_level_2nd = sd->status.job_level;
9250 pc_setglobalreg (sd, "jobchange_level", sd->change_level_2nd);
9251 }
9252 // changing from 2nd to 3rd job
9253 else if((b_class&JOBL_THIRD) && !(sd->class_&JOBL_THIRD)) {
9254 sd->change_level_3rd = sd->status.job_level;
9255 pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd);
9256 }
9257
9258 if(sd->cloneskill_idx >= 0) {
9259 if( sd->status.skill[sd->cloneskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
9260 sd->status.skill[sd->cloneskill_idx].id = 0;
9261 sd->status.skill[sd->cloneskill_idx].lv = 0;
9262 sd->status.skill[sd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT;
9263 clif_deleteskill(sd,pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM));
9264 }
9265 sd->cloneskill_idx = -1;
9266 pc_setglobalreg(sd,SKILL_VAR_PLAGIARISM, 0);
9267 pc_setglobalreg(sd,SKILL_VAR_PLAGIARISM_LV, 0);
9268 }
9269
9270 if(sd->reproduceskill_idx >= 0) {
9271 if( sd->status.skill[sd->reproduceskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
9272 sd->status.skill[sd->reproduceskill_idx].id = 0;
9273 sd->status.skill[sd->reproduceskill_idx].lv = 0;
9274 sd->status.skill[sd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT;
9275 clif_deleteskill(sd,pc_readglobalreg(sd,SKILL_VAR_REPRODUCE));
9276 }
9277 sd->reproduceskill_idx = -1;
9278 pc_setglobalreg(sd,SKILL_VAR_REPRODUCE,0);
9279 pc_setglobalreg(sd,SKILL_VAR_REPRODUCE_LV,0);
9280 }
9281
9282 // Give or reduce transcendent status points
9283 if( (b_class&JOBL_UPPER) && !(sd->class_&JOBL_UPPER) ){ // Change from a non t class to a t class -> give points
9284 sd->status.status_point += 52;
9285 clif_updatestatus(sd,SP_STATUSPOINT);
9286 }else if( !(b_class&JOBL_UPPER) && (sd->class_&JOBL_UPPER) ){ // Change from a t class to a non t class -> remove points
9287 if( sd->status.status_point < 52 ){
9288 // The player already used his bonus points, so we have to reset his status points
9289 pc_resetstate(sd);
9290 }
9291 sd->status.status_point -= 52;
9292 clif_updatestatus(sd,SP_STATUSPOINT);
9293 }
9294
9295 if ( (b_class&MAPID_UPPERMASK) != (sd->class_&MAPID_UPPERMASK) ) { //Things to remove when changing class tree.
9296 const int class_ = pc_class2idx(sd->status.class_);
9297 short id;
9298 for(i = 0; i < MAX_SKILL_TREE && (id = skill_tree[class_][i].id) > 0; i++) {
9299 //Remove status specific to your current tree skills.
9300 enum sc_type sc = status_skill2sc(id);
9301 if (sc > SC_COMMON_MAX && sd->sc.data[sc])
9302 status_change_end(&sd->bl, sc, INVALID_TIMER);
9303 }
9304 }
9305
9306 if( (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && (b_class&MAPID_UPPERMASK) != MAPID_STAR_GLADIATOR) {
9307 /* going off star glad lineage, reset feel to not store no-longer-used vars in the database */
9308 pc_resetfeel(sd);
9309 }
9310
9311 sd->status.class_ = job;
9312 fame_flag = pc_famerank(sd->status.char_id,sd->class_&MAPID_UPPERMASK);
9313 sd->class_ = (unsigned short)b_class;
9314 sd->status.job_level=1;
9315 sd->status.job_exp=0;
9316
9317 if (sd->status.base_level > pc_maxbaselv(sd)) {
9318 sd->status.base_level = pc_maxbaselv(sd);
9319 sd->status.base_exp=0;
9320 pc_resetstate(sd);
9321 clif_updatestatus(sd,SP_STATUSPOINT);
9322 clif_updatestatus(sd,SP_BASELEVEL);
9323 clif_updatestatus(sd,SP_BASEEXP);
9324 clif_updatestatus(sd,SP_NEXTBASEEXP);
9325 }
9326
9327 clif_updatestatus(sd,SP_JOBLEVEL);
9328 clif_updatestatus(sd,SP_JOBEXP);
9329 clif_updatestatus(sd,SP_NEXTJOBEXP);
9330
9331 for(i=0;i<EQI_MAX;i++) {
9332 if(sd->equip_index[i] >= 0)
9333 if(!pc_isequip(sd,sd->equip_index[i]))
9334 pc_unequipitem(sd,sd->equip_index[i],2); // unequip invalid item for class
9335 }
9336
9337 //Change look, if disguised, you need to undisguise
9338 //to correctly calculate new job sprite without
9339 if (sd->disguise)
9340 pc_disguise(sd, 0);
9341
9342 status_set_viewdata(&sd->bl, job);
9343 clif_changelook(&sd->bl,LOOK_BASE,sd->vd.class_); // move sprite update to prevent client crashes with incompatible equipment [Valaris]
9344 if(sd->vd.cloth_color)
9345 clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
9346
9347 //Update skill tree.
9348 pc_calc_skilltree(sd);
9349 clif_skillinfoblock(sd);
9350
9351 if (sd->ed)
9352 elemental_delete(sd->ed, 0);
9353 if (sd->state.vending)
9354 vending_closevending(sd);
9355
9356 map_foreachinmap(jobchange_killclone, sd->bl.m, BL_MOB, sd->bl.id);
9357
9358 //Remove peco/cart/falcon
9359 i = sd->sc.option;
9360 if( i&OPTION_RIDING && !pc_checkskill(sd, KN_RIDING) )
9361 i&=~OPTION_RIDING;
9362 if( i&OPTION_FALCON && !pc_checkskill(sd, HT_FALCON) )
9363 i&=~OPTION_FALCON;
9364 if( i&OPTION_DRAGON && !pc_checkskill(sd,RK_DRAGONTRAINING) )
9365 i&=~OPTION_DRAGON;
9366 if( i&OPTION_WUGRIDER && !pc_checkskill(sd,RA_WUGMASTERY) )
9367 i&=~OPTION_WUGRIDER;
9368 if( i&OPTION_WUG && !pc_checkskill(sd,RA_WUGMASTERY) )
9369 i&=~OPTION_WUG;
9370 if( i&OPTION_MADOGEAR ) //You do not need a skill for this.
9371 i&=~OPTION_MADOGEAR;
9372#ifndef NEW_CARTS
9373 if( i&OPTION_CART && !pc_checkskill(sd, MC_PUSHCART) )
9374 i&=~OPTION_CART;
9375#else
9376 if( sd->sc.data[SC_PUSH_CART] && !pc_checkskill(sd, MC_PUSHCART) )
9377 pc_setcart(sd, 0);
9378#endif
9379 if(i != sd->sc.option)
9380 pc_setoption(sd, i);
9381
9382 if(merc_is_hom_active(sd->hd) && !pc_checkskill(sd, AM_CALLHOMUN))
9383 merc_hom_vaporize(sd, HOM_ST_ACTIVE);
9384
9385 if(sd->status.manner < 0)
9386 clif_changestatus(sd,SP_MANNER,sd->status.manner);
9387
9388 status_calc_pc(sd,0);
9389 pc_checkallowskill(sd);
9390 pc_equiplookall(sd);
9391
9392 //if you were previously famous, not anymore.
9393 if (fame_flag) {
9394 chrif_save(sd,0);
9395 chrif_buildfamelist();
9396 } else if (sd->status.fame > 0) {
9397 //It may be that now they are famous?
9398 switch (sd->class_&MAPID_UPPERMASK) {
9399 case MAPID_BLACKSMITH:
9400 case MAPID_ALCHEMIST:
9401 case MAPID_TAEKWON:
9402 chrif_save(sd,0);
9403 chrif_buildfamelist();
9404 break;
9405 }
9406 }
9407
9408 return 0;
9409}
9410
9411/*==========================================
9412 * Tell client player sd has change equipement
9413 *------------------------------------------*/
9414void pc_equiplookall(struct map_session_data *sd)
9415{
9416 nullpo_retv(sd);
9417
9418 clif_changelook(&sd->bl,LOOK_WEAPON,0);
9419 clif_changelook(&sd->bl,LOOK_SHOES,0);
9420 clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
9421 clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
9422 clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
9423 clif_changelook(&sd->bl,LOOK_ROBE, sd->status.robe);
9424}
9425
9426/*==========================================
9427 * Tell client player sd has change look (hair,equip...)
9428 *------------------------------------------*/
9429void pc_changelook(struct map_session_data *sd,int type,int val)
9430{
9431 nullpo_retv(sd);
9432
9433 switch(type){
9434 case LOOK_HAIR: //Use the battle_config limits! [Skotlex]
9435 val = cap_value(val, MIN_HAIR_STYLE, MAX_HAIR_STYLE);
9436
9437 if (sd->status.hair != val)
9438 {
9439 sd->status.hair=val;
9440 if (sd->status.guild_id) //Update Guild Window. [Skotlex]
9441 intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id,
9442 GMI_HAIR,&sd->status.hair,sizeof(sd->status.hair));
9443 }
9444 break;
9445 case LOOK_WEAPON:
9446 sd->status.weapon=val;
9447 break;
9448 case LOOK_HEAD_BOTTOM:
9449 sd->status.head_bottom=val;
9450 break;
9451 case LOOK_HEAD_TOP:
9452 sd->status.head_top=val;
9453 break;
9454 case LOOK_HEAD_MID:
9455 sd->status.head_mid=val;
9456 break;
9457 case LOOK_HAIR_COLOR: //Use the battle_config limits! [Skotlex]
9458 val = cap_value(val, MIN_HAIR_COLOR, MAX_HAIR_COLOR);
9459
9460 if (sd->status.hair_color != val) {
9461 sd->status.hair_color=val;
9462 if (sd->status.guild_id) //Update Guild Window. [Skotlex]
9463 intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id,
9464 GMI_HAIR_COLOR,&sd->status.hair_color,sizeof(sd->status.hair_color));
9465 }
9466 break;
9467 case LOOK_CLOTHES_COLOR: //Use the battle_config limits! [Skotlex]
9468 val = cap_value(val, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
9469
9470 sd->status.clothes_color=val;
9471 break;
9472 case LOOK_SHIELD:
9473 sd->status.shield=val;
9474 break;
9475 case LOOK_SHOES:
9476 break;
9477 case LOOK_ROBE:
9478 sd->status.robe = val;
9479 break;
9480 }
9481 clif_changelook(&sd->bl,type,val);
9482}
9483
9484/*==========================================
9485 * Give an option (type) to player (sd) and display it to client
9486 *------------------------------------------*/
9487void pc_setoption(struct map_session_data *sd,int type)
9488{
9489 int p_type, new_look=0;
9490 nullpo_retv(sd);
9491 p_type = sd->sc.option;
9492
9493 //Option has to be changed client-side before the class sprite or it won't always work (eg: Wedding sprite) [Skotlex]
9494 sd->sc.option=type;
9495 clif_changeoption(&sd->bl);
9496
9497 if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) )
9498 { // Mounting
9499 clif_status_load(&sd->bl,SI_RIDING,1);
9500 status_calc_pc(sd,0);
9501 }
9502 else if( (!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) )
9503 { // Dismount
9504 clif_status_load(&sd->bl,SI_RIDING,0);
9505 status_calc_pc(sd,0);
9506 }
9507
9508#ifndef NEW_CARTS
9509 if( type&OPTION_CART && !( p_type&OPTION_CART ) ) { //Cart On
9510 clif_cartlist(sd);
9511 clif_updatestatus(sd, SP_CARTINFO);
9512 if(pc_checkskill(sd, MC_PUSHCART) < 10)
9513 status_calc_pc(sd,0); //Apply speed penalty.
9514 } else if( !( type&OPTION_CART ) && p_type&OPTION_CART ){ //Cart Off
9515 clif_clearcart(sd->fd);
9516 if(pc_checkskill(sd, MC_PUSHCART) < 10)
9517 status_calc_pc(sd,0); //Remove speed penalty.
9518 }
9519#endif
9520
9521 if (type&OPTION_FALCON && !(p_type&OPTION_FALCON)) //Falcon ON
9522 clif_status_load(&sd->bl,SI_FALCON,1);
9523 else if (!(type&OPTION_FALCON) && p_type&OPTION_FALCON) //Falcon OFF
9524 clif_status_load(&sd->bl,SI_FALCON,0);
9525
9526 if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) {
9527 if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting
9528 clif_status_load(&sd->bl,SI_WUGRIDER,1);
9529 status_calc_pc(sd,0);
9530 } else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount
9531 clif_status_load(&sd->bl,SI_WUGRIDER,0);
9532 status_calc_pc(sd,0);
9533 }
9534 }
9535 if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) {
9536 if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) ) {
9537 status_calc_pc(sd, 0);
9538 status_change_end(&sd->bl,SC_MAXIMIZEPOWER,INVALID_TIMER);
9539 status_change_end(&sd->bl,SC_OVERTHRUST,INVALID_TIMER);
9540 status_change_end(&sd->bl,SC_WEAPONPERFECTION,INVALID_TIMER);
9541 status_change_end(&sd->bl,SC_ADRENALINE,INVALID_TIMER);
9542 status_change_end(&sd->bl,SC_CARTBOOST,INVALID_TIMER);
9543 status_change_end(&sd->bl,SC_MELTDOWN,INVALID_TIMER);
9544 status_change_end(&sd->bl,SC_MAXOVERTHRUST,INVALID_TIMER);
9545 } else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR ) {
9546 status_calc_pc(sd, 0);
9547 status_change_end(&sd->bl,SC_SHAPESHIFT,INVALID_TIMER);
9548 status_change_end(&sd->bl,SC_HOVERING,INVALID_TIMER);
9549 status_change_end(&sd->bl,SC_ACCELERATION,INVALID_TIMER);
9550 status_change_end(&sd->bl,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER);
9551 status_change_end(&sd->bl,SC_OVERHEAT,INVALID_TIMER);
9552 }
9553 }
9554
9555 if (type&OPTION_FLYING && !(p_type&OPTION_FLYING))
9556 new_look = JOB_STAR_GLADIATOR2;
9557 else if (!(type&OPTION_FLYING) && p_type&OPTION_FLYING)
9558 new_look = -1;
9559
9560 if (type&OPTION_WEDDING && !(p_type&OPTION_WEDDING))
9561 new_look = JOB_WEDDING;
9562 else if (!(type&OPTION_WEDDING) && p_type&OPTION_WEDDING)
9563 new_look = -1;
9564
9565 if (type&OPTION_XMAS && !(p_type&OPTION_XMAS))
9566 new_look = JOB_XMAS;
9567 else if (!(type&OPTION_XMAS) && p_type&OPTION_XMAS)
9568 new_look = -1;
9569
9570 if (type&OPTION_SUMMER && !(p_type&OPTION_SUMMER))
9571 new_look = JOB_SUMMER;
9572 else if (!(type&OPTION_SUMMER) && p_type&OPTION_SUMMER)
9573 new_look = -1;
9574
9575 if (type&OPTION_HANBOK && !(p_type&OPTION_HANBOK))
9576 new_look = JOB_HANBOK;
9577 else if (!(type&OPTION_HANBOK) && p_type&OPTION_HANBOK)
9578 new_look = -1;
9579
9580 if (type&OPTION_OKTOBERFEST && !(p_type&OPTION_OKTOBERFEST))
9581 new_look = JOB_OKTOBERFEST;
9582 else if (!(type&OPTION_OKTOBERFEST) && p_type&OPTION_OKTOBERFEST)
9583 new_look = -1;
9584
9585 if (sd->disguise || !new_look)
9586 return; //Disguises break sprite changes
9587
9588 if (new_look < 0) { //Restore normal look.
9589 status_set_viewdata(&sd->bl, sd->status.class_);
9590 new_look = sd->vd.class_;
9591 }
9592
9593 pc_stop_attack(sd); //Stop attacking on new view change (to prevent wedding/santa attacks.
9594 clif_changelook(&sd->bl,LOOK_BASE,new_look);
9595 if (sd->vd.cloth_color)
9596 clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
9597 clif_skillinfoblock(sd); // Skill list needs to be updated after base change.
9598}
9599
9600/*==========================================
9601 * Give player a cart
9602 *------------------------------------------*/
9603bool pc_setcart(struct map_session_data *sd,int type) {
9604#ifndef NEW_CARTS
9605 int cart[6] = {0x0000,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5};
9606 int option;
9607#endif
9608 nullpo_retr(false,sd);
9609
9610 if( type < 0 || type > MAX_CARTS )
9611 return false;// Never trust the values sent by the client! [Skotlex]
9612
9613 if( pc_checkskill(sd,MC_PUSHCART) <= 0 && type != 0 )
9614 return false;// Push cart is required
9615
9616#ifdef NEW_CARTS
9617
9618 switch( type ) {
9619 case 0:
9620 if( !sd->sc.data[SC_PUSH_CART] )
9621 return 0;
9622 status_change_end(&sd->bl,SC_PUSH_CART,INVALID_TIMER);
9623 clif_clearcart(sd->fd);
9624 break;
9625 default:/* everything else is an allowed ID so we can move on */
9626 if( !sd->sc.data[SC_PUSH_CART] ) /* first time, so fill cart data */
9627 clif_cartlist(sd);
9628 clif_updatestatus(sd, SP_CARTINFO);
9629 sc_start(&sd->bl,&sd->bl, SC_PUSH_CART, 100, type, 0);
9630 clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2 , type, 0, 0);
9631 if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */
9632 sd->sc.data[SC_PUSH_CART]->val1 = type;
9633 break;
9634 }
9635
9636 if(pc_checkskill(sd, MC_PUSHCART) < 10)
9637 status_calc_pc(sd,0); //Recalc speed penalty.
9638#else
9639 // Update option
9640 option = sd->sc.option;
9641 option &= ~OPTION_CART;// clear cart bits
9642 option |= cart[type]; // set cart
9643 pc_setoption(sd, option);
9644#endif
9645
9646 return true;
9647}
9648
9649/*==========================================
9650 * Give player a falcon
9651 *------------------------------------------*/
9652void pc_setfalcon(TBL_PC* sd, int flag)
9653{
9654 if( flag ){
9655 if( pc_checkskill(sd,HT_FALCON)>0 ) // add falcon if he have the skill
9656 pc_setoption(sd,sd->sc.option|OPTION_FALCON);
9657 } else if( pc_isfalcon(sd) ){
9658 pc_setoption(sd,sd->sc.option&~OPTION_FALCON); // remove falcon
9659 }
9660}
9661
9662/*==========================================
9663 * Set player riding
9664 *------------------------------------------*/
9665void pc_setriding(TBL_PC* sd, int flag)
9666{
9667 if( &sd->sc && sd->sc.data[SC_ALL_RIDING] )
9668 return;
9669
9670 if( flag ){
9671 if( pc_checkskill(sd,KN_RIDING) > 0 ) // add peco
9672 pc_setoption(sd, sd->sc.option|OPTION_RIDING);
9673 } else if( pc_isriding(sd) ){
9674 pc_setoption(sd, sd->sc.option&~OPTION_RIDING);
9675 }
9676}
9677
9678/*==========================================
9679 * Give player a mado
9680 *------------------------------------------*/
9681void pc_setmadogear(TBL_PC* sd, int flag)
9682{
9683 if( flag ){
9684 if( pc_checkskill(sd,NC_MADOLICENCE) > 0 )
9685 pc_setoption(sd, sd->sc.option|OPTION_MADOGEAR);
9686 } else if( pc_ismadogear(sd) ){
9687 pc_setoption(sd, sd->sc.option&~OPTION_MADOGEAR);
9688 }
9689}
9690
9691/*==========================================
9692 * Check if player can drop an item
9693 *------------------------------------------*/
9694bool pc_candrop(struct map_session_data *sd, struct item *item)
9695{
9696 if( item && (item->expire_time || (item->bound && !pc_can_give_bounded_items(sd))) )
9697 return false;
9698 if( !pc_can_give_items(sd) || sd->sc.cant.drop) //check if this GM level can drop items
9699 return false;
9700 return (itemdb_isdropable(item, pc_get_group_level(sd)));
9701}
9702
9703/*==========================================
9704 * Read ram register for player sd
9705 * get val (int) from reg for player sd
9706 *------------------------------------------*/
9707int pc_readreg(struct map_session_data* sd, int reg)
9708{
9709 int i;
9710
9711 nullpo_ret(sd);
9712
9713 ARR_FIND( 0, sd->reg_num, i, sd->reg[i].index == reg );
9714 return ( i < sd->reg_num ) ? sd->reg[i].data : 0;
9715}
9716/*==========================================
9717 * Set ram register for player sd
9718 * memo val(int) at reg for player sd
9719 *------------------------------------------*/
9720bool pc_setreg(struct map_session_data* sd, int reg, int val)
9721{
9722 int i;
9723
9724 nullpo_retr(false,sd);
9725
9726 ARR_FIND( 0, sd->reg_num, i, sd->reg[i].index == reg );
9727 if( i < sd->reg_num )
9728 {// overwrite existing entry
9729 sd->reg[i].data = val;
9730 return true;
9731 }
9732
9733 ARR_FIND( 0, sd->reg_num, i, sd->reg[i].data == 0 );
9734 if( i == sd->reg_num )
9735 {// nothing free, increase size
9736 sd->reg_num++;
9737 RECREATE(sd->reg, struct script_reg, sd->reg_num);
9738 }
9739 sd->reg[i].index = reg;
9740 sd->reg[i].data = val;
9741
9742 return true;
9743}
9744
9745/*==========================================
9746 * Read ram register for player sd
9747 * get val (str) from reg for player sd
9748 *------------------------------------------*/
9749char* pc_readregstr(struct map_session_data* sd, int reg)
9750{
9751 int i;
9752
9753 nullpo_ret(sd);
9754
9755 ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].index == reg );
9756 return ( i < sd->regstr_num ) ? sd->regstr[i].data : NULL;
9757}
9758/*==========================================
9759 * Set ram register for player sd
9760 * memo val(str) at reg for player sd
9761 *------------------------------------------*/
9762bool pc_setregstr(struct map_session_data* sd, int reg, const char* str)
9763{
9764 int i;
9765
9766 nullpo_retr(false,sd);
9767
9768 ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].index == reg );
9769 if( i < sd->regstr_num )
9770 {// found entry, update
9771 if( str == NULL || *str == '\0' )
9772 {// empty string
9773 if( sd->regstr[i].data != NULL )
9774 aFree(sd->regstr[i].data);
9775 sd->regstr[i].data = NULL;
9776 }
9777 else if( sd->regstr[i].data )
9778 {// recreate
9779 size_t len = strlen(str)+1;
9780 RECREATE(sd->regstr[i].data, char, len);
9781 memcpy(sd->regstr[i].data, str, len*sizeof(char));
9782 }
9783 else
9784 {// create
9785 sd->regstr[i].data = aStrdup(str);
9786 }
9787 return true;
9788 }
9789
9790 if( str == NULL || *str == '\0' )
9791 return true;// nothing to add, empty string
9792
9793 ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].data == NULL );
9794 if( i == sd->regstr_num )
9795 {// nothing free, increase size
9796 sd->regstr_num++;
9797 RECREATE(sd->regstr, struct script_regstr, sd->regstr_num);
9798 }
9799 sd->regstr[i].index = reg;
9800 sd->regstr[i].data = aStrdup(str);
9801
9802 return true;
9803}
9804
9805int pc_readregistry(struct map_session_data *sd,const char *reg,int type)
9806{
9807 struct global_reg *sd_reg;
9808 int i,max;
9809
9810 nullpo_ret(sd);
9811 switch (type) {
9812 case 3: //Char reg
9813 sd_reg = sd->save_reg.global;
9814 max = sd->save_reg.global_num;
9815 break;
9816 case 2: //Account reg
9817 sd_reg = sd->save_reg.account;
9818 max = sd->save_reg.account_num;
9819 break;
9820 case 1: //Account2 reg
9821 sd_reg = sd->save_reg.account2;
9822 max = sd->save_reg.account2_num;
9823 break;
9824 default:
9825 return 0;
9826 }
9827 if (max == -1) {
9828 ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type);
9829 //This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again.
9830 intif_request_registry(sd,type==3?4:type);
9831 return 0;
9832 }
9833
9834 ARR_FIND( 0, max, i, strcmp(sd_reg[i].str,reg) == 0 );
9835 return ( i < max ) ? atoi(sd_reg[i].value) : 0;
9836}
9837
9838char* pc_readregistry_str(struct map_session_data *sd,const char *reg,int type)
9839{
9840 struct global_reg *sd_reg;
9841 int i,max;
9842
9843 nullpo_ret(sd);
9844 switch (type) {
9845 case 3: //Char reg
9846 sd_reg = sd->save_reg.global;
9847 max = sd->save_reg.global_num;
9848 break;
9849 case 2: //Account reg
9850 sd_reg = sd->save_reg.account;
9851 max = sd->save_reg.account_num;
9852 break;
9853 case 1: //Account2 reg
9854 sd_reg = sd->save_reg.account2;
9855 max = sd->save_reg.account2_num;
9856 break;
9857 default:
9858 return NULL;
9859 }
9860 if (max == -1) {
9861 ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type);
9862 //This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again.
9863 intif_request_registry(sd,type==3?4:type);
9864 return NULL;
9865 }
9866
9867 ARR_FIND( 0, max, i, strcmp(sd_reg[i].str,reg) == 0 );
9868 return ( i < max ) ? sd_reg[i].value : NULL;
9869}
9870
9871bool pc_setregistry(struct map_session_data *sd,const char *reg,int val,int type)
9872{
9873 struct global_reg *sd_reg;
9874 int i,*max, regmax;
9875
9876 nullpo_retr(false,sd);
9877
9878 switch( type )
9879 {
9880 case 3: //Char reg
9881 if( !strcmp(reg,"PC_DIE_COUNTER") && sd->die_counter != val )
9882 {
9883 i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
9884 sd->die_counter = val;
9885 if( i )
9886 status_calc_pc(sd,0); // Lost the bonus.
9887 }
9888 else if( !strcmp(reg,"COOK_MASTERY") && sd->cook_mastery != val )
9889 {
9890 val = cap_value(val, 0, 1999);
9891 sd->cook_mastery = val;
9892 }
9893 else if( !strcmp(reg,"Bat_Team") && sd->bg_team != val )
9894 {
9895 val = cap_value(val, 0, 2);
9896 sd->bg_team = val;
9897 }
9898
9899 sd_reg = sd->save_reg.global;
9900 max = &sd->save_reg.global_num;
9901 regmax = GLOBAL_REG_NUM;
9902 break;
9903 case 2: //Account reg
9904 if( !strcmp(reg,"#CASHPOINTS") && sd->cashPoints != val )
9905 {
9906 val = cap_value(val, 0, MAX_ZENY);
9907 sd->cashPoints = val;
9908 }
9909 else if( !strcmp(reg,"#KAFRAPOINTS") && sd->kafraPoints != val )
9910 {
9911 val = cap_value(val, 0, MAX_ZENY);
9912 sd->kafraPoints = val;
9913 }
9914 else if( !strcmp(reg,"#Premium_Tick") && sd->Premium_Tick != val )
9915 {
9916 sd->Premium_Tick = val; // Premium Account System
9917 pc_Premium_validate(sd);
9918 }
9919
9920 sd_reg = sd->save_reg.account;
9921 max = &sd->save_reg.account_num;
9922 regmax = ACCOUNT_REG_NUM;
9923 break;
9924 case 1: //Account2 reg
9925 sd_reg = sd->save_reg.account2;
9926 max = &sd->save_reg.account2_num;
9927 regmax = ACCOUNT_REG2_NUM;
9928 break;
9929 default:
9930 return false;
9931 }
9932 if (*max == -1) {
9933 ShowError("pc_setregistry : refusing to set %s (type %d) until vars are received.\n", reg, type);
9934 return true;
9935 }
9936
9937 // delete reg
9938 if (val == 0) {
9939 ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
9940 if( i < *max )
9941 {
9942 if (i != *max - 1)
9943 memcpy(&sd_reg[i], &sd_reg[*max - 1], sizeof(struct global_reg));
9944 memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg));
9945 (*max)--;
9946 sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
9947 }
9948 return true;
9949 }
9950 // change value if found
9951 ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
9952 if( i < *max )
9953 {
9954 safesnprintf(sd_reg[i].value, sizeof(sd_reg[i].value), "%d", val);
9955 sd->state.reg_dirty |= 1<<(type-1);
9956 return true;
9957 }
9958
9959 // add value if not found
9960 if (i < regmax) {
9961 memset(&sd_reg[i], 0, sizeof(struct global_reg));
9962 safestrncpy(sd_reg[i].str, reg, sizeof(sd_reg[i].str));
9963 safesnprintf(sd_reg[i].value, sizeof(sd_reg[i].value), "%d", val);
9964 (*max)++;
9965 sd->state.reg_dirty |= 1<<(type-1);
9966 return true;
9967 }
9968
9969 ShowError("pc_setregistry : couldn't set %s, limit of registries reached (%d)\n", reg, regmax);
9970
9971 return false;
9972}
9973
9974bool pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *val,int type)
9975{
9976 struct global_reg *sd_reg;
9977 int i,*max, regmax;
9978
9979 nullpo_retr(false,sd);
9980 if (reg[strlen(reg)-1] != '$') {
9981 ShowError("pc_setregistry_str : reg %s must be string (end in '$') to use this!\n", reg);
9982 return false;
9983 }
9984
9985 switch (type) {
9986 case 3: //Char reg
9987 sd_reg = sd->save_reg.global;
9988 max = &sd->save_reg.global_num;
9989 regmax = GLOBAL_REG_NUM;
9990 break;
9991 case 2: //Account reg
9992 sd_reg = sd->save_reg.account;
9993 max = &sd->save_reg.account_num;
9994 regmax = ACCOUNT_REG_NUM;
9995 break;
9996 case 1: //Account2 reg
9997 sd_reg = sd->save_reg.account2;
9998 max = &sd->save_reg.account2_num;
9999 regmax = ACCOUNT_REG2_NUM;
10000 break;
10001 default:
10002 return false;
10003 }
10004 if (*max == -1) {
10005 ShowError("pc_setregistry_str : refusing to set %s (type %d) until vars are received.\n", reg, type);
10006 return false;
10007 }
10008
10009 // delete reg
10010 if (!val || strcmp(val,"")==0)
10011 {
10012 ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
10013 if( i < *max )
10014 {
10015 if (i != *max - 1)
10016 memcpy(&sd_reg[i], &sd_reg[*max - 1], sizeof(struct global_reg));
10017 memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg));
10018 (*max)--;
10019 sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
10020 if (type!=3) intif_saveregistry(sd,type);
10021 }
10022 return true;
10023 }
10024
10025 // change value if found
10026 ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
10027 if( i < *max )
10028 {
10029 safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value));
10030 sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
10031 if (type!=3) intif_saveregistry(sd,type);
10032 return true;
10033 }
10034
10035 // add value if not found
10036 if (i < regmax) {
10037 memset(&sd_reg[i], 0, sizeof(struct global_reg));
10038 safestrncpy(sd_reg[i].str, reg, sizeof(sd_reg[i].str));
10039 safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value));
10040 (*max)++;
10041 sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
10042 if (type!=3) intif_saveregistry(sd,type);
10043 return true;
10044 }
10045
10046 ShowError("pc_setregistry : couldn't set %s, limit of registries reached (%d)\n", reg, regmax);
10047 return false;
10048}
10049
10050/*==========================================
10051 * Exec eventtimer for player sd (retrieved from map_session (id))
10052 *------------------------------------------*/
10053static int pc_eventtimer(int tid, unsigned int tick, int id, intptr_t data)
10054{
10055 struct map_session_data *sd=map_id2sd(id);
10056 char *p = (char *)data;
10057 int i;
10058 if(sd==NULL)
10059 return 0;
10060
10061 ARR_FIND( 0, MAX_EVENTTIMER, i, sd->eventtimer[i] == tid );
10062 if( i < MAX_EVENTTIMER )
10063 {
10064 sd->eventtimer[i] = INVALID_TIMER;
10065 sd->eventcount--;
10066 npc_event(sd,p,0);
10067 }
10068 else
10069 ShowError("pc_eventtimer: no such event timer\n");
10070
10071 if (p) aFree(p);
10072 return 0;
10073}
10074
10075/*==========================================
10076 * Add eventtimer for player sd ?
10077 *------------------------------------------*/
10078bool pc_addeventtimer(struct map_session_data *sd,int tick,const char *name)
10079{
10080 int i;
10081 nullpo_retr(false,sd);
10082
10083 ARR_FIND( 0, MAX_EVENTTIMER, i, sd->eventtimer[i] == INVALID_TIMER );
10084 if( i == MAX_EVENTTIMER )
10085 return false;
10086
10087 sd->eventtimer[i] = add_timer(gettick()+tick, pc_eventtimer, sd->bl.id, (intptr_t)aStrdup(name));
10088 sd->eventcount++;
10089
10090 return true;
10091}
10092
10093/*==========================================
10094 * Del eventtimer for player sd ?
10095 *------------------------------------------*/
10096bool pc_deleventtimer(struct map_session_data *sd,const char *name)
10097{
10098 char* p = NULL;
10099 int i;
10100
10101 nullpo_retr(false,sd);
10102 if (sd->eventcount == 0)
10103 return false;
10104
10105 // find the named event timer
10106 ARR_FIND( 0, MAX_EVENTTIMER, i,
10107 sd->eventtimer[i] != INVALID_TIMER &&
10108 (p = (char *)(get_timer(sd->eventtimer[i])->data)) != NULL &&
10109 strcmp(p, name) == 0
10110 );
10111 if( i == MAX_EVENTTIMER )
10112 return false; // not found
10113
10114 delete_timer(sd->eventtimer[i],pc_eventtimer);
10115 sd->eventtimer[i] = INVALID_TIMER;
10116 if(sd->eventcount > 0)
10117 sd->eventcount--;
10118 aFree(p);
10119
10120 return true;
10121}
10122
10123/*==========================================
10124 * Update eventtimer count for player sd
10125 *------------------------------------------*/
10126void pc_addeventtimercount(struct map_session_data *sd,const char *name,int tick)
10127{
10128 int i;
10129
10130 nullpo_retv(sd);
10131
10132 for(i=0;i<MAX_EVENTTIMER;i++)
10133 if( sd->eventtimer[i] != INVALID_TIMER && strcmp(
10134 (char *)(get_timer(sd->eventtimer[i])->data), name)==0 ){
10135 addtick_timer(sd->eventtimer[i],tick);
10136 break;
10137 }
10138}
10139
10140/*==========================================
10141 * Remove all eventtimer for player sd
10142 *------------------------------------------*/
10143void pc_cleareventtimer(struct map_session_data *sd)
10144{
10145 int i;
10146
10147 nullpo_retv(sd);
10148
10149 if (sd->eventcount == 0)
10150 return;
10151
10152 for(i=0;i<MAX_EVENTTIMER;i++){
10153 if( sd->eventtimer[i] != INVALID_TIMER ){
10154 char *p = (char *)(get_timer(sd->eventtimer[i])->data);
10155 delete_timer(sd->eventtimer[i],pc_eventtimer);
10156 sd->eventtimer[i] = INVALID_TIMER;
10157 if(sd->eventcount > 0) //avoid looping to max val
10158 sd->eventcount--;
10159 if (p) aFree(p);
10160 }
10161 }
10162}
10163
10164/**
10165* Called when an item with combo is worn
10166* @param *sd
10167* @param *data struct item_data
10168* @return success numbers of succeed combo
10169*/
10170static int pc_checkcombo(struct map_session_data *sd, struct item_data *data) {
10171 uint16 i;
10172 int success = 0;
10173 for( i = 0; i < data->combos_count; i++ ) {
10174 int16 *combo_idx = NULL, idx, j;
10175 /* ensure this isn't a duplicate combo */
10176 if( sd->combos.bonus != NULL ) {
10177 int x;
10178 ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id );
10179
10180 /* found a match, skip this combo */
10181 if( x < sd->combos.count )
10182 continue;
10183 }
10184
10185 CREATE(combo_idx,int16,data->combos[i]->count);
10186 memset(combo_idx,-1,data->combos[i]->count * sizeof(int16));
10187
10188 for( j = 0; j < data->combos[i]->count; j++ ) {
10189 uint16 id = data->combos[i]->nameid[j], k;
10190 bool found = false;
10191
10192 for( k = 0; k < EQI_MAX; k++ ) {
10193 bool do_continue = false; //used to continue that specific loop with some check that also use some loop
10194 int16 index;
10195 index = sd->equip_index[k];
10196 if( index < 0 ) continue;
10197 if( k == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index ) continue;
10198 if( k == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index ) continue;
10199 if( k == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index) ) continue;
10200
10201 if(!sd->inventory_data[index])
10202 continue;
10203 if(j>0){
10204 uint8 z;
10205 for (z = 0; z < data->combos[i]->count; z++)
10206 if(combo_idx[z] == index) //we already have that index recorded
10207 do_continue=true;
10208 if(do_continue)
10209 continue;
10210 }
10211
10212 if ( itemdb_type(id) != IT_CARD ) {
10213 if ( sd->inventory_data[index]->nameid != id )
10214 continue;
10215 combo_idx[j] = index;
10216 found = true;
10217 break;
10218 } else { //Cards
10219 uint16 z;
10220 if ( sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0]) )
10221 continue;
10222 for (z = 0; z < sd->inventory_data[index]->slot; z++) {
10223 if (sd->status.inventory[index].card[z] != id)
10224 continue;
10225 combo_idx[j] = index;
10226 found = true;
10227 break;
10228 }
10229 }
10230 }
10231 if( !found )
10232 break;/* we haven't found all the ids for this combo, so we can return */
10233 }
10234 aFree(combo_idx);
10235 /* means we broke out of the count loop w/o finding all ids, we can move to the next combo */
10236 if( j < data->combos[i]->count )
10237 continue;
10238 /* we got here, means all items in the combo are matching */
10239 idx = sd->combos.count;
10240 if( sd->combos.bonus == NULL ) {
10241 CREATE(sd->combos.bonus, struct script_code *, 1);
10242 CREATE(sd->combos.id, unsigned short, 1);
10243 sd->combos.count = 1;
10244 } else {
10245 RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count);
10246 RECREATE(sd->combos.id, unsigned short, sd->combos.count);
10247 }
10248 /* we simply copy the pointer */
10249 sd->combos.bonus[idx] = data->combos[i]->script;
10250 /* save this combo's id */
10251 sd->combos.id[idx] = data->combos[i]->id;
10252 success++;
10253 }
10254 return success;
10255}
10256
10257/**
10258* Called when an item with combo is removed
10259* @param *sd
10260* @param *data struct item_data
10261* @return retval numbers of removed combo
10262*/
10263static int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
10264 int i, retval = 0;
10265
10266 if( sd->combos.bonus == NULL )
10267 return 0;/* nothing to do here, player has no combos */
10268 for( i = 0; i < data->combos_count; i++ ) {
10269 /* check if this combo exists in this user */
10270 int x = 0, cursor = 0, j;
10271 ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id );
10272 /* no match, skip this combo */
10273 if( !(x < sd->combos.count) )
10274 continue;
10275
10276 sd->combos.bonus[x] = NULL;
10277 sd->combos.id[x] = 0;
10278 retval++;
10279
10280 /* check if combo requirements still fit */
10281 if( pc_checkcombo( sd, data ) )
10282 continue;
10283
10284 /* move next value to empty slot */
10285 for( j = 0, cursor = 0; j < sd->combos.count; j++ ) {
10286 if( sd->combos.bonus[j] == NULL )
10287 continue;
10288
10289 if( cursor != j ) {
10290 sd->combos.bonus[cursor] = sd->combos.bonus[j];
10291 sd->combos.id[cursor] = sd->combos.id[j];
10292 }
10293 cursor++;
10294 }
10295
10296 /* it's empty, we can clear all the memory */
10297 if( (sd->combos.count = cursor) == 0 ) {
10298 aFree(sd->combos.bonus);
10299 aFree(sd->combos.id);
10300 sd->combos.bonus = NULL;
10301 sd->combos.id = NULL;
10302 return retval; /* we also can return at this point for we have no more combos to check */
10303 }
10304 }
10305
10306 return retval;
10307}
10308
10309/**
10310* Load combo data(s) of player
10311* @param *sd
10312* @return ret numbers of succeed combo
10313*/
10314int pc_load_combo(struct map_session_data *sd) {
10315 int i, ret = 0;
10316 for( i = 0; i < EQI_MAX; i++ ) {
10317 struct item_data *id = NULL;
10318 int idx = sd->equip_index[i];
10319 if( sd->equip_index[i] < 0 || !(id = sd->inventory_data[idx] ) )
10320 continue;
10321 if( id->combos_count )
10322 ret += pc_checkcombo(sd,id);
10323 if(!itemdb_isspecial(sd->status.inventory[idx].card[0])) {
10324 struct item_data *data;
10325 int j;
10326 for( j = 0; j < id->slot; j++ ) {
10327 if (!sd->status.inventory[idx].card[j])
10328 continue;
10329 if ( ( data = itemdb_exists(sd->status.inventory[idx].card[j]) ) != NULL ) {
10330 if( data->combos_count )
10331 ret += pc_checkcombo(sd,data);
10332 }
10333 }
10334 }
10335 }
10336 return ret;
10337}
10338/*==========================================
10339 * Equip item on player sd at req_pos from inventory index n
10340 * return: false - fail; true - success
10341 *------------------------------------------*/
10342bool pc_equipitem(struct map_session_data *sd,int n,int req_pos)
10343{
10344 int i,pos,flag=0,iflag;
10345 struct item_data *id;
10346
10347 nullpo_retr(false,sd);
10348
10349 if( n < 0 || n >= MAX_INVENTORY ) {
10350 clif_equipitemack(sd,0,0,0);
10351 return false;
10352 }
10353
10354 if( sd->sc.count && (
10355 (sd->sc.data[SC_PYROCLASTIC] && sd->inventory_data[n]->type == IT_WEAPON) ||
10356 sd->sc.data[SC_BERSERK] ||
10357 sd->sc.data[SC_SATURDAYNIGHTFEVER]) )
10358 {
10359 clif_equipitemack(sd,0,0,0);
10360 return false;
10361 }
10362
10363 if( DIFF_TICK(sd->canequip_tick,gettick()) > 0 ) {
10364 clif_equipitemack(sd,n,0,0);
10365 return false;
10366 }
10367
10368 if (!(id = sd->inventory_data[n]))
10369 return false;
10370 pos = pc_equippoint(sd,n); //With a few exceptions, item should go in all specified slots.
10371
10372 if(battle_config.battle_log)
10373 ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos);
10374
10375 if(!pc_isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris]
10376 // FIXME: pc_isequip: equip level failure uses 2 instead of 0
10377 clif_equipitemack(sd,n,0,0); // fail
10378 return false;
10379 }
10380
10381 if(pos == EQP_ACC) { //Accesories should only go in one of the two,
10382 pos = req_pos&EQP_ACC;
10383 if (pos == EQP_ACC) //User specified both slots..
10384 pos = sd->equip_index[EQI_ACC_R] >= 0 ? EQP_ACC_L : EQP_ACC_R;
10385 }
10386
10387 if(pos == EQP_SHADOW_ACC) { // Shadow System
10388 pos = req_pos&EQP_SHADOW_ACC;
10389 if (pos == EQP_SHADOW_ACC)
10390 pos = sd->equip_index[EQI_SHADOW_ACC_L] >= 0 ? EQP_SHADOW_ACC_R : EQP_SHADOW_ACC_L;
10391 }
10392
10393 if(pos == EQP_ARMS && id->equip == EQP_HAND_R) { //Dual wield capable weapon.
10394 pos = (req_pos&EQP_ARMS);
10395 if (pos == EQP_ARMS) //User specified both slots, pick one for them.
10396 pos = sd->equip_index[EQI_HAND_R] >= 0 ? EQP_HAND_L : EQP_HAND_R;
10397 }
10398
10399 if (pos&EQP_HAND_R && battle_config.use_weapon_skill_range&BL_PC) {
10400 //Update skill-block range database when weapon range changes. [Skotlex]
10401 i = sd->equip_index[EQI_HAND_R];
10402 if (i < 0 || !sd->inventory_data[i]) //No data, or no weapon equipped
10403 flag = 1;
10404 else
10405 flag = id->range != sd->inventory_data[i]->range;
10406 }
10407
10408 for(i=0;i<EQI_MAX;i++) {
10409 if(pos & equip_pos[i]) {
10410 if(sd->equip_index[i] >= 0) //Slot taken, remove item from there.
10411 pc_unequipitem(sd,sd->equip_index[i],2);
10412
10413 sd->equip_index[i] = n;
10414 }
10415 }
10416
10417 if(pos==EQP_AMMO) {
10418 clif_arrowequip(sd,n);
10419 clif_arrow_fail(sd,3);
10420 }
10421 else
10422 clif_equipitemack(sd,n,pos,1);
10423
10424 sd->status.inventory[n].equip=pos;
10425 achievement_validate_item(sd,AT_ITEM_EQUIP,sd->status.inventory[n].nameid,1);
10426
10427 if(pos & EQP_HAND_R) {
10428 if(id)
10429 sd->weapontype1 = id->look;
10430 else
10431 sd->weapontype1 = 0;
10432 pc_calcweapontype(sd);
10433 clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
10434 }
10435 if(pos & EQP_HAND_L) {
10436 if(id) {
10437 if(id->type == IT_WEAPON) {
10438 sd->status.shield = 0;
10439 sd->weapontype2 = id->look;
10440 }
10441 else
10442 if(id->type == IT_ARMOR) {
10443 sd->status.shield = id->look;
10444 sd->weapontype2 = 0;
10445 }
10446 }
10447 else
10448 sd->status.shield = sd->weapontype2 = 0;
10449 pc_calcweapontype(sd);
10450 clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
10451 }
10452 //Added check to prevent sending the same look on multiple slots ->
10453 //causes client to redraw item on top of itself. (suggested by Lupus)
10454 if(pos & EQP_HEAD_LOW && pc_checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1) {
10455 if(id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID)))
10456 sd->status.head_bottom = id->look;
10457 else
10458 sd->status.head_bottom = 0;
10459 clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
10460 }
10461 if(pos & EQP_HEAD_TOP && pc_checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1) {
10462 if(id)
10463 sd->status.head_top = id->look;
10464 else
10465 sd->status.head_top = 0;
10466 clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
10467 }
10468 if(pos & EQP_HEAD_MID && pc_checkequip(sd,EQP_COSTUME_HEAD_MID) == -1) {
10469 if(id && !(pos&EQP_HEAD_TOP))
10470 sd->status.head_mid = id->look;
10471 else
10472 sd->status.head_mid = 0;
10473 clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
10474 }
10475 if(pos & EQP_COSTUME_HEAD_TOP) {
10476 if(id){
10477 sd->status.head_top = id->look;
10478 } else
10479 sd->status.head_top = 0;
10480 clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
10481 }
10482 if(pos & EQP_COSTUME_HEAD_MID) {
10483 if(id && !(pos&EQP_HEAD_TOP)){
10484 sd->status.head_mid = id->look;
10485 } else
10486 sd->status.head_mid = 0;
10487 clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
10488 }
10489 if(pos & EQP_COSTUME_HEAD_LOW) {
10490 if(id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID))){
10491 sd->status.head_bottom = id->look;
10492 } else
10493 sd->status.head_bottom = 0;
10494 clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
10495 }
10496 if(pos & EQP_SHOES)
10497 clif_changelook(&sd->bl,LOOK_SHOES,0);
10498 if(pos&EQP_GARMENT && pc_checkequip(sd,EQP_COSTUME_GARMENT) == -1) {
10499 sd->status.robe = id ? id->look : 0;
10500 clif_changelook(&sd->bl, LOOK_ROBE, sd->status.robe);
10501 }
10502 if(pos & EQP_COSTUME_GARMENT) {
10503 sd->status.robe = id ? id->look : 0;
10504 clif_changelook(&sd->bl,LOOK_ROBE,sd->status.robe);
10505 }
10506
10507 pc_checkallowskill(sd); //Check if status changes should be halted.
10508 iflag = sd->npc_item_flag;
10509
10510 /* check for combos (MUST be before status_calc_pc) */
10511 if( id->combos_count )
10512 pc_checkcombo(sd,id);
10513 if(itemdb_isspecial(sd->status.inventory[n].card[0]))
10514 ; //No cards
10515 else {
10516 for( i = 0; i < id->slot; i++ ) {
10517 struct item_data *data;
10518 if (!sd->status.inventory[n].card[i])
10519 continue;
10520 if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
10521 if( data->combos_count )
10522 pc_checkcombo(sd,data);
10523 }
10524 }
10525 }
10526
10527 status_calc_pc(sd,0);
10528 if (flag) //Update skill data
10529 clif_skillinfoblock(sd);
10530
10531 //OnEquip script [Skotlex]
10532 if (id) {
10533 //only run the script if item isn't restricted
10534 if (id->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(id,sd->bl.m)))
10535 run_script(id->equip_script,0,sd->bl.id,fake_nd->bl.id);
10536 if(itemdb_isspecial(sd->status.inventory[n].card[0]))
10537 ; //No cards
10538 else {
10539 for( i = 0; i < id->slot; i++ ) {
10540 struct item_data *data;
10541 if (!sd->status.inventory[n].card[i])
10542 continue;
10543 if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
10544 if (data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data,sd->bl.m)))
10545 run_script(data->equip_script,0,sd->bl.id,fake_nd->bl.id);
10546 }
10547 }
10548 }
10549 }
10550 sd->npc_item_flag = iflag;
10551
10552 return true;
10553}
10554
10555/*==========================================
10556 * Called when attemting to unequip an item from player
10557 * type:
10558 * 0 - only unequip
10559 * 1 - calculate status after unequipping
10560 * 2 - force unequip
10561 * return: false - fail; true - success
10562 *------------------------------------------*/
10563bool pc_unequipitem(struct map_session_data *sd,int n,int flag) {
10564 int i,iflag;
10565 bool status_cacl = false;
10566 nullpo_retr(false,sd);
10567
10568 if( n < 0 || n >= MAX_INVENTORY ) {
10569 clif_unequipitemack(sd,0,0,0);
10570 return false;
10571 }
10572
10573 // status change that makes player cannot unequip equipment
10574 if( !(flag&2) && sd->sc.count && (
10575 sd->sc.data[SC_BERSERK] ||
10576 sd->sc.data[SC_SATURDAYNIGHTFEVER] ||
10577 sd->sc.data[SC__BLOODYLUST] ||
10578 sd->sc.data[SC_KYOUGAKU] ||
10579 (sd->sc.data[SC_PYROCLASTIC] && sd->inventory_data[n]->type == IT_WEAPON)) ) // can't switch weapon
10580 {
10581 clif_unequipitemack(sd,n,0,0);
10582 return false;
10583 }
10584 if (&sd->sc) {
10585 if (sd->sc.data[SC_HEAT_BARREL])
10586 status_change_end(&sd->bl,SC_HEAT_BARREL,INVALID_TIMER);
10587 if (sd->sc.data[SC_P_ALTER] && (sd->inventory_data[n]->type == IT_WEAPON || sd->inventory_data[n]->type == IT_AMMO))
10588 status_change_end(&sd->bl,SC_P_ALTER,INVALID_TIMER);
10589 }
10590
10591 if(battle_config.battle_log)
10592 ShowInfo("unequip %d %x:%x\n",n,pc_equippoint(sd,n),sd->status.inventory[n].equip);
10593
10594 if(!sd->status.inventory[n].equip){ //Nothing to unequip
10595 clif_unequipitemack(sd,n,0,0);
10596 return false;
10597 }
10598 for(i=0;i<EQI_MAX;i++) {
10599 if(sd->status.inventory[n].equip & equip_pos[i])
10600 sd->equip_index[i] = -1;
10601 }
10602
10603 if(sd->status.inventory[n].equip & EQP_HAND_R) {
10604 sd->weapontype1 = 0;
10605 sd->status.weapon = sd->weapontype2;
10606 pc_calcweapontype(sd);
10607 clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
10608 if( !battle_config.dancing_weaponswitch_fix )
10609 status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); // Unequipping => stop dancing.
10610 }
10611 if(sd->status.inventory[n].equip & EQP_HAND_L) {
10612 sd->status.shield = sd->weapontype2 = 0;
10613 pc_calcweapontype(sd);
10614 clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
10615 }
10616 if(sd->status.inventory[n].equip & EQP_HEAD_LOW) {
10617 sd->status.head_bottom = ( pc_checkequip(sd,EQP_COSTUME_HEAD_LOW) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_COSTUME_HEAD_LOW)]->look : 0;
10618 clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
10619 }
10620 if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_LOW) {
10621 sd->status.head_bottom = ( pc_checkequip(sd,EQP_HEAD_LOW) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_LOW)]->look : 0;
10622 clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
10623 }
10624 if(sd->status.inventory[n].equip & EQP_HEAD_TOP) {
10625 sd->status.head_top = ( pc_checkequip(sd,EQP_COSTUME_HEAD_TOP) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_COSTUME_HEAD_TOP)]->look : 0;
10626 clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
10627 }
10628 if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_TOP) {
10629 sd->status.head_top = ( pc_checkequip(sd,EQP_HEAD_TOP) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_TOP)]->look : 0;
10630 clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
10631 }
10632 if(sd->status.inventory[n].equip & EQP_HEAD_MID) {
10633 sd->status.head_mid = ( pc_checkequip(sd,EQP_COSTUME_HEAD_MID) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_COSTUME_HEAD_MID)]->look : 0;
10634 clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
10635 }
10636 if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_MID) {
10637 sd->status.head_mid = ( pc_checkequip(sd,EQP_HEAD_MID) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_MID)]->look : 0;
10638 clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
10639 }
10640 if(sd->status.inventory[n].equip & EQP_SHOES)
10641 clif_changelook(&sd->bl,LOOK_SHOES,0);
10642
10643 if(sd->status.inventory[n].equip&EQP_GARMENT && pc_checkequip(sd,EQP_COSTUME_GARMENT) == -1) {
10644 sd->status.robe = 0;
10645 clif_changelook(&sd->bl, LOOK_ROBE, 0);
10646 }
10647
10648 if(sd->status.inventory[n].equip & EQP_COSTUME_GARMENT) {
10649 sd->status.robe = ( pc_checkequip(sd,EQP_GARMENT) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_GARMENT)]->look : 0;
10650 clif_changelook(&sd->bl,LOOK_ROBE,sd->status.robe);
10651 }
10652
10653 clif_unequipitemack(sd,n,sd->status.inventory[n].equip,1);
10654
10655 if((sd->status.inventory[n].equip & EQP_ARMS) &&
10656 sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!)
10657 skill_enchant_elemental_end(&sd->bl,-1);
10658
10659 if(sd->status.inventory[n].equip & EQP_ARMOR) {
10660 // On Armor Change...
10661 status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER);
10662 status_change_end(&sd->bl, SC_ARMOR_RESIST, INVALID_TIMER);
10663 }
10664
10665 if( sd->state.autobonus&sd->status.inventory[n].equip )
10666 sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish]
10667
10668 sd->status.inventory[n].equip=0;
10669 iflag = sd->npc_item_flag;
10670
10671 /* check for combos (MUST be before status_calc_pc) */
10672 if ( sd->inventory_data[n] ) {
10673 if( sd->inventory_data[n]->combos_count ) {
10674 if( pc_removecombo(sd,sd->inventory_data[n]) )
10675 status_cacl = true;
10676 } if(itemdb_isspecial(sd->status.inventory[n].card[0]))
10677 ; //No cards
10678 else {
10679 for( i = 0; i < sd->inventory_data[n]->slot; i++ ) {
10680 struct item_data *data;
10681 if (!sd->status.inventory[n].card[i])
10682 continue;
10683 if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
10684 if( data->combos_count ) {
10685 if( pc_removecombo(sd,data) )
10686 status_cacl = true;
10687 }
10688 }
10689 }
10690 }
10691 }
10692
10693 if(flag&1 || status_cacl) {
10694 pc_checkallowskill(sd);
10695 status_calc_pc(sd,0);
10696 }
10697
10698 if(sd->sc.data[SC_SIGNUMCRUCIS] && !battle_check_undead(sd->battle_status.race,sd->battle_status.def_ele))
10699 status_change_end(&sd->bl, SC_SIGNUMCRUCIS, INVALID_TIMER);
10700
10701 //OnUnEquip script [Skotlex]
10702 if (sd->inventory_data[n]) {
10703 if (sd->inventory_data[n]->unequip_script)
10704 run_script(sd->inventory_data[n]->unequip_script,0,sd->bl.id,fake_nd->bl.id);
10705 if(itemdb_isspecial(sd->status.inventory[n].card[0]))
10706 ; //No cards
10707 else {
10708 for( i = 0; i < sd->inventory_data[n]->slot; i++ ) {
10709 struct item_data *data;
10710 if (!sd->status.inventory[n].card[i])
10711 continue;
10712
10713 if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
10714 if( data->unequip_script )
10715 run_script(data->unequip_script,0,sd->bl.id,fake_nd->bl.id);
10716 }
10717
10718 }
10719 }
10720 }
10721 sd->npc_item_flag = iflag;
10722
10723 return true;
10724}
10725
10726/*==========================================
10727 * Checking if player (sd) has an invalid item
10728 * and is unequiped on map load (item_noequip)
10729 *------------------------------------------*/
10730void pc_checkitem(struct map_session_data *sd) {
10731 int i, calc_flag = 0;
10732 struct item it;
10733
10734 nullpo_retv(sd);
10735
10736 if( sd->state.vending ) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam)
10737 return;
10738
10739 for( i = 0; i < MAX_INVENTORY; i++ ) {
10740 it = sd->status.inventory[i];
10741
10742 if( it.nameid == 0 )
10743 continue;
10744 if( !it.equip )
10745 continue;
10746 if( it.equip&~pc_equippoint(sd,i) ) {
10747 pc_unequipitem(sd, i, 2);
10748 calc_flag = 1;
10749 continue;
10750 }
10751
10752 if( !pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT) && !battle_config.allow_equip_restricted_item && itemdb_isNoEquip(sd->inventory_data[i], sd->bl.m) ) {
10753 pc_unequipitem(sd, i, 2);
10754 calc_flag = 1;
10755 continue;
10756 }
10757 }
10758
10759 if( calc_flag && sd->state.active ) {
10760 pc_checkallowskill(sd);
10761 status_calc_pc(sd,0);
10762 }
10763
10764 return;
10765}
10766
10767/*==========================================
10768 * Checks for unavailable items and removes them.
10769 *------------------------------------------*/
10770void pc_check_available_item(struct map_session_data *sd) {
10771 int i, it;
10772 char output[256];
10773
10774 nullpo_retv(sd);
10775
10776 if( battle_config.item_check&1 ) { // Check for invalid(ated) items in inventory.
10777 for( i = 0; i < MAX_INVENTORY; i++ ) {
10778 it = sd->status.inventory[i].nameid;
10779
10780 if( it && !itemdb_available(it) ) {
10781 sprintf(output, msg_txt(sd, 709), it); // Item %d has been removed from your inventory.
10782 clif_displaymessage(sd->fd, output);
10783 ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", it, sd->status.inventory[i].amount, sd->status.char_id);
10784 pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER);
10785 }
10786 }
10787 }
10788
10789 if( battle_config.item_check&2 ) { // Check for invalid(ated) items in cart.
10790 for( i = 0; i < MAX_CART; i++ ) {
10791 it = sd->status.cart[i].nameid;
10792
10793 if( it && !itemdb_available(it) ) {
10794 sprintf(output, msg_txt(sd, 710), it); // Item %d has been removed from your cart.
10795 clif_displaymessage(sd->fd, output);
10796 ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", it, sd->status.cart[i].amount, sd->status.char_id);
10797 pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER);
10798 }
10799 }
10800 }
10801
10802 if( battle_config.item_check&4 ) { // Check for invalid(ated) items in storage.
10803 for( i = 0; i < sd->storage_size; i++ ) {
10804 it = sd->status.storage.items[i].nameid;
10805
10806 if( it && !itemdb_available(it) ) {
10807 sprintf(output, msg_txt(sd, 711), it); // Item %d has been removed from your storage.
10808 clif_displaymessage(sd->fd, output);
10809 ShowWarning("Removed invalid/disabled item id %d from storage (amount=%d, char_id=%d).\n", it, sd->status.storage.items[i].amount, sd->status.char_id);
10810 storage_delitem(sd, i, sd->status.storage.items[i].amount);
10811 }
10812 }
10813 }
10814}
10815
10816/*==========================================
10817 * Update PVP rank for sd1 in cmp to sd2
10818 *------------------------------------------*/
10819static int pc_calc_pvprank_sub(struct block_list *bl,va_list ap)
10820{
10821 struct map_session_data *sd1,*sd2;
10822
10823 sd1=(struct map_session_data *)bl;
10824 sd2=va_arg(ap,struct map_session_data *);
10825
10826 if( sd1->sc.option&OPTION_INVISIBLE || sd2->sc.option&OPTION_INVISIBLE )
10827 {// cannot register pvp rank for hidden GMs
10828 return 0;
10829 }
10830
10831 if( sd1->pvp_point > sd2->pvp_point )
10832 sd2->pvp_rank++;
10833 return 0;
10834}
10835/*==========================================
10836 * Calculate new rank beetween all present players (map_foreachinarea)
10837 * and display result
10838 *------------------------------------------*/
10839int pc_calc_pvprank(struct map_session_data *sd)
10840{
10841 int old = sd->pvp_rank;
10842 struct map_data *m = &map[sd->bl.m];
10843
10844 sd->pvp_rank=1;
10845 map_foreachinmap(pc_calc_pvprank_sub,sd->bl.m,BL_PC,sd);
10846 if(old!=sd->pvp_rank || sd->pvp_lastusers!=m->users_pvp)
10847 clif_pvpset(sd,sd->pvp_rank,sd->pvp_lastusers=m->users_pvp,0);
10848 return sd->pvp_rank;
10849}
10850/*==========================================
10851 * Calculate next sd ranking calculation from config
10852 *------------------------------------------*/
10853int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data)
10854{
10855 struct map_session_data *sd;
10856
10857 sd=map_id2sd(id);
10858 if(sd==NULL)
10859 return 0;
10860 sd->pvp_timer = INVALID_TIMER;
10861
10862 if( sd->sc.option&OPTION_INVISIBLE )
10863 {// do not calculate the pvp rank for a hidden GM
10864 return 0;
10865 }
10866
10867 if( pc_calc_pvprank(sd) > 0 )
10868 sd->pvp_timer = add_timer(gettick()+PVP_CALCRANK_INTERVAL,pc_calc_pvprank_timer,id,data);
10869 return 0;
10870}
10871
10872/*==========================================
10873 * Checking if sd is married
10874 * Return:
10875 * partner_id = yes
10876 * 0 = no
10877 *------------------------------------------*/
10878int pc_ismarried(struct map_session_data *sd)
10879{
10880 if(sd == NULL)
10881 return -1;
10882 if(sd->status.partner_id > 0)
10883 return sd->status.partner_id;
10884 else
10885 return 0;
10886}
10887/*==========================================
10888 * Marry player sd to player dstsd
10889 * Return:
10890 * false = fail
10891 * true = success
10892 *------------------------------------------*/
10893bool pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd)
10894{
10895 if(sd == NULL || dstsd == NULL ||
10896 sd->status.partner_id > 0 || dstsd->status.partner_id > 0 ||
10897 (sd->class_&JOBL_BABY) || (dstsd->class_&JOBL_BABY))
10898 return false;
10899 sd->status.partner_id = dstsd->status.char_id;
10900 dstsd->status.partner_id = sd->status.char_id;
10901 return true;
10902}
10903
10904/*==========================================
10905 * Divorce sd from its partner
10906 * Return:
10907 * false = fail
10908 * true = success
10909 *------------------------------------------*/
10910bool pc_divorce(struct map_session_data *sd)
10911{
10912 struct map_session_data *p_sd;
10913 int i;
10914
10915 if( sd == NULL || !pc_ismarried(sd) )
10916 return false;
10917
10918 if( !sd->status.partner_id )
10919 return false; // Char is not married
10920
10921 if( (p_sd = map_charid2sd(sd->status.partner_id)) == NULL )
10922 { // Lets char server do the divorce
10923 if( chrif_divorce(sd->status.char_id, sd->status.partner_id) )
10924 return false; // No char server connected
10925
10926 return true;
10927 }
10928
10929 // Both players online, lets do the divorce manually
10930 sd->status.partner_id = 0;
10931 p_sd->status.partner_id = 0;
10932 for( i = 0; i < MAX_INVENTORY; i++ )
10933 {
10934 if( sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F )
10935 pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER);
10936 if( p_sd->status.inventory[i].nameid == WEDDING_RING_M || p_sd->status.inventory[i].nameid == WEDDING_RING_F )
10937 pc_delitem(p_sd, i, 1, 0, 0, LOG_TYPE_OTHER);
10938 }
10939
10940 clif_divorced(sd, p_sd->status.name);
10941 clif_divorced(p_sd, sd->status.name);
10942
10943 return true;
10944}
10945
10946/**
10947 * Get the partner map_session_data of a player
10948 * @param sd : the husband|wife session
10949 * @return partner session or NULL
10950 */
10951struct map_session_data *pc_get_partner(struct map_session_data *sd){
10952 if (!sd || !pc_ismarried(sd))
10953 return NULL;
10954 return map_charid2sd(sd->status.partner_id);
10955}
10956
10957/**
10958 * Get the father map_session_data of a player
10959 * @param sd : the baby session
10960 * @return father session or NULL
10961 */
10962struct map_session_data *pc_get_father (struct map_session_data *sd){
10963 if (!sd || !(sd->class_&JOBL_BABY) || !sd->status.father)
10964 return NULL;
10965 return map_charid2sd(sd->status.father);
10966}
10967
10968/**
10969 * Get the mother map_session_data of a player
10970 * @param sd : the baby session
10971 * @return mother session or NULL
10972 */
10973struct map_session_data *pc_get_mother (struct map_session_data *sd){
10974 if (!sd || !(sd->class_&JOBL_BABY) || !sd->status.mother)
10975 return NULL;
10976 return map_charid2sd(sd->status.mother);
10977}
10978
10979/*==========================================
10980 * Get sd children charid. (Need to be married)
10981 *------------------------------------------*/
10982struct map_session_data *pc_get_child (struct map_session_data *sd)
10983{
10984 if (!sd || !pc_ismarried(sd) || !sd->status.child)
10985 // charid2sd returns NULL if not found
10986 return NULL;
10987 return map_charid2sd(sd->status.child);
10988}
10989
10990/*==========================================
10991 * Set player sd to bleed. (losing hp and/or sp each diff_tick)
10992 *------------------------------------------*/
10993void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick)
10994{
10995 int hp = 0, sp = 0;
10996
10997 if( pc_isdead(sd) )
10998 return;
10999
11000 if (sd->hp_loss.value) {
11001 sd->hp_loss.tick += diff_tick;
11002 while (sd->hp_loss.tick >= sd->hp_loss.rate) {
11003 hp += sd->hp_loss.value;
11004 sd->hp_loss.tick -= sd->hp_loss.rate;
11005 }
11006 if(hp >= sd->battle_status.hp)
11007 hp = sd->battle_status.hp-1; //Script drains cannot kill you.
11008 }
11009
11010 if (sd->sp_loss.value) {
11011 sd->sp_loss.tick += diff_tick;
11012 while (sd->sp_loss.tick >= sd->sp_loss.rate) {
11013 sp += sd->sp_loss.value;
11014 sd->sp_loss.tick -= sd->sp_loss.rate;
11015 }
11016 }
11017
11018 if (hp > 0 || sp > 0)
11019 status_zap(&sd->bl, hp, sp);
11020}
11021
11022//Character regen. Flag is used to know which types of regen can take place.
11023//&1: HP regen
11024//&2: SP regen
11025void pc_regen (struct map_session_data *sd, unsigned int diff_tick)
11026{
11027 int hp = 0, sp = 0;
11028
11029 if (sd->hp_regen.value) {
11030 sd->hp_regen.tick += diff_tick;
11031 while (sd->hp_regen.tick >= sd->hp_regen.rate) {
11032 hp += sd->hp_regen.value;
11033 sd->hp_regen.tick -= sd->hp_regen.rate;
11034 }
11035 }
11036
11037 if (sd->sp_regen.value) {
11038 sd->sp_regen.tick += diff_tick;
11039 while (sd->sp_regen.tick >= sd->sp_regen.rate) {
11040 sp += sd->sp_regen.value;
11041 sd->sp_regen.tick -= sd->sp_regen.rate;
11042 }
11043 }
11044
11045 if (hp > 0 || sp > 0)
11046 status_heal(&sd->bl, hp, sp, 0);
11047}
11048
11049/*==========================================
11050 * Memo player sd savepoint. (map,x,y)
11051 *------------------------------------------*/
11052void pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y)
11053{
11054 nullpo_retv(sd);
11055
11056 sd->status.save_point.map = mapindex;
11057 sd->status.save_point.x = x;
11058 sd->status.save_point.y = y;
11059}
11060
11061/*==========================================
11062 * Save 1 player data at autosave intervalle
11063 *------------------------------------------*/
11064static int pc_autosave(int tid, unsigned int tick, int id, intptr_t data)
11065{
11066 int interval;
11067 struct s_mapiterator* iter;
11068 struct map_session_data* sd;
11069 static int last_save_id = 0, save_flag = 0;
11070
11071 if(save_flag == 2) //Someone was saved on last call, normal cycle
11072 save_flag = 0;
11073 else
11074 save_flag = 1; //Noone was saved, so save first found char.
11075
11076 iter = mapit_getallusers();
11077 for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
11078 {
11079 if(sd->bl.id == last_save_id && save_flag != 1) {
11080 save_flag = 1;
11081 continue;
11082 }
11083
11084 if(save_flag != 1) //Not our turn to save yet.
11085 continue;
11086
11087 //Save char.
11088 last_save_id = sd->bl.id;
11089 save_flag = 2;
11090#ifdef VIP_ENABLE
11091 if(sd->vip.enabled) //check if we're still vip
11092 chrif_req_login_operation(1, sd->status.name, 6, 0, 1, 0);
11093#endif
11094 chrif_save(sd,0);
11095 break;
11096 }
11097 mapit_free(iter);
11098
11099 interval = autosave_interval/(map_usercount()+1);
11100 if(interval < minsave_interval)
11101 interval = minsave_interval;
11102 add_timer(gettick()+interval,pc_autosave,0,0);
11103
11104 return 0;
11105}
11106
11107static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap)
11108{
11109 if (sd->state.night != night_flag && map[sd->bl.m].flag.nightenabled)
11110 { //Night/day state does not match.
11111 clif_status_load(&sd->bl, SI_NIGHT, night_flag); //New night effect by dynamix [Skotlex]
11112 sd->state.night = night_flag;
11113 return 1;
11114 }
11115 return 0;
11116}
11117/*================================================
11118 * timer to do the day [Yor]
11119 * data: 0 = called by timer, 1 = gmcommand/script
11120 *------------------------------------------------*/
11121int map_day_timer(int tid, unsigned int tick, int id, intptr_t data)
11122{
11123 char tmp_soutput[1024];
11124
11125 if (data == 0 && battle_config.day_duration <= 0) // if we want a day
11126 return 0;
11127
11128 if (!night_flag)
11129 return 0; //Already day.
11130
11131 night_flag = 0; // 0=day, 1=night [Yor]
11132 map_foreachpc(pc_daynight_timer_sub);
11133 strcpy(tmp_soutput, (data == 0) ? msg_txt(NULL,502) : msg_txt(NULL,60)); // The day has arrived!
11134 intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0);
11135 return 0;
11136}
11137
11138/*================================================
11139 * timer to do the night [Yor]
11140 * data: 0 = called by timer, 1 = gmcommand/script
11141 *------------------------------------------------*/
11142int map_night_timer(int tid, unsigned int tick, int id, intptr_t data)
11143{
11144 char tmp_soutput[1024];
11145
11146 if (data == 0 && battle_config.night_duration <= 0) // if we want a night
11147 return 0;
11148
11149 if (night_flag)
11150 return 0; //Already nigth.
11151
11152 night_flag = 1; // 0=day, 1=night [Yor]
11153 map_foreachpc(pc_daynight_timer_sub);
11154 strcpy(tmp_soutput, (data == 0) ? msg_txt(NULL,503) : msg_txt(NULL,59)); // The night has fallen...
11155 intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0);
11156 return 0;
11157}
11158
11159void pc_setstand(struct map_session_data *sd){
11160 nullpo_retv(sd);
11161
11162 status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER);
11163 clif_status_load(&sd->bl,SI_SIT,0);
11164 clif_standing(&sd->bl,true); //Inform area PC is standing
11165 //Reset sitting tick.
11166 sd->ssregen.tick.hp = sd->ssregen.tick.sp = 0;
11167 sd->state.dead_sit = sd->vd.dead_sit = 0;
11168}
11169/*==========================================
11170 * Aura
11171 *------------------------------------------*/
11172int pc_get_aura(struct map_session_data *sd)
11173{
11174 int i;
11175 struct faction_data *fd;
11176
11177 // Battleground Ranking
11178 if( map_flag_vs(sd->bl.m) )
11179 return 0;
11180
11181 if( sd->state.pvpmode )
11182 return battle_config.aura_pvpmode_enable; // 15 Default
11183 if( sd->user_aura != 0 )
11184 return sd->user_aura; // Priority Custom Aura
11185
11186 ARR_FIND(0, MAX_FAME_LIST, i, bgrank_fame_list[i].id == sd->status.char_id);
11187 if( i < MAX_FAME_LIST )
11188 return battle_config.aura_top10_bgranked; // Default 5
11189 ARR_FIND(0, MAX_FAME_LIST, i, bg_fame_list[i].id == sd->status.char_id);
11190 if( i < MAX_FAME_LIST )
11191 return battle_config.aura_top10_bgnormal; // Default 4
11192 ARR_FIND(0, MAX_FAME_LIST, i, pvprank_fame_list[i].id == sd->status.char_id);
11193 if( i < MAX_FAME_LIST )
11194 return battle_config.aura_pvpmode_top10; // Default 2
11195
11196 if( sd->status.faction_id && (fd = faction_search(sd->status.faction_id)) != NULL && fd->aura_id > 0 )
11197 return fd->aura_id;
11198
11199 return 0;
11200}
11201
11202void pc_pvpmode(struct map_session_data* sd)
11203{
11204 if( sd->state.pvpmode || map_flag_nopvpmode(sd->bl.m) )
11205 return; // Mapas de No PK
11206
11207 if( sd->duel_group > 0 )
11208 return; // No PK en Duelo
11209
11210 if( sd->disguise )
11211 return; // No PK si esta Disguise
11212
11213 if( sd->status.guild_id && guild_isatwar(sd->status.guild_id) )
11214 return; // No PK on GuildWars
11215
11216 if( !map[sd->bl.m].flag.nopvpmode && sd->idlepvp >= last_tick - battle_config.pvpmode_enable_delay )
11217 {
11218 char pkinfo[100];
11219 unsigned int tick = (unsigned int)(sd->idlepvp - last_tick + battle_config.pvpmode_enable_delay);
11220 sprintf(pkinfo, "[PK disable - wait %d seconds to enter again in PK Mode.]", tick);
11221 clif_disp_onlyself(sd ,(const char*)pkinfo,(int)strlen((const char*)pkinfo));
11222
11223 return;
11224 }
11225
11226 sd->state.pvpmode = 1;
11227 sd->view_aura = pc_get_aura(sd);
11228 sd->idlepvp = last_tick; // Inicio de Modo PK
11229
11230 clif_clearunit_area(&sd->bl,CLR_OUTSIGHT);
11231 clif_refresh(sd);
11232 map_foreachinrange(clif_insight_tbl2bl,&sd->bl,AREA_SIZE,BL_PC,&sd->bl);
11233 clif_map_property(sd, MAPPROPERTY_FREEPVPZONE);
11234
11235 clif_displaymessage(sd->fd, "[Entering PK Mode - You can kill/be killed by others in PK Mode]");
11236 return;
11237}
11238
11239void pc_pvpmodeoff(struct map_session_data* sd, short force, short flag)
11240{
11241 char pkinfo[100];
11242
11243 if( !sd || !sd->state.pvpmode )
11244 return;
11245
11246 if( !force && sd->idlepvp >= last_tick - battle_config.pvpmode_disable_delay )
11247 {
11248 unsigned int tick = (unsigned int)(sd->idlepvp - last_tick + battle_config.pvpmode_disable_delay);
11249 sprintf(pkinfo, "[PK Enabled - %d seconds to disable it]", tick);
11250 clif_disp_onlyself(sd,pkinfo,(int)strlen(pkinfo));
11251 return;
11252 }
11253
11254 sd->state.pvpmode = 0;
11255 sd->view_aura = pc_get_aura(sd);
11256
11257 if( flag )
11258 { // Manual Change - else it's a off from change map
11259 clif_clearunit_area(&sd->bl,CLR_OUTSIGHT);
11260 clif_refresh(sd);
11261 map_foreachinrange(clif_insight_tbl2bl,&sd->bl,AREA_SIZE,BL_PC,&sd->bl);
11262 }
11263
11264 sprintf(pkinfo, "[PK Mode Disabled]");
11265 clif_disp_onlyself(sd,pkinfo,(int)strlen(pkinfo));
11266 sd->idlepvp = last_tick; // PK Last Action
11267
11268 return;
11269}
11270
11271/**
11272 * Mechanic (MADO GEAR)
11273 **/
11274void pc_overheat(struct map_session_data *sd, int val) {
11275 int heat = val, skill,
11276 limit[] = { 10, 20, 28, 46, 66 };
11277
11278 if( !pc_ismadogear(sd) || sd->sc.data[SC_OVERHEAT] )
11279 return; // already burning
11280
11281 skill = cap_value(pc_checkskill(sd,NC_MAINFRAME),0,4);
11282 if( sd->sc.data[SC_OVERHEAT_LIMITPOINT] ) {
11283 heat += sd->sc.data[SC_OVERHEAT_LIMITPOINT]->val1;
11284 status_change_end(&sd->bl,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER);
11285 }
11286
11287 heat = max(0,heat); // Avoid negative HEAT
11288 if( heat >= limit[skill] )
11289 sc_start(&sd->bl,&sd->bl,SC_OVERHEAT,100,0,1000);
11290 else
11291 sc_start(&sd->bl,&sd->bl,SC_OVERHEAT_LIMITPOINT,100,heat,30000);
11292
11293 return;
11294}
11295
11296/**
11297 * Check if player is autolooting given itemID.
11298 */
11299bool pc_isautolooting(struct map_session_data *sd, int nameid)
11300{
11301 bool j = false;
11302
11303 if (!sd->state.autolootingtype)
11304 return false;
11305
11306 if (sd->state.autolootingtype && sd->state.autoloottype&(1<<itemdb_type(nameid)))
11307 j = true;
11308
11309 return ( j );
11310}
11311
11312/**
11313 * Checks if player can use @/#command
11314 * @param sd Player map session data
11315 * @param command Command name without @/# and params
11316 * @param type is it atcommand or charcommand
11317 */
11318bool pc_can_use_command(struct map_session_data *sd, const char *command, AtCommandType type)
11319{
11320 return pc_group_can_use_command(pc_get_group_id(sd), command, type);
11321}
11322
11323/**
11324 * Checks if commands used by a player should be logged
11325 * according to their group setting.
11326 * @param sd Player map session data
11327 */
11328bool pc_should_log_commands(struct map_session_data *sd)
11329{
11330 return pc_group_should_log_commands(pc_get_group_id(sd));
11331}
11332
11333static int pc_talisman_timer(int tid, unsigned int tick, int id, intptr_t data)
11334{
11335 struct map_session_data *sd;
11336 int i, type;
11337
11338 if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC )
11339 return 1;
11340
11341 ARR_FIND(1, 5, type, sd->talisman[type] > 0);
11342
11343 if( sd->talisman[type] <= 0 )
11344 {
11345 ShowError("pc_talisman_timer: %d talisman's available. (aid=%d cid=%d tid=%d)\n", sd->talisman[type], sd->status.account_id, sd->status.char_id, tid);
11346 sd->talisman[type] = 0;
11347 return 0;
11348 }
11349
11350 ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == tid);
11351 if( i == sd->talisman[type] )
11352 {
11353 ShowError("pc_talisman_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid);
11354 return 0;
11355 }
11356
11357 sd->talisman[type]--;
11358 if( i != sd->talisman[type] )
11359 memmove(sd->talisman_timer[type]+i, sd->talisman_timer[type]+i+1, (sd->talisman[type]-i)*sizeof(int));
11360 sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER;
11361
11362 clif_talisman(sd, type);
11363
11364 return 0;
11365}
11366
11367int pc_add_talisman(struct map_session_data *sd,int interval,int max,int type)
11368{
11369 int tid, i;
11370
11371 nullpo_ret(sd);
11372
11373 if(max > 10)
11374 max = 10;
11375 if(sd->talisman[type] < 0)
11376 sd->talisman[type] = 0;
11377
11378 if( sd->talisman[type] && sd->talisman[type] >= max )
11379 {
11380 if(sd->talisman_timer[type][0] != INVALID_TIMER)
11381 delete_timer(sd->talisman_timer[type][0],pc_talisman_timer);
11382 sd->talisman[type]--;
11383 if( sd->talisman[type] != 0 )
11384 memmove(sd->talisman_timer[type]+0, sd->talisman_timer[type]+1, (sd->talisman[type])*sizeof(int));
11385 sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER;
11386 }
11387
11388 tid = add_timer(gettick()+interval, pc_talisman_timer, sd->bl.id, 0);
11389 ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->talisman_timer[type][i])->tick) < 0);
11390 if( i != sd->talisman[type] )
11391 memmove(sd->talisman_timer[type]+i+1, sd->talisman_timer[type]+i, (sd->talisman[type]-i)*sizeof(int));
11392 sd->talisman_timer[type][i] = tid;
11393 sd->talisman[type]++;
11394
11395 clif_talisman(sd, type);
11396 return 0;
11397}
11398
11399int pc_del_talisman(struct map_session_data *sd,int count,int type)
11400{
11401 int i;
11402
11403 nullpo_ret(sd);
11404
11405 if( sd->talisman[type] <= 0 ) {
11406 sd->talisman[type] = 0;
11407 return 0;
11408 }
11409
11410 if( count <= 0 )
11411 return 0;
11412 if( count > sd->talisman[type] )
11413 count = sd->talisman[type];
11414 sd->talisman[type] -= count;
11415 if( count > 10 )
11416 count = 10;
11417
11418 for(i = 0; i < count; i++) {
11419 if(sd->talisman_timer[type][i] != INVALID_TIMER) {
11420 delete_timer(sd->talisman_timer[type][i],pc_talisman_timer);
11421 sd->talisman_timer[type][i] = INVALID_TIMER;
11422 }
11423 }
11424 for(i = count; i < 10; i++) {
11425 sd->talisman_timer[type][i-count] = sd->talisman_timer[type][i];
11426 sd->talisman_timer[type][i] = INVALID_TIMER;
11427 }
11428
11429 clif_talisman(sd, type);
11430 return 0;
11431}
11432#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
11433/*==========================================
11434 * Renewal EXP/Itemdrop rate modifier base on level penalty
11435 * 1=exp 2=itemdrop
11436 *------------------------------------------*/
11437int pc_level_penalty_mod(struct map_session_data *sd, int mob_level, uint32 mob_class, int type)
11438{
11439 int diff, rate = 100, i;
11440
11441 nullpo_ret(sd);
11442
11443 diff = mob_level - sd->status.base_level;
11444
11445 if( diff < 0 )
11446 diff = MAX_LEVEL + ( ~diff + 1 );
11447
11448 for( i = 0; i < CLASS_ALL; i++ ) {
11449 int tmp;
11450
11451 if( ( tmp = level_penalty[type][i][diff] ) > 0 ) {
11452 rate = tmp;
11453 break;
11454 }
11455 }
11456
11457 return rate;
11458}
11459#endif
11460int pc_split_str(char *str,char **val,int num)
11461{
11462 int i;
11463
11464 for (i=0; i<num && str; i++){
11465 val[i] = str;
11466 str = strchr(str,',');
11467 if (str && i<num-1) //Do not remove a trailing comma.
11468 *str++=0;
11469 }
11470 return i;
11471}
11472
11473int pc_split_atoi(char* str, int* val, char sep, int max)
11474{
11475 int i,j;
11476 for (i=0; i<max; i++) {
11477 if (!str) break;
11478 val[i] = atoi(str);
11479 str = strchr(str,sep);
11480 if (str)
11481 *str++=0;
11482 }
11483 //Zero up the remaining.
11484 for(j=i; j < max; j++)
11485 val[j] = 0;
11486 return i;
11487}
11488
11489int pc_split_atoui(char* str, unsigned int* val, char sep, int max)
11490{
11491 static int warning=0;
11492 int i,j;
11493 for (i=0; i<max; i++) {
11494 double f;
11495 if (!str) break;
11496 f = atof(str);
11497 if (f < 0)
11498 val[i] = 0;
11499 else if (f > UINT_MAX) {
11500 val[i] = UINT_MAX;
11501 if (!warning) {
11502 warning = 1;
11503 ShowWarning("pc_readdb (exp.txt): Required exp per level is capped to %u\n", UINT_MAX);
11504 }
11505 } else
11506 val[i] = (unsigned int)f;
11507 str = strchr(str,sep);
11508 if (str)
11509 *str++=0;
11510 }
11511 //Zero up the remaining.
11512 for(j=i; j < max; j++)
11513 val[j] = 0;
11514 return i;
11515}
11516
11517/*==========================================
11518 * sub DB reading.
11519 * Function used to read skill_tree.txt
11520 *------------------------------------------*/
11521static bool pc_readdb_skilltree(char* fields[], int columns, int current)
11522{
11523 unsigned char joblv = 0, skill_lv;
11524 uint16 skill_id;
11525 int idx, class_;
11526 unsigned int i, offset = 3, skill_idx;
11527
11528 class_ = atoi(fields[0]);
11529 skill_id = (uint16)atoi(fields[1]);
11530 skill_lv = (unsigned char)atoi(fields[2]);
11531
11532 if(columns==4+MAX_PC_SKILL_REQUIRE*2)
11533 {// job level requirement extra column
11534 joblv = (unsigned char)atoi(fields[3]);
11535 offset++;
11536 }
11537
11538 if(!pcdb_checkid(class_))
11539 {
11540 ShowWarning("pc_readdb_skilltree: Invalid job class %d specified.\n", class_);
11541 return false;
11542 }
11543 idx = pc_class2idx(class_);
11544
11545 //This is to avoid adding two lines for the same skill. [Skotlex]
11546 ARR_FIND( 0, MAX_SKILL_TREE, skill_idx, skill_tree[idx][skill_idx].id == 0 || skill_tree[idx][skill_idx].id == skill_id );
11547 if( skill_idx == MAX_SKILL_TREE )
11548 {
11549 ShowWarning("pc_readdb_skilltree: Unable to load skill %hu into job %d's tree. Maximum number of skills per class has been reached.\n", skill_id, class_);
11550 return false;
11551 }
11552 else if(skill_tree[idx][skill_idx].id)
11553 {
11554 ShowNotice("pc_readdb_skilltree: Overwriting skill %hu for job class %d.\n", skill_id, class_);
11555 }
11556
11557 skill_tree[idx][skill_idx].id = skill_id;
11558 skill_tree[idx][skill_idx].max = skill_lv;
11559 skill_tree[idx][skill_idx].joblv = joblv;
11560
11561 for(i = 0; i < MAX_PC_SKILL_REQUIRE; i++)
11562 {
11563 skill_tree[idx][skill_idx].need[i].id = atoi(fields[i*2+offset]);
11564 skill_tree[idx][skill_idx].need[i].lv = atoi(fields[i*2+offset+1]);
11565 }
11566 return true;
11567}
11568#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
11569static bool pc_readdb_levelpenalty(char* fields[], int columns, int current)
11570{
11571 int type, class_, diff;
11572
11573 type = atoi(fields[0]); //1=experience, 2=item drop
11574 class_ = atoi(fields[1]);
11575 diff = atoi(fields[2]);
11576
11577 if( type != 1 && type != 2 ){
11578 ShowWarning("pc_readdb_levelpenalty: Invalid type %d specified.\n", type);
11579 return false;
11580 }
11581
11582 if( class_ < 0 || class_ > CLASS_ALL ){
11583 ShowWarning("pc_readdb_levelpenalty: Invalid class %d specified.\n", class_);
11584 return false;
11585 }
11586
11587 diff = min(diff, MAX_LEVEL);
11588
11589 if( diff < 0 )
11590 diff = min(MAX_LEVEL + ( ~(diff) + 1 ), MAX_LEVEL*2);
11591
11592 level_penalty[type][class_][diff] = atoi(fields[3]);
11593
11594 return true;
11595}
11596#endif
11597
11598/** [Cydh]
11599* Calculates base hp of player. Reference: http://irowiki.org/wiki/Max_HP
11600* @param level Base level of player
11601* @param idx Index of class
11602* @return base_hp
11603*/
11604static unsigned int pc_calc_basehp(uint16 level, uint16 class_idx) {
11605 double base_hp;
11606 uint16 i;
11607
11608 base_hp = 35 + level * (job_info[class_idx].hp_multiplicator/100.);
11609 for (i = 2; i <= level; i++)
11610 base_hp += floor(((job_info[class_idx].hp_factor/100.) * i) + 0.5); //Don't have round()
11611 if (class_ >= JOB_BABY && class_ <= JOB_SUPER_BABY) {
11612 base_hp *= 70/100;
11613 }
11614 return (unsigned int)base_hp;
11615}
11616
11617//Reading job_db1.txt line, (class,weight,HPFactor,HPMultiplicator,SPFactor,aspd/lvl...)
11618static bool pc_readdb_job1(char* fields[], int columns, int current){
11619 int idx, class_;
11620 unsigned int i;
11621
11622 class_ = atoi(fields[0]);
11623
11624 if (!pcdb_checkid(class_)) {
11625 ShowWarning("status_readdb_job1: Invalid job class %d specified.\n", class_);
11626 return false;
11627 }
11628 idx = pc_class2idx(class_);
11629
11630 job_info[idx].max_weight_base = atoi(fields[1]);
11631 job_info[idx].hp_factor = atoi(fields[2]);
11632 job_info[idx].hp_multiplicator = atoi(fields[3]);
11633 job_info[idx].sp_factor = atoi(fields[4]);
11634
11635#ifdef RENEWAL_ASPD
11636 for(i = 0; i <= MAX_WEAPON_TYPE; i++)
11637#else
11638 for(i = 0; i < MAX_WEAPON_TYPE; i++)
11639#endif
11640 {
11641 job_info[idx].aspd_base[i] = atoi(fields[i+5]);
11642 }
11643
11644 return true;
11645}
11646
11647//Reading job_db2.txt line (class,JobLv1,JobLv2,JobLv3,...)
11648static bool pc_readdb_job2(char* fields[], int columns, int current)
11649{
11650 int idx, class_, i;
11651
11652 class_ = atoi(fields[0]);
11653
11654 if(!pcdb_checkid(class_))
11655 {
11656 ShowWarning("status_readdb_job2: Invalid job class %d specified.\n", class_);
11657 return false;
11658 }
11659 idx = pc_class2idx(class_);
11660
11661 for(i = 1; i < columns; i++)
11662 {
11663 job_info[idx].job_bonus[i-1] = atoi(fields[i]);
11664 }
11665 return true;
11666}
11667
11668//Reading job_exp.txt line
11669//Max Level,Class list,Type (0 - Base Exp; 1 - Job Exp),Exp/lvl...
11670static bool pc_readdb_job_exp(char* fields[], int columns, int current)
11671{
11672 int idx, i, type;
11673 int job_id,job_count,jobs[CLASS_COUNT];
11674 unsigned int ui, maxlvl;
11675
11676 maxlvl = atoi(fields[0]);
11677 if(maxlvl > MAX_LEVEL || maxlvl<1){
11678 ShowError("pc_readdb_job_exp: Invalid maxlevel %d specified.\n", maxlvl);
11679 return false;
11680 }
11681 if((maxlvl+3) > columns){ //nb values = (maxlvl-startlvl)+1-index1stvalue
11682 ShowError("pc_readdb_job_exp: Number of columns %d defined is too low for max level %d.\n",columns,maxlvl);
11683 return false;
11684 }
11685 type = atoi(fields[2]);
11686 if(type < 0 || type > 1){
11687 ShowError("pc_readdb_job_exp: Invalid type %d specified.\n", type);
11688 return false;
11689 }
11690 job_count = pc_split_atoi(fields[1],jobs,':',CLASS_COUNT);
11691 if (job_count < 1)
11692 return false;
11693 job_id = jobs[0];
11694 if(!pcdb_checkid(job_id)){
11695 ShowError("pc_readdb_job_exp: Invalid job class %d specified.\n", job_id);
11696 return false;
11697 }
11698 idx = pc_class2idx(job_id);
11699
11700 job_info[idx].max_level[type] = maxlvl;
11701 for(i=0; i<maxlvl; i++)
11702 job_info[idx].exp_table[type][i] = ((uint32) atoi(fields[3+i]));
11703 //Reverse check in case the array has a bunch of trailing zeros... [Skotlex]
11704 //The reasoning behind the -2 is this... if the max level is 5, then the array
11705 //should look like this:
11706 //0: x, 1: x, 2: x: 3: x 4: 0 <- last valid value is at 3.
11707 while ((ui = job_info[idx].max_level[type]) >= 2 && job_info[idx].exp_table[type][ui-2] <= 0)
11708 job_info[idx].max_level[type]--;
11709 if (job_info[idx].max_level[type] < maxlvl) {
11710 ShowWarning("pc_readdb_job_exp: Specified max %u for job %d, but that job's exp table only goes up to level %u.\n", maxlvl, job_id, job_info[idx].max_level[type]);
11711 ShowInfo("Filling the missing values with the last exp entry.\n");
11712 //Fill the requested values with the last entry.
11713 ui = (job_info[idx].max_level[type] <= 2? 0: job_info[idx].max_level[type]-2);
11714 for (; ui+2 < maxlvl; ui++)
11715 job_info[idx].exp_table[type][ui] = job_info[idx].exp_table[type][ui-1];
11716 job_info[idx].max_level[type] = maxlvl;
11717 }
11718// ShowInfo("%s - Class %d: %d\n", type?"Job":"Base", job_id, job_info[idx].max_level[type]);
11719 for (i = 1; i < job_count; i++) {
11720 job_id = jobs[i];
11721 if (!pcdb_checkid(job_id)) {
11722 ShowError("pc_readdb_job_exp: Invalid job ID %d.\n", job_id);
11723 continue;
11724 }
11725 idx = pc_class2idx(job_id);
11726 memcpy(job_info[idx].exp_table[type], job_info[pc_class2idx(jobs[0])].exp_table[type], sizeof(job_info[pc_class2idx(jobs[0])].exp_table[type]));
11727 job_info[idx].max_level[type] = maxlvl;
11728// ShowInfo("%s - Class %d: %u\n", type?"Job":"Base", job_id, job_info[idx].max_level[type]);
11729 }
11730 return true;
11731}
11732
11733/**
11734* #ifdef HP_SP_TABLES, reads 'job_basehpsp_db.txt to replace hp/sp results from formula
11735* startlvl,endlvl,class,type,values...
11736*/
11737#ifdef HP_SP_TABLES
11738static bool pc_readdb_job_basehpsp(char* fields[], int columns, int current)
11739{
11740 int i, startlvl, endlvl;
11741 int job_count,jobs[CLASS_COUNT];
11742 short type;
11743
11744 startlvl = atoi(fields[0]);
11745 if(startlvl<1){
11746 ShowError("pc_readdb_job_basehpsp: Invalid start level %d specified.\n", startlvl);
11747 return false;
11748 }
11749 endlvl = atoi(fields[1]);
11750 if(endlvl<1 || endlvl<startlvl){
11751 ShowError("pc_readdb_job_basehpsp: Invalid end level %d specified.\n", endlvl);
11752 return false;
11753 }
11754 if((endlvl-startlvl+1+4) > columns){ //nb values = (maxlvl-startlvl)+1-index1stvalue
11755 ShowError("pc_readdb_job_basehpsp: Number of columns %d (needs %d) defined is too low for start level %d, max level %d.\n",columns,(endlvl-startlvl+1+4),startlvl,endlvl);
11756 return false;
11757 }
11758 type = atoi(fields[3]);
11759 if(type < 0 || type > 1){
11760 ShowError("pc_readdb_job_basehpsp: Invalid type %d specified.\n", type);
11761 return false;
11762 }
11763
11764 job_count = pc_split_atoi(fields[2],jobs,':',CLASS_COUNT);
11765 if (job_count < 1)
11766 return false;
11767
11768 for (i = 0; i < job_count; i++) {
11769 int idx, job_id = jobs[i], use_endlvl;
11770 if (!pcdb_checkid(job_id)) {
11771 ShowError("pc_readdb_job_basehpsp: Invalid job class %d specified.\n", job_id);
11772 return false;
11773 }
11774 idx = pc_class2idx(job_id);
11775 if (startlvl > job_info[idx].max_level[0]) {
11776 ShowError("pc_readdb_job_basehpsp: Invalid start level %d specified.\n", startlvl);
11777 return false;
11778 }
11779 //Just read until available max level for this job, don't use MAX_LEVEL!
11780 use_endlvl = endlvl;
11781 if (use_endlvl > job_info[idx].max_level[0])
11782 use_endlvl = job_info[idx].max_level[0];
11783
11784 if(type == 0) { //hp type
11785 uint16 j;
11786 for(j = 0; j < use_endlvl; j++) {
11787 if (atoi(fields[j+4])) {
11788 uint16 lvl_idx = startlvl-1+j;
11789 job_info[idx].base_hp[lvl_idx] = atoi(fields[j+4]);
11790 //Tells if this HP is lower than previous level
11791 if (lvl_idx-1 >= 0 && job_info[idx].base_hp[lvl_idx] < job_info[idx].base_hp[lvl_idx-1])
11792 ShowWarning("pc_readdb_job_basehpsp: HP value at line %d col %d is lower than previous level (job=%d,lvl=%d,oldval=%d,val=%d).\n",
11793 current,j+4,job_id,lvl_idx+1,job_info[idx].base_hp[lvl_idx-1],job_info[idx].base_hp[lvl_idx]);
11794 }
11795 }
11796 }
11797 else { //sp type
11798 uint16 j;
11799 for(j = 0; j < use_endlvl; j++) {
11800 if (atoi(fields[j+4])) {
11801 uint16 lvl_idx = startlvl-1+j;
11802 job_info[idx].base_sp[lvl_idx] = atoi(fields[j+4]);
11803 //Tells if this SP is lower than previous level
11804 if (lvl_idx-1 >= 0 && job_info[idx].base_sp[lvl_idx] < job_info[idx].base_sp[lvl_idx-1])
11805 ShowWarning("pc_readdb_job_basehpsp: SP value at line %d col %d is lower than previous level (job=%d,lvl=%d,oldval=%d,val=%d).\n",
11806 current,j+4,job_id,lvl_idx+1,job_info[idx].base_sp[lvl_idx-1],job_info[idx].base_sp[lvl_idx]);
11807 }
11808 }
11809 }
11810 }
11811 return true;
11812}
11813#endif
11814
11815/** [Cydh]
11816* Reads 'job_param_db.txt' to check max. param each job and store them to job_info[].max_param.*
11817*/
11818static bool pc_readdb_job_param(char* fields[], int columns, int current)
11819{
11820 int idx, class_;
11821 uint16 str, agi, vit, int_, dex, luk;
11822
11823 script_get_constant(trim(fields[0]),&class_);
11824
11825 if ((idx = pc_class2idx(class_)) < 0) {
11826 ShowError("pc_readdb_job_param: Invalid job '%s'. Skipping!",fields[0]);
11827 return false;
11828 }
11829 str = cap_value(atoi(fields[1]),10,SHRT_MAX);
11830 agi = atoi(fields[2]) ? cap_value(atoi(fields[2]),10,SHRT_MAX) : str;
11831 vit = atoi(fields[3]) ? cap_value(atoi(fields[3]),10,SHRT_MAX) : str;
11832 int_ = atoi(fields[4]) ? cap_value(atoi(fields[4]),10,SHRT_MAX) : str;
11833 dex = atoi(fields[5]) ? cap_value(atoi(fields[5]),10,SHRT_MAX) : str;
11834 luk = atoi(fields[6]) ? cap_value(atoi(fields[6]),10,SHRT_MAX) : str;
11835
11836 job_info[idx].max_param.str = str;
11837 job_info[idx].max_param.agi = agi;
11838 job_info[idx].max_param.vit = vit;
11839 job_info[idx].max_param.int_ = int_;
11840 job_info[idx].max_param.dex = dex;
11841 job_info[idx].max_param.luk = luk;
11842
11843 return true;
11844}
11845
11846static int pc_read_statsdb(const char *basedir, int last_s, bool silent){
11847 int i=1;
11848 char line[24000]; //FIXME this seem too big
11849 FILE *fp;
11850
11851 sprintf(line, "%s/statpoint.txt", basedir);
11852 fp=fopen(line,"r");
11853 if(fp == NULL){
11854 if(silent==0) ShowWarning("Can't read '"CL_WHITE"%s"CL_RESET"'... Generating DB.\n",line);
11855 return max(last_s,i);
11856 } else {
11857 int entries=0;
11858 while(fgets(line, sizeof(line), fp))
11859 {
11860 int stat;
11861 trim(line);
11862 if(line[0] == '\0' || (line[0]=='/' && line[1]=='/'))
11863 continue;
11864 if ((stat=strtoul(line,NULL,10))<0)
11865 stat=0;
11866 if (i > MAX_LEVEL)
11867 break;
11868 stats_point_table[i]=stat;
11869 i++;
11870 entries++;
11871 }
11872 fclose(fp);
11873 ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s/%s"CL_RESET"'.\n", entries, basedir,"statpoint.txt");
11874 }
11875 return max(last_s,i);
11876}
11877
11878/*==========================================
11879 * pc DB reading.
11880 * job_exp.txt - required experience values
11881 * skill_tree.txt - skill tree for every class
11882 * attr_fix.txt - elemental adjustment table
11883 * job_db1.txt - job,weight,hp_factor,hp_multiplicator,sp_factor,aspds/lvl
11884 * job_db2.txt - job,stats bonuses/lvl
11885 * job_maxhpsp_db.txt - strtlvl,maxlvl,job,type,values/lvl (values=hp|sp)
11886 *------------------------------------------*/
11887int pc_readdb(void)
11888{
11889 int i, k, s = 1;
11890 const char* dbsubpath[] = {
11891 "",
11892 "/"DBIMPORT,
11893 //add other path here
11894 };
11895
11896 //reset
11897 memset(job_info,0,sizeof(job_info)); // job_info table
11898
11899 // Reset and read skilltree
11900 memset(skill_tree,0,sizeof(skill_tree));
11901 sv_readdb(db_path, DBPATH"skill_tree.txt", ',', 3+MAX_PC_SKILL_REQUIRE*2, 4+MAX_PC_SKILL_REQUIRE*2, -1, &pc_readdb_skilltree, 0);
11902 sv_readdb(db_path, DBIMPORT"/skill_tree.txt", ',', 3+MAX_PC_SKILL_REQUIRE*2, 4+MAX_PC_SKILL_REQUIRE*2, -1, &pc_readdb_skilltree, 1);
11903
11904#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
11905 sv_readdb(db_path, "re/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty, 0);
11906 sv_readdb(db_path, DBIMPORT"/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty, 1);
11907 for( k=1; k < 3; k++ ){ // fill in the blanks
11908 int j;
11909 for( j = 0; j < CLASS_ALL; j++ ){
11910 int tmp = 0;
11911 for( i = 0; i < MAX_LEVEL*2; i++ ){
11912 if( i == MAX_LEVEL+1 )
11913 tmp = level_penalty[k][j][0];// reset
11914 if( level_penalty[k][j][i] > 0 )
11915 tmp = level_penalty[k][j][i];
11916 else
11917 level_penalty[k][j][i] = tmp;
11918 }
11919 }
11920 }
11921#endif
11922
11923 // reset then read statspoint
11924 memset(stats_point_table,0,sizeof(stats_point_table));
11925 for(i=0; i<ARRAYLENGTH(dbsubpath); i++){
11926 uint8 n1 = strlen(db_path)+strlen(dbsubpath[i])+1;
11927 uint8 n2 = strlen(db_path)+strlen(DBPATH)+strlen(dbsubpath[i])+1;
11928 char* dbsubpath1 = (char*)aMalloc(n1+1);
11929 char* dbsubpath2 = (char*)aMalloc(n2+1);
11930
11931 if(i==0) {
11932 safesnprintf(dbsubpath1,n1,"%s%s",db_path,dbsubpath[i]);
11933 safesnprintf(dbsubpath2,n2,"%s/%s%s",db_path,DBPATH,dbsubpath[i]);
11934 }
11935 else {
11936 safesnprintf(dbsubpath1,n1,"%s%s",db_path,dbsubpath[i]);
11937 safesnprintf(dbsubpath2,n1,"%s%s",db_path,dbsubpath[i]);
11938 }
11939
11940 s = pc_read_statsdb(dbsubpath2,s,i);
11941 if (i == 0)
11942#ifdef RENEWAL_ASPD
11943 sv_readdb(dbsubpath1, "re/job_db1.txt",',',6+MAX_WEAPON_TYPE,6+MAX_WEAPON_TYPE,CLASS_COUNT,&pc_readdb_job1, i);
11944#else
11945 sv_readdb(dbsubpath1, "pre-re/job_db1.txt",',',5+MAX_WEAPON_TYPE,5+MAX_WEAPON_TYPE,CLASS_COUNT,&pc_readdb_job1, i);
11946#endif
11947 else
11948 sv_readdb(dbsubpath1, "job_db1.txt",',',5+MAX_WEAPON_TYPE,5+MAX_WEAPON_TYPE,CLASS_COUNT,&pc_readdb_job1, i);
11949 sv_readdb(dbsubpath1, "job_db2.txt",',',1,1+MAX_LEVEL,CLASS_COUNT,&pc_readdb_job2, i);
11950 sv_readdb(dbsubpath2, "job_exp.txt",',',4,1000+3,CLASS_COUNT*2,&pc_readdb_job_exp, i); //support till 1000lvl
11951#ifdef HP_SP_TABLES
11952 sv_readdb(dbsubpath2, "job_basehpsp_db.txt", ',', 4, 4+500, CLASS_COUNT*2, &pc_readdb_job_basehpsp, i); //Make it support until lvl 500!
11953#endif
11954 sv_readdb(dbsubpath2, "job_param_db.txt", ',', 2, PARAM_MAX+1, CLASS_COUNT, &pc_readdb_job_param, i);
11955 aFree(dbsubpath1);
11956 aFree(dbsubpath2);
11957 }
11958
11959 // generate the remaining parts of the db if necessary
11960 k = battle_config.use_statpoint_table; //save setting
11961 battle_config.use_statpoint_table = 0; //temporarily disable to force pc_gets_status_point use default values
11962 stats_point_table[0] = 45; // seed value
11963 for (; s <= MAX_LEVEL; s++)
11964 stats_point_table[s] = stats_point_table[s-1] + pc_gets_status_point(s-1);
11965 battle_config.use_statpoint_table = k; //restore setting
11966
11967 //Checking if all class have their data
11968 for (i = 0; i < JOB_MAX; i++) {
11969 int idx;
11970 uint16 j;
11971 if (!pcdb_checkid(i)) continue;
11972 if (i == JOB_WEDDING || i == JOB_XMAS || i == JOB_SUMMER || i == JOB_HANBOK || i == JOB_OKTOBERFEST)
11973 continue; //Classes that do not need exp tables.
11974 idx = pc_class2idx(i);
11975 if (!job_info[idx].max_level[0])
11976 ShowWarning("Class %s (%d) does not have a base exp table.\n", job_name(i), i);
11977 if (!job_info[idx].max_level[1])
11978 ShowWarning("Class %s (%d) does not have a job exp table.\n", job_name(i), i);
11979
11980 //Init and checking the empty value of Base HP/SP [Cydh]
11981 for (j = 0; j < (job_info[idx].max_level[0] ? job_info[idx].max_level[0] : MAX_LEVEL); j++) {
11982 if (job_info[idx].base_hp[j] == 0)
11983 job_info[idx].base_hp[j] = pc_calc_basehp(j+1,idx);
11984 if (job_info[idx].base_sp[j] == 0)
11985 job_info[idx].base_sp[j] = 10 + (unsigned int)floor((j+1) * (job_info[idx].sp_factor / 100.));
11986 }
11987 }
11988 return 0;
11989}
11990
11991// Read MOTD on startup. [Valaris]
11992int pc_read_motd(void)
11993{
11994 FILE* fp;
11995 // clear old MOTD
11996 memset(motd_text, 0, sizeof(motd_text));
11997
11998 // read current MOTD
11999 if( ( fp = fopen(motd_txt, "r") ) != NULL )
12000 {
12001 unsigned int entries = 0;
12002
12003 while( entries < MOTD_LINE_SIZE && fgets(motd_text[entries], sizeof(motd_text[entries]), fp) )
12004 {
12005 char* buf = motd_text[entries];
12006 unsigned int lines = 0;
12007 size_t len;
12008 lines++;
12009 if( buf[0] == '/' && buf[1] == '/' )
12010 continue;
12011 len = strlen(buf);
12012 while( len && ( buf[len-1] == '\r' || buf[len-1] == '\n' ) ) // strip trailing EOL characters
12013 len--;
12014 if( len ) {
12015 char * ptr;
12016 buf[len] = 0;
12017 if( ( ptr = strstr(buf, " :") ) != NULL && ptr-buf >= NAME_LENGTH ) // crashes newer clients
12018 ShowWarning("Found sequence '"CL_WHITE" :"CL_RESET"' on line '"CL_WHITE"%u"CL_RESET"' in '"CL_WHITE"%s"CL_RESET"'. This can cause newer clients to crash.\n", lines, motd_txt);
12019 }
12020 else {// empty line
12021 buf[0] = ' ';
12022 buf[1] = 0;
12023 }
12024 entries++;
12025 }
12026 fclose(fp);
12027 ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, motd_txt);
12028 }
12029 else
12030 ShowWarning("File '"CL_WHITE"%s"CL_RESET"' not found.\n", motd_txt);
12031
12032 return 0;
12033}
12034void pc_itemcd_do(struct map_session_data *sd, bool load) {
12035 int i,cursor = 0;
12036 struct item_cd* cd = NULL;
12037
12038 if( load ) {
12039 if( !(cd = idb_get(itemcd_db, sd->status.char_id)) ) {
12040 // no skill cooldown is associated with this character
12041 return;
12042 }
12043 for(i = 0; i < MAX_ITEMDELAYS; i++) {
12044 if( cd->nameid[i] && DIFF_TICK(gettick(),cd->tick[i]) < 0 ) {
12045 sd->item_delay[cursor].tick = cd->tick[i];
12046 sd->item_delay[cursor].nameid = cd->nameid[i];
12047 cursor++;
12048 }
12049 }
12050 idb_remove(itemcd_db,sd->status.char_id);
12051 } else {
12052 if( !(cd = idb_get(itemcd_db,sd->status.char_id)) ) {
12053 // create a new skill cooldown object for map storage
12054 CREATE( cd, struct item_cd, 1 );
12055 idb_put( itemcd_db, sd->status.char_id, cd );
12056 }
12057 for(i = 0; i < MAX_ITEMDELAYS; i++) {
12058 if( sd->item_delay[i].nameid && DIFF_TICK(gettick(),sd->item_delay[i].tick) < 0 ) {
12059 cd->tick[cursor] = sd->item_delay[i].tick;
12060 cd->nameid[cursor] = sd->item_delay[i].nameid;
12061 cursor++;
12062 }
12063 }
12064 }
12065 return;
12066}
12067
12068/**
12069* Clear the dmglog data from player
12070* @param sd
12071* @param md
12072**/
12073static void pc_clear_log_damage_sub(int char_id, struct mob_data *md)
12074{
12075 uint8 i;
12076 ARR_FIND(0,DAMAGELOG_SIZE,i,md->dmglog[i].id == char_id);
12077 if (i < DAMAGELOG_SIZE) {
12078 md->dmglog[i].id=0;
12079 md->dmglog[i].dmg=0;
12080 md->dmglog[i].flag=0;
12081 }
12082}
12083
12084/**
12085* Add log to player's dmglog
12086* @param sd
12087* @param id Monster's GID
12088**/
12089void pc_damage_log_add(struct map_session_data *sd, int id)
12090{
12091 uint8 i = 0;
12092
12093 if (!sd)
12094 return;
12095
12096 //Only store new data, don't need to renew the old one with same id
12097 for (i = 0; i < DAMAGELOG_SIZE_PC; i++) {
12098 if (sd->dmglog[i] == id)
12099 return;
12100 sd->dmglog[i] = id;
12101 return;
12102 }
12103}
12104
12105/**
12106* Clear dmglog data from player
12107* @param sd
12108* @param id Monster's id
12109**/
12110void pc_damage_log_clear(struct map_session_data *sd, int id)
12111{
12112 uint8 i;
12113 struct mob_data *md = NULL;
12114
12115 if (!sd)
12116 return;
12117
12118 if (!id) {
12119 for (i = 0; i < DAMAGELOG_SIZE_PC; i++) {
12120 if( !sd->dmglog[i] ) //skip the empty value
12121 continue;
12122
12123 if ((md = map_id2md(sd->dmglog[i])))
12124 pc_clear_log_damage_sub(sd->status.char_id,md);
12125 sd->dmglog[i] = 0;
12126 }
12127 }
12128 else {
12129 if ((md = map_id2md(id)))
12130 pc_clear_log_damage_sub(sd->status.char_id,md);
12131
12132 ARR_FIND(0,DAMAGELOG_SIZE_PC,i,sd->dmglog[i] == id); // find the id position
12133 if (i < DAMAGELOG_SIZE_PC)
12134 sd->dmglog[i] = 0;
12135 }
12136}
12137
12138/**
12139* Deposit some money to bank
12140* @param sd
12141* @param money Amount of money to deposit
12142**/
12143enum e_BANKING_DEPOSIT_ACK pc_bank_deposit(struct map_session_data *sd, int money) {
12144 unsigned int limit_check = money+sd->status.bank_vault;
12145
12146 if( money <= 0 || limit_check > MAX_BANK_ZENY ) {
12147 return BDA_OVERFLOW;
12148 } else if ( money > sd->status.zeny ) {
12149 return BDA_NO_MONEY;
12150 }
12151
12152 if( pc_payzeny(sd,money, LOG_TYPE_BANK, NULL) )
12153 return BDA_NO_MONEY;
12154
12155 sd->status.bank_vault += money;
12156 if( save_settings&256 )
12157 chrif_save(sd,0);
12158 return BDA_SUCCESS;
12159}
12160
12161/**
12162* Withdraw money from bank
12163* @param sd
12164* @param money Amount of money that will be withdrawn
12165**/
12166enum e_BANKING_WITHDRAW_ACK pc_bank_withdraw(struct map_session_data *sd, int money) {
12167 unsigned int limit_check = money+sd->status.zeny;
12168
12169 if( money <= 0 ) {
12170 return BWA_UNKNOWN_ERROR;
12171 } else if ( money > sd->status.bank_vault ) {
12172 return BWA_NO_MONEY;
12173 } else if ( limit_check > MAX_ZENY ) {
12174 /* no official response for this scenario exists. */
12175 clif_colormes(sd,color_table[COLOR_RED],msg_txt(sd,1495)); //You can't withdraw that much money
12176 return BWA_UNKNOWN_ERROR;
12177 }
12178
12179 if( pc_getzeny(sd,money, LOG_TYPE_BANK, NULL) )
12180 return BWA_NO_MONEY;
12181
12182 sd->status.bank_vault -= money;
12183 if( save_settings&256 )
12184 chrif_save(sd,0);
12185 return BWA_SUCCESS;
12186}
12187
12188/**
12189* Clear Cirmson Marker data from caster
12190* @param sd: Player
12191**/
12192void pc_crimson_marker_clear(struct map_session_data *sd) {
12193 uint8 i;
12194
12195 if (!sd || !(&sd->c_marker) || !sd->c_marker.target)
12196 return;
12197
12198 for (i = 0; i < MAX_SKILL_CRIMSON_MARKER; i++) {
12199 struct block_list *bl = NULL;
12200 if (sd->c_marker.target[i] && (bl = map_id2bl(sd->c_marker.target[i])))
12201 status_change_end(bl,SC_C_MARKER,INVALID_TIMER);
12202 }
12203}
12204
12205/**
12206* Show version to player
12207* @param sd: Player
12208**/
12209void pc_show_version(struct map_session_data *sd) {
12210 const char* svn = get_svn_revision();
12211 char buf[CHAT_SIZE_MAX];
12212
12213 if( svn[0] != UNKNOWN_VERSION )
12214 sprintf(buf,msg_txt(sd,1295),"SVN: r",svn); //rAthena Version SVN: r%s
12215 else {
12216 const char* git = get_git_hash();
12217 if( git[0] != UNKNOWN_VERSION )
12218 sprintf(buf,msg_txt(sd,1295),"Git Hash: ",git); //rAthena Version Git Hash: %s
12219 else
12220 sprintf(buf,"%s",msg_txt(sd,1296)); //Cannot determine SVN/Git version.
12221 }
12222 clif_displaymessage(sd->fd,buf);
12223}
12224
12225/** [Cydh]
12226* Timer for bonus_script
12227* @param tid
12228* @param tick
12229* @param id
12230* @param data
12231**/
12232int pc_bonus_script_timer(int tid, unsigned int tick, int id, intptr_t data) {
12233 uint8 i = (uint8)data;
12234 struct map_session_data *sd;
12235
12236 sd = map_id2sd(id);
12237 if (!sd) {
12238 ShowDebug("pc_bonus_script_timer: Null pointer id: %d data: %d\n",id,data);
12239 return 0;
12240 }
12241
12242 if (i > MAX_PC_BONUS_SCRIPT|| !(&sd->bonus_script[i]) || !sd->bonus_script[i].script) {
12243 ShowDebug("pc_bonus_script_timer: Invalid index %d\n",i);
12244 return 0;
12245 }
12246
12247 pc_bonus_script_remove(sd,i);
12248 status_calc_pc(sd,false);
12249 return 0;
12250}
12251
12252/** [Cydh]
12253* Remove bonus_script data from sd (not deleting timer)
12254* @param sd: Target player
12255* @param i: Bonus script index
12256**/
12257void pc_bonus_script_remove(struct map_session_data *sd, uint8 i) {
12258 if (!sd || i >= MAX_PC_BONUS_SCRIPT)
12259 return;
12260
12261 script_free_code(sd->bonus_script[i].script);
12262 memset(&sd->bonus_script[i].script,0,sizeof(sd->bonus_script[i].script));
12263 sd->bonus_script[i].script_str[0] = '\0';
12264 sd->bonus_script[i].tick = 0;
12265 sd->bonus_script[i].tid = 0;
12266 sd->bonus_script[i].flag = 0;
12267 clif_status_change(&sd->bl,sd->bonus_script[i].icon,0,0,0,0,0);
12268 sd->bonus_script[i].icon = SI_BLANK;
12269}
12270
12271/** [Cydh]
12272* Check then clear all active timer(s) of bonus_script data from player based on reason
12273* @param sd: Target player
12274* @param flag: Reason to remove the bonus_script. e_bonus_script_flags or e_bonus_script_types
12275**/
12276void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag) {
12277 uint8 i, count = 0;
12278 if (!sd)
12279 return;
12280
12281 for (i = 0; i < MAX_PC_BONUS_SCRIPT; i++) {
12282 if (&sd->bonus_script[i] && sd->bonus_script[i].script &&
12283 (sd->bonus_script[i].flag&flag || //Remove bonus script based on e_bonus_script_flags
12284 (sd->bonus_script[i].type && (
12285 (flag&BONUS_FLAG_REM_BUFF && sd->bonus_script[i].type == 1) || //Remove bonus script based on buff type
12286 (flag&BONUS_FLAG_REM_DEBUFF && sd->bonus_script[i].type == 2)) //Remove bonus script based on debuff type
12287 )))
12288 {
12289 delete_timer(sd->bonus_script[i].tid,pc_bonus_script_timer);
12290 pc_bonus_script_remove(sd,i);
12291 count++;
12292 }
12293 }
12294 if (count && !(flag&BONUS_FLAG_REM_ON_LOGOUT)) //Don't need to do this if log out
12295 status_calc_pc(sd,false);
12296}
12297
12298/** [Cydh]
12299 * Gives/removes SC_BASILICA when player steps in/out the cell with 'cell_basilica'
12300 * @param sd: Target player
12301 */
12302void pc_cell_basilica(struct map_session_data *sd) {
12303 nullpo_retv(sd);
12304
12305 if (!map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKBASILICA)) {
12306 if (&sd->sc && sd->sc.data[SC_BASILICA])
12307 status_change_end(&sd->bl,SC_BASILICA,INVALID_TIMER);
12308 }
12309 else if (!(&sd->sc) || !sd->sc.data[SC_BASILICA])
12310 sc_start(&sd->bl,&sd->bl,SC_BASILICA,100,0,-1);
12311}
12312
12313/** [Cydh]
12314 * Get maximum specified parameter for specified class
12315 * @param class_: sd->class
12316 * @param sex: sd->status.sex
12317 * @param flag: parameter will be checked
12318 * @return max_param
12319 */
12320short pc_maxparameter(struct map_session_data *sd, enum e_params param) {
12321 int idx = -1, class_ = sd->class_;
12322
12323 if ((idx = pc_class2idx(pc_mapid2jobid(class_,sd->status.sex))) >= 0) {
12324 short max_param = 0;
12325 switch (param) {
12326 case PARAM_STR: max_param = job_info[idx].max_param.str; break;
12327 case PARAM_AGI: max_param = job_info[idx].max_param.agi; break;
12328 case PARAM_VIT: max_param = job_info[idx].max_param.vit; break;
12329 case PARAM_INT: max_param = job_info[idx].max_param.int_; break;
12330 case PARAM_DEX: max_param = job_info[idx].max_param.dex; break;
12331 case PARAM_LUK: max_param = job_info[idx].max_param.luk; break;
12332 }
12333 if (max_param > 0)
12334 return max_param;
12335 }
12336
12337 return ((class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO || (class_&MAPID_UPPERMASK) == MAPID_REBELLION) ? battle_config.max_extended_parameter :
12338 ((class_&JOBL_THIRD) ? ((class_&JOBL_UPPER) ? battle_config.max_third_trans_parameter : ((class_&JOBL_BABY) ? battle_config.max_baby_third_parameter : battle_config.max_third_parameter)) :
12339 ((class_&JOBL_BABY) ? battle_config.max_baby_parameter :
12340 ((class_&JOBL_UPPER) ? battle_config.max_trans_parameter : battle_config.max_parameter)));
12341}
12342
12343/*==========================================
12344 * pc Init/Terminate
12345 *------------------------------------------*/
12346void do_final_pc(void) {
12347
12348 db_destroy(itemcd_db);
12349
12350 do_final_pc_groups();
12351 return;
12352}
12353
12354int do_init_pc(void) {
12355
12356 itemcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
12357
12358 pc_readdb();
12359 pc_read_motd(); // Read MOTD [Valaris]
12360
12361 memset(pvpevent_fame_list, 0, sizeof(pvpevent_fame_list));
12362
12363 add_timer_func_list(pc_invincible_timer, "pc_invincible_timer");
12364 add_timer_func_list(pc_eventtimer, "pc_eventtimer");
12365 add_timer_func_list(pc_inventory_rental_end, "pc_inventory_rental_end");
12366 add_timer_func_list(pc_calc_pvprank_timer, "pc_calc_pvprank_timer");
12367 add_timer_func_list(pc_autosave, "pc_autosave");
12368 add_timer_func_list(pc_spiritball_timer, "pc_spiritball_timer");
12369 add_timer_func_list(pc_follow_timer, "pc_follow_timer");
12370 add_timer_func_list(pc_endautobonus, "pc_endautobonus");
12371 add_timer_func_list(pc_talisman_timer, "pc_talisman_timer");
12372
12373 add_timer(gettick() + autosave_interval, pc_autosave, 0, 0);
12374
12375 // 0=day, 1=night [Yor]
12376 night_flag = battle_config.night_at_start ? 1 : 0;
12377
12378 if (battle_config.day_duration > 0 && battle_config.night_duration > 0) {
12379 int day_duration = battle_config.day_duration;
12380 int night_duration = battle_config.night_duration;
12381 // add night/day timer [Yor]
12382 add_timer_func_list(map_day_timer, "map_day_timer");
12383 add_timer_func_list(map_night_timer, "map_night_timer");
12384
12385 day_timer_tid = add_timer_interval(gettick() + (night_flag ? 0 : day_duration) + night_duration, map_day_timer, 0, 0, day_duration + night_duration);
12386 night_timer_tid = add_timer_interval(gettick() + day_duration + (night_flag ? night_duration : 0), map_night_timer, 0, 0, day_duration + night_duration);
12387 }
12388
12389 do_init_pc_groups();
12390
12391 return 0;
12392}
12393
12394void pc_lgp_update_settings (struct map_session_data * sd)
12395{
12396 WFIFOHEAD(sd->fd, 12);
12397 WFIFOW(sd->fd,0) = 0x8D;
12398 WFIFOW(sd->fd,2) = 12;
12399 WFIFOL(sd->fd,4) = sd->lgp_settings;
12400 WFIFOL(sd->fd,8) = 0x1;
12401 WFIFOSET(sd->fd, 12);
12402}