PageRenderTime 105ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 1ms

/src/map/pc.c

https://gitlab.com/evol/evol-server-code-old
C | 9663 lines | 7776 code | 1063 blank | 824 comment | 2852 complexity | 32a4509e89109e4b9776d128ed008b02 MD5 | raw file
Possible License(s): GPL-2.0
  1. // $Id: pc.c 101 2004-09-25 17:57:22Z Valaris $
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <time.h>
  7. #include "socket.h" // [Valaris]
  8. #include "timer.h"
  9. #include "db.h"
  10. #include "malloc.h"
  11. #include "nullpo.h"
  12. #include "strlib.h"
  13. #include "atcommand.h"
  14. #include "battle.h"
  15. #include "chat.h"
  16. #include "chrif.h"
  17. #include "clif.h"
  18. #include "guild.h"
  19. #include "intif.h"
  20. #include "itemdb.h"
  21. #include "map.h"
  22. #include "mob.h"
  23. #include "npc.h"
  24. #include "party.h"
  25. #include "pc.h"
  26. #include "script.h"
  27. #include "skill.h"
  28. #include "storage.h"
  29. #include "trade.h"
  30. #ifdef MEMWATCH
  31. #include "memwatch.h"
  32. #endif
  33. #define PVP_CALCRANK_INTERVAL 1000 // PVP順位計算の間隔
  34. //define it here, since the ifdef only occurs in this file
  35. #define USE_ASTRAL_SOUL_SKILL
  36. #define STATE_BLIND 0x10
  37. #ifdef USE_ASTRAL_SOUL_SKILL
  38. #define MAGIC_SKILL_THRESHOLD 200 // [fate] At this threshold, the Astral Soul skill kicks in
  39. #endif
  40. #define MAP_LOG_STATS(sd, suffix) \
  41. MAP_LOG_PC(sd, "STAT %d %d %d %d %d %d " suffix, \
  42. sd->status.str, sd->status.agi, sd->status.vit, sd->status.int_, sd->status.dex, sd->status.luk)
  43. #define MAP_LOG_XP(sd, suffix) \
  44. MAP_LOG_PC(sd, "XP %d %d JOB %d %d %d ZENY %d + %d " suffix, \
  45. sd->status.base_level, sd->status.base_exp, sd->status.job_level, sd->status.job_exp, sd->status.skill_point, sd->status.zeny, pc_readaccountreg(sd, "BankAccount"))
  46. #define MAP_LOG_MAGIC(sd, suffix) \
  47. MAP_LOG_PC(sd, "MAGIC %d %d %d %d %d %d EXP %d %d " suffix, \
  48. sd->status.skill[TMW_MAGIC].lv, \
  49. sd->status.skill[TMW_MAGIC_LIFE].lv, \
  50. sd->status.skill[TMW_MAGIC_WAR].lv, \
  51. sd->status.skill[TMW_MAGIC_TRANSMUTE].lv, \
  52. sd->status.skill[TMW_MAGIC_NATURE].lv, \
  53. sd->status.skill[TMW_MAGIC_ETHER].lv, \
  54. pc_readglobalreg(sd, "MAGIC_EXPERIENCE") & 0xffff, \
  55. (pc_readglobalreg(sd, "MAGIC_EXPERIENCE") >> 24) & 0xff)
  56. static int max_weight_base[MAX_PC_CLASS];
  57. static int hp_coefficient[MAX_PC_CLASS];
  58. static int hp_coefficient2[MAX_PC_CLASS];
  59. static int hp_sigma_val[MAX_PC_CLASS][MAX_LEVEL];
  60. static int sp_coefficient[MAX_PC_CLASS];
  61. static int aspd_base[MAX_PC_CLASS][20];
  62. static char job_bonus[3][MAX_PC_CLASS][MAX_LEVEL];
  63. static int exp_table[14][MAX_LEVEL];
  64. static char statp[255][7];
  65. static struct
  66. {
  67. int id;
  68. int max;
  69. struct
  70. {
  71. short id, lv;
  72. } need[6];
  73. } skill_tree[3][MAX_PC_CLASS][100];
  74. static int atkmods[3][20]; // 武器ATKサイズ修正(size_fix.txt)
  75. static int refinebonus[5][3]; // 精?ボ?ナステ?ブル(refine_db.txt)
  76. static int percentrefinery[5][10]; // 精?成功率(refine_db.txt)
  77. static int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
  78. static int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
  79. static unsigned int equip_pos[MAX_EQUIP_SIZE] =
  80. { 0x0080, 0x0008, 0x0040, 0x0004, 0x0001, 0x0200, 0x0100, 0x0010, 0x0020,
  81. 0x0002, 0x8000, 0x0400, 0x0800
  82. };
  83. int pc_attack_timer (int tid, unsigned int tick, int id, int data);
  84. //static struct dbt *gm_account_db;
  85. static struct gm_account *gm_account = NULL;
  86. static int GM_num = 0;
  87. const int MAX_PLAYER_CLASS = 8;
  88. int pc_isGM (struct map_session_data *sd)
  89. {
  90. // struct gm_account *p;
  91. int i;
  92. nullpo_retr (0, sd);
  93. /* p = numdb_search(gm_account_db, sd->status.account_id);
  94. if (p == NULL)
  95. return 0;
  96. return p->level;*/
  97. for (i = 0; i < GM_num; i++)
  98. if (gm_account[i].account_id == sd->status.account_id)
  99. return gm_account[i].level;
  100. return 0;
  101. }
  102. int pc_iskiller (struct map_session_data *src,
  103. struct map_session_data *target)
  104. {
  105. nullpo_retr (0, src);
  106. if (src->bl.type != BL_PC)
  107. return 0;
  108. if (src->special_state.killer)
  109. return 1;
  110. nullpo_retr (0, target);
  111. if (target->bl.type != BL_PC)
  112. return 0;
  113. if (target->special_state.killable)
  114. return 1;
  115. return 0;
  116. }
  117. int pc_set_gm_level (int account_id, int level)
  118. {
  119. int i;
  120. for (i = 0; i < GM_num; i++)
  121. {
  122. if (account_id == gm_account[i].account_id)
  123. {
  124. gm_account[i].level = level;
  125. return 0;
  126. }
  127. }
  128. GM_num++;
  129. gm_account = realloc (gm_account, sizeof (struct gm_account) * GM_num);
  130. if (!gm_account)
  131. {
  132. printf("out of memory pc_set_gm_level\n");
  133. exit(1);
  134. }
  135. gm_account[GM_num - 1].account_id = account_id;
  136. gm_account[GM_num - 1].level = level;
  137. return 0;
  138. }
  139. int pc_getrefinebonus (int lv, int type)
  140. {
  141. if (lv >= 0 && lv < 5 && type >= 0 && type < 3)
  142. return refinebonus[lv][type];
  143. return 0;
  144. }
  145. static int distance (int x0, int y0, int x1, int y1)
  146. {
  147. int dx, dy;
  148. dx = abs (x0 - x1);
  149. dy = abs (y0 - y1);
  150. return dx > dy ? dx : dy;
  151. }
  152. static int pc_invincible_timer (int tid, unsigned int tick __attribute__ ((unused)),
  153. int id, int data __attribute__ ((unused)))
  154. {
  155. struct map_session_data *sd;
  156. if ((sd = (struct map_session_data *) map_id2sd (id)) == NULL
  157. || sd->bl.type != BL_PC)
  158. return 1;
  159. if (sd->invincible_timer != tid)
  160. {
  161. if (battle_config.error_log)
  162. printf ("invincible_timer %d != %d\n", sd->invincible_timer, tid);
  163. return 0;
  164. }
  165. sd->invincible_timer = -1;
  166. return 0;
  167. }
  168. int pc_setinvincibletimer (struct map_session_data *sd, int val)
  169. {
  170. nullpo_retr (0, sd);
  171. if (sd->invincible_timer != -1)
  172. delete_timer (sd->invincible_timer, pc_invincible_timer);
  173. sd->invincible_timer =
  174. add_timer (gettick () + val, pc_invincible_timer, sd->bl.id, 0);
  175. return 0;
  176. }
  177. int pc_delinvincibletimer (struct map_session_data *sd)
  178. {
  179. nullpo_retr (0, sd);
  180. if (sd->invincible_timer != -1)
  181. {
  182. delete_timer (sd->invincible_timer, pc_invincible_timer);
  183. sd->invincible_timer = -1;
  184. }
  185. return 0;
  186. }
  187. int pc_delattacktimer (struct map_session_data *sd)
  188. {
  189. nullpo_retr (0, sd);
  190. if (sd->attacktimer != -1)
  191. {
  192. delete_timer (sd->attacktimer, pc_attack_timer);
  193. sd->attacktimer = -1;
  194. }
  195. return 0;
  196. }
  197. static int pc_spiritball_timer (int tid, unsigned int tick __attribute__ ((unused)),
  198. int id, int data __attribute__ ((unused)))
  199. {
  200. struct map_session_data *sd;
  201. int i;
  202. if ((sd = (struct map_session_data *) map_id2sd (id)) == NULL
  203. || sd->bl.type != BL_PC)
  204. return 1;
  205. if (sd->spirit_timer[0] != tid)
  206. {
  207. if (battle_config.error_log)
  208. printf ("spirit_timer %d != %d\n", sd->spirit_timer[0], tid);
  209. return 0;
  210. }
  211. sd->spirit_timer[0] = -1;
  212. for (i = 1; i < sd->spiritball && i < MAX_SKILL_LEVEL; i++)
  213. {
  214. sd->spirit_timer[i - 1] = sd->spirit_timer[i];
  215. sd->spirit_timer[i] = -1;
  216. }
  217. sd->spiritball--;
  218. if (sd->spiritball < 0)
  219. sd->spiritball = 0;
  220. clif_spiritball (sd);
  221. return 0;
  222. }
  223. int pc_addspiritball (struct map_session_data *sd, int interval, int max)
  224. {
  225. nullpo_retr (0, sd);
  226. if (max > MAX_SKILL_LEVEL)
  227. max = MAX_SKILL_LEVEL;
  228. if (sd->spiritball < 0)
  229. sd->spiritball = 0;
  230. if (sd->spiritball >= max)
  231. {
  232. int i;
  233. if (sd->spirit_timer[0] != -1)
  234. {
  235. delete_timer (sd->spirit_timer[0], pc_spiritball_timer);
  236. sd->spirit_timer[0] = -1;
  237. }
  238. for (i = 1; i < max; i++)
  239. {
  240. sd->spirit_timer[i - 1] = sd->spirit_timer[i];
  241. sd->spirit_timer[i] = -1;
  242. }
  243. }
  244. else
  245. sd->spiritball++;
  246. if (sd->spiritball >= 1 && sd->spiritball <= MAX_SKILL_LEVEL)
  247. {
  248. sd->spirit_timer[sd->spiritball - 1] =
  249. add_timer (gettick () + interval, pc_spiritball_timer, sd->bl.id, 0);
  250. clif_spiritball (sd);
  251. }
  252. return 0;
  253. }
  254. int pc_delspiritball (struct map_session_data *sd, int count, int type)
  255. {
  256. int i;
  257. nullpo_retr (0, sd);
  258. if (sd->spiritball <= 0)
  259. {
  260. sd->spiritball = 0;
  261. return 0;
  262. }
  263. if (count > sd->spiritball)
  264. count = sd->spiritball;
  265. sd->spiritball -= count;
  266. if (count > MAX_SKILL_LEVEL)
  267. count = MAX_SKILL_LEVEL;
  268. for (i = 0; i < count; i++)
  269. {
  270. if (sd->spirit_timer[i] != -1)
  271. {
  272. delete_timer (sd->spirit_timer[i], pc_spiritball_timer);
  273. sd->spirit_timer[i] = -1;
  274. }
  275. }
  276. for (i = count; i < MAX_SKILL_LEVEL; i++)
  277. {
  278. sd->spirit_timer[i - count] = sd->spirit_timer[i];
  279. sd->spirit_timer[i] = -1;
  280. }
  281. if (!type)
  282. clif_spiritball (sd);
  283. return 0;
  284. }
  285. int pc_setrestartvalue (struct map_session_data *sd, int type)
  286. {
  287. //?生や養子の場合の元の職業を算出する
  288. struct pc_base_job s_class;
  289. nullpo_retr (0, sd);
  290. s_class = pc_calc_base_job (sd->status.class);
  291. //-----------------------
  292. // 死亡した
  293. if (sd->special_state.restart_full_recover)
  294. { // オシリスカ?ド
  295. sd->status.hp = sd->status.max_hp;
  296. sd->status.sp = sd->status.max_sp;
  297. }
  298. else
  299. {
  300. if (s_class.job <= 5 && battle_config.restart_hp_rate == 0)
  301. { //ノビは半分回復
  302. sd->status.hp = (sd->status.max_hp) / 2;
  303. }
  304. else
  305. {
  306. if (battle_config.restart_hp_rate <= 0)
  307. sd->status.hp = 1;
  308. else
  309. {
  310. sd->status.hp =
  311. sd->status.max_hp * battle_config.restart_hp_rate / 100;
  312. if (sd->status.hp <= 0)
  313. sd->status.hp = 1;
  314. }
  315. }
  316. if (battle_config.restart_sp_rate > 0)
  317. {
  318. int sp = sd->status.max_sp * battle_config.restart_sp_rate / 100;
  319. if (sd->status.sp < sp)
  320. sd->status.sp = sp;
  321. }
  322. }
  323. if (type & 1)
  324. clif_updatestatus (sd, SP_HP);
  325. if (type & 1)
  326. clif_updatestatus (sd, SP_SP);
  327. /* removed exp penalty on spawn [Valaris] */
  328. if (type & 2 && sd->status.class > MAX_PLAYER_CLASS && battle_config.zeny_penalty > 0
  329. && !map[sd->bl.m].flag.nozenypenalty)
  330. {
  331. int zeny =
  332. (int) ((double) sd->status.zeny *
  333. (double) battle_config.zeny_penalty / 10000.);
  334. if (zeny < 1)
  335. zeny = 1;
  336. sd->status.zeny -= zeny;
  337. if (sd->status.zeny < 0)
  338. sd->status.zeny = 0;
  339. clif_updatestatus (sd, SP_ZENY);
  340. }
  341. sd->heal_xp = 0; // [Fate] Set gainable xp for healing this player to 0
  342. return 0;
  343. }
  344. /*==========================================
  345. * 自分をロックしているMOBの?を?える(foreachclient)
  346. *------------------------------------------
  347. */
  348. static int pc_counttargeted_sub (struct block_list *bl, va_list ap)
  349. {
  350. int id, *c, target_lv;
  351. struct block_list *src;
  352. nullpo_retr (0, bl);
  353. nullpo_retr (0, ap);
  354. id = va_arg (ap, int);
  355. nullpo_retr (0, c = va_arg (ap, int *));
  356. src = va_arg (ap, struct block_list *);
  357. target_lv = va_arg (ap, int);
  358. if (id == bl->id || (src && id == src->id))
  359. return 0;
  360. if (bl->type == BL_PC)
  361. {
  362. struct map_session_data *sd = (struct map_session_data *) bl;
  363. if (sd && sd->attacktarget == id && sd->attacktimer != -1
  364. && sd->attacktarget_lv >= target_lv)
  365. (*c)++;
  366. }
  367. else if (bl->type == BL_MOB)
  368. {
  369. struct mob_data *md = (struct mob_data *) bl;
  370. if (md && md->target_id == id && md->timer != -1
  371. && md->state.state == MS_ATTACK && md->target_lv >= target_lv)
  372. (*c)++;
  373. //printf("md->target_lv:%d, target_lv:%d\n",((struct mob_data *)bl)->target_lv,target_lv);
  374. }
  375. return 0;
  376. }
  377. int pc_counttargeted (struct map_session_data *sd, struct block_list *src,
  378. int target_lv)
  379. {
  380. int c = 0;
  381. nullpo_retr (0, sd);
  382. map_foreachinarea (pc_counttargeted_sub, sd->bl.m,
  383. sd->bl.x - AREA_SIZE, sd->bl.y - AREA_SIZE,
  384. sd->bl.x + AREA_SIZE, sd->bl.y + AREA_SIZE, 0,
  385. sd->bl.id, &c, src, target_lv);
  386. return c;
  387. }
  388. /*==========================================
  389. * ロ?カルプロトタイプ宣言 (必要な物のみ)
  390. *------------------------------------------
  391. */
  392. static int pc_walktoxy_sub (struct map_session_data *);
  393. /*==========================================
  394. * saveに必要なステ?タス修正を行なう
  395. *------------------------------------------
  396. */
  397. int pc_makesavestatus (struct map_session_data *sd)
  398. {
  399. nullpo_retr (0, sd);
  400. // 服の色は色?弊害が多いので保存?象にはしない
  401. if (!battle_config.save_clothcolor)
  402. sd->status.clothes_color = 0;
  403. // 死亡?態だったのでhpを1、位置をセ?ブ場所に?更
  404. if (pc_isdead (sd))
  405. {
  406. pc_setrestartvalue (sd, 0);
  407. memcpy (&sd->status.last_point, &sd->status.save_point,
  408. sizeof (sd->status.last_point));
  409. }
  410. else
  411. {
  412. memcpy (sd->status.last_point.map, sd->mapname, 24);
  413. sd->status.last_point.x = sd->bl.x;
  414. sd->status.last_point.y = sd->bl.y;
  415. }
  416. // セ?ブ禁止マップだったので指定位置に移動
  417. if (map[sd->bl.m].flag.nosave)
  418. {
  419. struct map_data *m = &map[sd->bl.m];
  420. if (strcmp (m->save.map, "SavePoint") == 0)
  421. memcpy (&sd->status.last_point, &sd->status.save_point,
  422. sizeof (sd->status.last_point));
  423. else
  424. memcpy (&sd->status.last_point, &m->save,
  425. sizeof (sd->status.last_point));
  426. }
  427. //マナ?ポイントがプラスだった場合0に
  428. if (battle_config.muting_players && sd->status.manner > 0)
  429. sd->status.manner = 0;
  430. return 0;
  431. }
  432. /*==========================================
  433. * 接?時の初期化
  434. *------------------------------------------
  435. */
  436. int pc_setnewpc (struct map_session_data *sd, int account_id, int char_id,
  437. int login_id1, int client_tick, int sex,
  438. int fd __attribute__ ((unused)))
  439. {
  440. nullpo_retr (0, sd);
  441. sd->bl.id = account_id;
  442. sd->char_id = char_id;
  443. sd->login_id1 = login_id1;
  444. sd->login_id2 = 0; // at this point, we can not know the value :(
  445. sd->client_tick = client_tick;
  446. sd->sex = sex;
  447. sd->state.auth = 0;
  448. sd->bl.type = BL_PC;
  449. sd->canact_tick = sd->canmove_tick = gettick ();
  450. sd->canlog_tick = gettick ();
  451. sd->state.waitingdisconnect = 0;
  452. return 0;
  453. }
  454. int pc_equippoint (struct map_session_data *sd, int n)
  455. {
  456. int ep = 0;
  457. //?生や養子の場合の元の職業を算出する
  458. struct pc_base_job s_class;
  459. nullpo_retr (0, sd);
  460. if (n < 0 || n >= MAX_INVENTORY || !sd->inventory_data[n])
  461. return 0;
  462. s_class = pc_calc_base_job (sd->status.class);
  463. ep = sd->inventory_data[n]->equip;
  464. if ((sd->inventory_data[n]->look == 1 || sd->inventory_data[n]->look == 2
  465. || sd->inventory_data[n]->look == 6) && (ep == 2
  466. &&
  467. (pc_checkskill (sd, AS_LEFT)
  468. > 0 || s_class.job == 12)))
  469. {
  470. return 34;
  471. }
  472. return ep;
  473. }
  474. int pc_setinventorydata (struct map_session_data *sd)
  475. {
  476. int i, id;
  477. nullpo_retr (0, sd);
  478. for (i = 0; i < MAX_INVENTORY; i++)
  479. {
  480. id = sd->status.inventory[i].nameid;
  481. sd->inventory_data[i] = itemdb_search (id);
  482. }
  483. return 0;
  484. }
  485. int pc_calcweapontype (struct map_session_data *sd)
  486. {
  487. nullpo_retr (0, sd);
  488. if (sd->weapontype1 != 0 && sd->weapontype2 == 0)
  489. sd->status.weapon = sd->weapontype1;
  490. if (sd->weapontype1 == 0 && sd->weapontype2 != 0) // 左手武器 Only
  491. sd->status.weapon = sd->weapontype2;
  492. else if (sd->weapontype1 == 1 && sd->weapontype2 == 1) // 双短剣
  493. sd->status.weapon = 0x11;
  494. else if (sd->weapontype1 == 2 && sd->weapontype2 == 2) // 双単手剣
  495. sd->status.weapon = 0x12;
  496. else if (sd->weapontype1 == 6 && sd->weapontype2 == 6) // 双単手斧
  497. sd->status.weapon = 0x13;
  498. else if ((sd->weapontype1 == 1 && sd->weapontype2 == 2) || (sd->weapontype1 == 2 && sd->weapontype2 == 1)) // 短剣 - 単手剣
  499. sd->status.weapon = 0x14;
  500. else if ((sd->weapontype1 == 1 && sd->weapontype2 == 6) || (sd->weapontype1 == 6 && sd->weapontype2 == 1)) // 短剣 - 斧
  501. sd->status.weapon = 0x15;
  502. else if ((sd->weapontype1 == 2 && sd->weapontype2 == 6) || (sd->weapontype1 == 6 && sd->weapontype2 == 2)) // 単手剣 - 斧
  503. sd->status.weapon = 0x16;
  504. else
  505. sd->status.weapon = sd->weapontype1;
  506. return 0;
  507. }
  508. int pc_setequipindex (struct map_session_data *sd)
  509. {
  510. int i, j;
  511. nullpo_retr (0, sd);
  512. for (i = 0; i < MAX_EQUIP_SIZE; i++)
  513. sd->equip_index[i] = -1;
  514. for (i = 0; i < MAX_INVENTORY; i++)
  515. {
  516. if (sd->status.inventory[i].nameid <= 0)
  517. continue;
  518. if (sd->status.inventory[i].equip)
  519. {
  520. for (j = 0; j < MAX_EQUIP_SIZE; j++)
  521. if (sd->status.inventory[i].equip & equip_pos[j])
  522. sd->equip_index[j] = i;
  523. if (sd->status.inventory[i].equip & 0x0002)
  524. {
  525. if (sd->inventory_data[i])
  526. sd->weapontype1 = sd->inventory_data[i]->look;
  527. else
  528. sd->weapontype1 = 0;
  529. }
  530. if (sd->status.inventory[i].equip & 0x0020)
  531. {
  532. if (sd->inventory_data[i])
  533. {
  534. if (sd->inventory_data[i]->type == 4)
  535. {
  536. if (sd->status.inventory[i].equip == 0x0020)
  537. sd->weapontype2 = sd->inventory_data[i]->look;
  538. else
  539. sd->weapontype2 = 0;
  540. }
  541. else
  542. sd->weapontype2 = 0;
  543. }
  544. else
  545. sd->weapontype2 = 0;
  546. }
  547. }
  548. }
  549. pc_calcweapontype (sd);
  550. return 0;
  551. }
  552. int pc_isequip (struct map_session_data *sd, int n)
  553. {
  554. struct item_data *item;
  555. struct status_change *sc_data;
  556. //転生や養子の場合の元の職業を算出する
  557. nullpo_retr (0, sd);
  558. if (n < 0 || n >= MAX_INVENTORY)
  559. return 0;
  560. item = sd->inventory_data[n];
  561. sc_data = battle_get_sc_data (&sd->bl);
  562. //s_class = pc_calc_base_job(sd->status.class);
  563. if (battle_config.gm_allequip > 0
  564. && pc_isGM (sd) >= battle_config.gm_allequip)
  565. return 1;
  566. if (item == NULL)
  567. return 0;
  568. if (item->sex != 2 && sd->status.sex != item->sex)
  569. return 0;
  570. if (item->elv > 0 && sd->status.base_level < item->elv)
  571. return 0;
  572. if (map[sd->bl.m].flag.pvp
  573. && (item->flag.no_equip == 1 || item->flag.no_equip == 3))
  574. return 0;
  575. if (map[sd->bl.m].flag.gvg
  576. && (item->flag.no_equip == 2 || item->flag.no_equip == 3))
  577. return 0;
  578. if (item->equip & 0x0002 && sc_data
  579. && sc_data[SC_STRIPWEAPON].timer != -1)
  580. return 0;
  581. if (item->equip & 0x0020 && sc_data
  582. && sc_data[SC_STRIPSHIELD].timer != -1)
  583. return 0;
  584. if (item->equip & 0x0010 && sc_data && sc_data[SC_STRIPARMOR].timer != -1)
  585. return 0;
  586. if (item->equip & 0x0100 && sc_data && sc_data[SC_STRIPHELM].timer != -1)
  587. return 0;
  588. return 1;
  589. }
  590. /*==========================================
  591. * Weapon Breaking [Valaris]
  592. *------------------------------------------
  593. */
  594. int pc_breakweapon (struct map_session_data *sd)
  595. {
  596. struct item_data *item;
  597. char output[255];
  598. int i;
  599. if (sd == NULL)
  600. return -1;
  601. if (sd->unbreakable >= MRAND (100))
  602. return 0;
  603. if (sd->sc_data && sd->sc_data[SC_CP_WEAPON].timer != -1)
  604. return 0;
  605. for (i = 0; i < MAX_INVENTORY; i++)
  606. {
  607. if (sd->status.inventory[i].equip
  608. && sd->status.inventory[i].equip & 0x0002
  609. && !sd->status.inventory[i].broken)
  610. {
  611. item = sd->inventory_data[i];
  612. if (!item)
  613. continue;
  614. sd->status.inventory[i].broken = 1;
  615. //pc_unequipitem(sd,i,0);
  616. if (sd->status.inventory[i].equip
  617. && sd->status.inventory[i].equip & 0x0002
  618. && sd->status.inventory[i].broken == 1)
  619. {
  620. sprintf (output, "%s has broken.", item->jname);
  621. clif_emotion (&sd->bl, 23);
  622. clif_displaymessage (sd->fd, output);
  623. clif_equiplist (sd);
  624. skill_status_change_start (&sd->bl, SC_BROKNWEAPON, 0, 0, 0,
  625. 0, 0, 0);
  626. }
  627. }
  628. if (sd->status.inventory[i].broken == 1)
  629. return 0;
  630. }
  631. return 0;
  632. }
  633. /*==========================================
  634. * Armor Breaking [Valaris]
  635. *------------------------------------------
  636. */
  637. int pc_breakarmor (struct map_session_data *sd)
  638. {
  639. struct item_data *item;
  640. char output[255];
  641. int i;
  642. if (sd == NULL)
  643. return -1;
  644. if (sd->unbreakable >= MRAND (100))
  645. return 0;
  646. if (sd->sc_data && sd->sc_data[SC_CP_ARMOR].timer != -1)
  647. return 0;
  648. for (i = 0; i < MAX_INVENTORY; i++)
  649. {
  650. if (sd->status.inventory[i].equip
  651. && sd->status.inventory[i].equip & 0x0010
  652. && !sd->status.inventory[i].broken)
  653. {
  654. item = sd->inventory_data[i];
  655. if (!item)
  656. continue;
  657. sd->status.inventory[i].broken = 1;
  658. //pc_unequipitem(sd,i,0);
  659. if (sd->status.inventory[i].equip
  660. && sd->status.inventory[i].equip & 0x0010
  661. && sd->status.inventory[i].broken == 1)
  662. {
  663. sprintf (output, "%s has broken.", item->jname);
  664. clif_emotion (&sd->bl, 23);
  665. clif_displaymessage (sd->fd, output);
  666. clif_equiplist (sd);
  667. skill_status_change_start (&sd->bl, SC_BROKNARMOR, 0, 0, 0, 0,
  668. 0, 0);
  669. }
  670. }
  671. if (sd->status.inventory[i].broken == 1)
  672. return 0;
  673. }
  674. return 0;
  675. }
  676. /*==========================================
  677. * session idに問題無し
  678. * char鯖から送られてきたステータスを設定
  679. *------------------------------------------
  680. */
  681. int pc_authok (int id, int login_id2, time_t connect_until_time,
  682. short tmw_version, struct mmo_charstatus *st)
  683. {
  684. struct map_session_data *sd = NULL;
  685. // struct party *p;
  686. // struct guild *g;
  687. int i;
  688. unsigned long tick = gettick ();
  689. struct sockaddr_in sai;
  690. socklen_t sa_len = sizeof(struct sockaddr);
  691. sd = map_id2sd (id);
  692. if (sd == NULL)
  693. return 1;
  694. sd->login_id2 = login_id2;
  695. sd->tmw_version = tmw_version;
  696. memcpy (&sd->status, st, sizeof (*st));
  697. if (sd->status.sex != sd->sex)
  698. {
  699. clif_authfail_fd (sd->fd, 0);
  700. return 1;
  701. }
  702. MAP_LOG_STATS (sd, "LOGIN");
  703. MAP_LOG_XP (sd, "LOGIN");
  704. MAP_LOG_MAGIC (sd, "LOGIN");
  705. memset (&sd->state, 0, sizeof (sd->state));
  706. // 基本的な初期化
  707. sd->state.connect_new = 1;
  708. sd->bl.prev = sd->bl.next = NULL;
  709. sd->weapontype1 = sd->weapontype2 = 0;
  710. sd->view_class = sd->status.class;
  711. sd->speed = DEFAULT_WALK_SPEED;
  712. sd->state.dead_sit = 0;
  713. sd->dir = 0;
  714. sd->head_dir = 0;
  715. sd->state.auth = 1;
  716. sd->walktimer = -1;
  717. sd->attacktimer = -1;
  718. sd->followtimer = -1; // [MouseJstr]
  719. sd->skilltimer = -1;
  720. sd->skillitem = -1;
  721. sd->skillitemlv = -1;
  722. sd->invincible_timer = -1;
  723. sd->sg_count = 0;
  724. sd->deal_locked = 0;
  725. sd->trade_partner = 0;
  726. sd->inchealhptick = 0;
  727. sd->inchealsptick = 0;
  728. sd->hp_sub = 0;
  729. sd->sp_sub = 0;
  730. sd->quick_regeneration_hp.amount = 0;
  731. sd->quick_regeneration_sp.amount = 0;
  732. sd->heal_xp = 0;
  733. sd->inchealspirithptick = 0;
  734. sd->inchealspiritsptick = 0;
  735. sd->canact_tick = tick;
  736. sd->canmove_tick = tick;
  737. sd->attackabletime = tick;
  738. /* We don't want players bypassing spell restrictions. [remoitnane] */
  739. sd->cast_tick = tick + pc_readglobalreg (sd, "MAGIC_CAST_TICK");
  740. sd->doridori_counter = 0;
  741. sd->spiritball = 0;
  742. for (i = 0; i < MAX_SKILL_LEVEL; i++)
  743. sd->spirit_timer[i] = -1;
  744. for (i = 0; i < MAX_SKILLTIMERSKILL; i++)
  745. sd->skilltimerskill[i].timer = -1;
  746. memset (&sd->dev, 0, sizeof (struct square));
  747. for (i = 0; i < 5; i++)
  748. {
  749. sd->dev.val1[i] = 0;
  750. sd->dev.val2[i] = 0;
  751. }
  752. // アカウント変数の送信要求
  753. intif_request_accountreg (sd);
  754. // アイテムチェック
  755. pc_setinventorydata (sd);
  756. pc_checkitem (sd);
  757. // ステータス異常の初期化
  758. for (i = 0; i < MAX_STATUSCHANGE; i++)
  759. {
  760. sd->sc_data[i].timer = -1;
  761. sd->sc_data[i].val1 = sd->sc_data[i].val2 = sd->sc_data[i].val3 =
  762. sd->sc_data[i].val4 = 0;
  763. }
  764. sd->sc_count = 0;
  765. if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
  766. (pc_isGM (sd) >= get_atcommand_level (AtCommand_Hide)))
  767. sd->status.option &= (OPTION_MASK | OPTION_HIDE);
  768. else
  769. sd->status.option &= OPTION_MASK;
  770. // スキルユニット関係の初期化
  771. memset (sd->skillunit, 0, sizeof (sd->skillunit));
  772. memset (sd->skillunittick, 0, sizeof (sd->skillunittick));
  773. // init ignore list
  774. memset (sd->ignore, 0, sizeof (sd->ignore));
  775. // パーティー関係の初期化
  776. sd->party_sended = 0;
  777. sd->party_invite = 0;
  778. sd->party_x = -1;
  779. sd->party_y = -1;
  780. sd->party_hp = -1;
  781. // ギルド関係の初期化
  782. sd->guild_sended = 0;
  783. sd->guild_invite = 0;
  784. sd->guild_alliance = 0;
  785. // イベント関係の初期化
  786. memset (sd->eventqueue, 0, sizeof (sd->eventqueue));
  787. for (i = 0; i < MAX_EVENTTIMER; i++)
  788. sd->eventtimer[i] = -1;
  789. // 位置の設定
  790. pc_setpos (sd, sd->status.last_point.map, sd->status.last_point.x,
  791. sd->status.last_point.y, 0);
  792. // パーティ、ギルドデータの要求
  793. if (sd->status.party_id > 0
  794. && party_search (sd->status.party_id) == NULL)
  795. party_request_info (sd->status.party_id);
  796. if (sd->status.guild_id > 0
  797. && guild_search (sd->status.guild_id) == NULL)
  798. guild_request_info (sd->status.guild_id);
  799. // pvpの設定
  800. sd->pvp_rank = 0;
  801. sd->pvp_point = 0;
  802. sd->pvp_timer = -1;
  803. // 通知
  804. clif_authok (sd);
  805. map_addnickdb (sd);
  806. if (map_charid2nick (sd->status.char_id) == NULL)
  807. map_addchariddb (sd->status.char_id, sd->status.name);
  808. //スパノビ用死にカウンターのスクリプト変数からの読み出しとsdへのセット
  809. sd->die_counter = pc_readglobalreg (sd, "PC_DIE_COUNTER");
  810. if (night_flag == 1)
  811. {
  812. char tmpstr[1024];
  813. strcpy (tmpstr, msg_txt (500)); // Actually, it's the night...
  814. clif_wis_message (sd->fd, wisp_server_name, tmpstr,
  815. strlen (tmpstr) + 1);
  816. sd->opt2 |= STATE_BLIND;
  817. }
  818. // ステータス初期計算など
  819. pc_calcstatus (sd, 1);
  820. if (pc_isGM (sd))
  821. {
  822. printf
  823. ("Connection accepted: character '%s' (account: %d; GM level %d).\n",
  824. sd->status.name, sd->status.account_id, pc_isGM (sd));
  825. clif_updatestatus (sd, SP_GM);
  826. }
  827. else
  828. printf ("Connection accepted: Character '%s' (account: %d).\n",
  829. sd->status.name, sd->status.account_id);
  830. // Message of the Dayの送信
  831. {
  832. char buf[256];
  833. FILE *fp;
  834. if ((fp = fopen_ (motd_txt, "r")) != NULL)
  835. {
  836. while (fgets (buf, sizeof (buf) - 1, fp) != NULL)
  837. {
  838. int i;
  839. for (i = 0; buf[i]; i++)
  840. {
  841. if (buf[i] == '\r' || buf[i] == '\n')
  842. {
  843. buf[i] = 0;
  844. break;
  845. }
  846. }
  847. clif_displaymessage (sd->fd, buf);
  848. }
  849. fclose_ (fp);
  850. }
  851. }
  852. sd->auto_ban_info.in_progress = 0;
  853. // Initialize antispam vars
  854. sd->chat_reset_due = sd->chat_lines_in = sd->chat_total_repeats =
  855. sd->chat_repeat_reset_due = 0;
  856. sd->chat_lastmsg[0] = '\0';
  857. memset(sd->flood_rates, 0, sizeof(sd->flood_rates));
  858. sd->packet_flood_reset_due = sd->packet_flood_in = 0;
  859. // Obtain IP address (if they are still connected)
  860. if (!getpeername(sd->fd, (struct sockaddr *)&sai, &sa_len))
  861. sd->ip = sai.sin_addr.s_addr;
  862. // message of the limited time of the account
  863. if (connect_until_time != 0)
  864. { // don't display if it's unlimited or unknow value
  865. char tmpstr[1024];
  866. strftime (tmpstr, sizeof (tmpstr) - 1, msg_txt (501), gmtime (&connect_until_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S."
  867. clif_wis_message (sd->fd, wisp_server_name, tmpstr,
  868. strlen (tmpstr) + 1);
  869. }
  870. pc_calcstatus (sd, 1);
  871. return 0;
  872. }
  873. /*==========================================
  874. * session idに問題ありなので後始末
  875. *------------------------------------------
  876. */
  877. int pc_authfail (int id)
  878. {
  879. struct map_session_data *sd;
  880. sd = map_id2sd (id);
  881. if (sd == NULL)
  882. return 1;
  883. clif_authfail_fd (sd->fd, 0);
  884. return 0;
  885. }
  886. static int pc_calc_skillpoint (struct map_session_data *sd)
  887. {
  888. int i, skill_points = 0;
  889. nullpo_retr (0, sd);
  890. for (i = 0; i < skill_pool_skills_size; i++)
  891. {
  892. if (skill_pool_skills[i] < 0 || skill_pool_skills[i] >= MAX_SKILL)
  893. continue;
  894. int lv = sd->status.skill[skill_pool_skills[i]].lv;
  895. if (lv)
  896. skill_points += ((lv * (lv - 1)) >> 1) - 1;
  897. }
  898. return skill_points;
  899. }
  900. /*==========================================
  901. * 覚えられるスキルの計算
  902. *------------------------------------------
  903. */
  904. int pc_calc_skilltree (struct map_session_data *sd)
  905. {
  906. int i, id = 0;
  907. int c = 0, s = 0;
  908. //転生や養子の場合の元の職業を算出する
  909. struct pc_base_job s_class;
  910. nullpo_retr (0, sd);
  911. s_class = pc_calc_base_job (sd->status.class);
  912. c = s_class.job;
  913. s = (s_class.upper == 1) ? 1 : 0; //転生以外は通常のスキル?
  914. if ((battle_config.skillup_limit)
  915. && ((c >= 0 && c < 23) || (c >= 4001 && c < 4023)
  916. || (c >= 4023 && c < 4045)))
  917. {
  918. int skill_point = pc_calc_skillpoint (sd);
  919. if (skill_point < 9)
  920. c = 0;
  921. else if ((sd->status.skill_point >= sd->status.job_level
  922. && skill_point < 58) && ((c > 6 && c < 23) || (c > 4007
  923. && c < 4023)
  924. || (c > 4029 && c < 4045)))
  925. {
  926. switch (c)
  927. {
  928. case 7:
  929. case 14:
  930. c = 1;
  931. break;
  932. case 8:
  933. case 15:
  934. c = 4;
  935. break;
  936. case 9:
  937. case 16:
  938. c = 2;
  939. break;
  940. case 10:
  941. case 18:
  942. c = 5;
  943. break;
  944. case 11:
  945. case 19:
  946. case 20:
  947. c = 3;
  948. break;
  949. case 12:
  950. case 17:
  951. c = 6;
  952. break;
  953. case 4008:
  954. case 4015:
  955. c = 4002;
  956. break;
  957. case 4009:
  958. case 4016:
  959. c = 4005;
  960. break;
  961. case 4010:
  962. case 4017:
  963. c = 4003;
  964. break;
  965. case 4011:
  966. case 4019:
  967. c = 4006;
  968. break;
  969. case 4012:
  970. case 4020:
  971. case 4021:
  972. c = 4004;
  973. break;
  974. case 4013:
  975. case 4018:
  976. c = 4007;
  977. break;
  978. case 4030:
  979. case 4037:
  980. c = 4024;
  981. break;
  982. case 4031:
  983. case 4038:
  984. c = 4027;
  985. break;
  986. case 4032:
  987. case 4039:
  988. c = 4025;
  989. break;
  990. case 4033:
  991. case 4040:
  992. c = 4028;
  993. break;
  994. case 4034:
  995. case 4041:
  996. case 4042:
  997. c = 4026;
  998. break;
  999. case 4035:
  1000. case 4043:
  1001. c = 4029;
  1002. break;
  1003. default:
  1004. break;
  1005. }
  1006. }
  1007. }
  1008. /*Comment this out for now, as we manage skills differently
  1009. * for(i=0;i<MAX_SKILL;i++)
  1010. * if (i < TMW_MAGIC || i > TMW_MAGIC_END){ // [Fate] This hack gets TMW magic working and persisted without bothering about the skill tree.
  1011. * if (sd->status.skill[i].flag != 13) sd->status.skill[i].id=0;
  1012. * if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){ // cardスキルなら、
  1013. * sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2; // 本当のlvに
  1014. * sd->status.skill[i].flag=0; // flagは0にしておく
  1015. * }
  1016. * }
  1017. */
  1018. if (battle_config.gm_allskill > 0
  1019. && pc_isGM (sd) >= battle_config.gm_allskill)
  1020. {
  1021. // 全てのスキル
  1022. for (i = 1; i < 158; i++)
  1023. sd->status.skill[i].id = i;
  1024. for (i = 210; i < 291; i++)
  1025. sd->status.skill[i].id = i;
  1026. for (i = 304; i < 337; i++)
  1027. sd->status.skill[i].id = i;
  1028. if (battle_config.enable_upper_class)
  1029. { //confで無効でなければ読み込む
  1030. for (i = 355; i < MAX_SKILL; i++)
  1031. sd->status.skill[i].id = i;
  1032. }
  1033. }
  1034. else
  1035. {
  1036. int flag;
  1037. // 通常の計算
  1038. do
  1039. {
  1040. flag = 0;
  1041. for (i = 0; (id = skill_tree[s][c][i].id) > 0; i++)
  1042. {
  1043. int f = 1;
  1044. if (!battle_config.skillfree)
  1045. {
  1046. int j;
  1047. for (j = 0; j < 5; j++)
  1048. {
  1049. if (skill_tree[s][c][i].need[j].id &&
  1050. pc_checkskill (sd,
  1051. skill_tree[s][c][i].need[j].id) <
  1052. skill_tree[s][c][i].need[j].lv)
  1053. f = 0;
  1054. }
  1055. }
  1056. if (f && sd->status.skill[id].id == 0)
  1057. {
  1058. sd->status.skill[id].id = id;
  1059. flag = 1;
  1060. }
  1061. }
  1062. }
  1063. while (flag);
  1064. }
  1065. // if(battle_config.etc_log)
  1066. // printf("calc skill_tree\n");
  1067. return 0;
  1068. }
  1069. /*==========================================
  1070. * 重量アイコンの確認
  1071. *------------------------------------------
  1072. */
  1073. int pc_checkweighticon (struct map_session_data *sd)
  1074. {
  1075. int flag = 0;
  1076. nullpo_retr (0, sd);
  1077. if (sd->weight * 2 >= sd->max_weight
  1078. && sd->sc_data[SC_FLYING_BACKPACK].timer == -1)
  1079. flag = 1;
  1080. if (sd->weight * 10 >= sd->max_weight * 9)
  1081. flag = 2;
  1082. if (flag == 1)
  1083. {
  1084. if (sd->sc_data[SC_WEIGHT50].timer == -1)
  1085. skill_status_change_start (&sd->bl, SC_WEIGHT50, 0, 0, 0, 0, 0,
  1086. 0);
  1087. }
  1088. else
  1089. {
  1090. skill_status_change_end (&sd->bl, SC_WEIGHT50, -1);
  1091. }
  1092. if (flag == 2)
  1093. {
  1094. if (sd->sc_data[SC_WEIGHT90].timer == -1)
  1095. skill_status_change_start (&sd->bl, SC_WEIGHT90, 0, 0, 0, 0, 0,
  1096. 0);
  1097. }
  1098. else
  1099. {
  1100. skill_status_change_end (&sd->bl, SC_WEIGHT90, -1);
  1101. }
  1102. return 0;
  1103. }
  1104. void pc_set_weapon_look (struct map_session_data *sd)
  1105. {
  1106. if (!sd)
  1107. return;
  1108. if (sd->attack_spell_override)
  1109. clif_changelook (&sd->bl, LOOK_WEAPON,
  1110. sd->attack_spell_look_override);
  1111. else
  1112. clif_changelook (&sd->bl, LOOK_WEAPON, sd->status.weapon);
  1113. }
  1114. /*==========================================
  1115. * パラメータ計算
  1116. * first==0の時、計算対象のパラメータが呼び出し前から
  1117. * 変 化した場合自動でsendするが、
  1118. * 能動的に変化させたパラメータは自前でsendするように
  1119. *------------------------------------------
  1120. */
  1121. int pc_calcstatus (struct map_session_data *sd, int first)
  1122. {
  1123. int b_speed, b_max_hp, b_max_sp, b_hp, b_sp, b_weight, b_max_weight,
  1124. b_paramb[6], b_parame[6], b_hit, b_flee;
  1125. int b_aspd, b_watk, b_def, b_watk2, b_def2, b_flee2, b_critical,
  1126. b_attackrange, b_matk1, b_matk2, b_mdef, b_mdef2, b_class;
  1127. int b_base_atk;
  1128. struct skill b_skill[MAX_SKILL];
  1129. int i, bl, index;
  1130. int skill, aspd_rate, wele, wele_, def_ele, refinedef = 0;
  1131. int str, dstr, dex;
  1132. struct pc_base_job s_class;
  1133. nullpo_retr (0, sd);
  1134. //転生や養子の場合の元の職業を算出する
  1135. s_class = pc_calc_base_job (sd->status.class);
  1136. b_speed = sd->speed;
  1137. b_max_hp = sd->status.max_hp;
  1138. b_max_sp = sd->status.max_sp;
  1139. b_hp = sd->status.hp;
  1140. b_sp = sd->status.sp;
  1141. b_weight = sd->weight;
  1142. b_max_weight = sd->max_weight;
  1143. memcpy (b_paramb, &sd->paramb, sizeof (b_paramb));
  1144. memcpy (b_parame, &sd->paramc, sizeof (b_parame));
  1145. memcpy (b_skill, &sd->status.skill, sizeof (b_skill));
  1146. b_hit = sd->hit;
  1147. b_flee = sd->flee;
  1148. b_aspd = sd->aspd;
  1149. b_watk = sd->watk;
  1150. b_def = sd->def;
  1151. b_watk2 = sd->watk2;
  1152. b_def2 = sd->def2;
  1153. b_flee2 = sd->flee2;
  1154. b_critical = sd->critical;
  1155. b_attackrange = sd->attackrange;
  1156. b_matk1 = sd->matk1;
  1157. b_matk2 = sd->matk2;
  1158. b_mdef = sd->mdef;
  1159. b_mdef2 = sd->mdef2;
  1160. b_class = sd->view_class;
  1161. sd->view_class = sd->status.class;
  1162. b_base_atk = sd->base_atk;
  1163. pc_calc_skilltree (sd); // スキルツリーの計算
  1164. sd->max_weight = max_weight_base[s_class.job] + sd->status.str * 300;
  1165. if (first & 1)
  1166. {
  1167. sd->weight = 0;
  1168. for (i = 0; i < MAX_INVENTORY; i++)
  1169. {
  1170. if (sd->status.inventory[i].nameid == 0
  1171. || sd->inventory_data[i] == NULL)
  1172. continue;
  1173. sd->weight +=
  1174. sd->inventory_data[i]->weight *
  1175. sd->status.inventory[i].amount;
  1176. }
  1177. sd->cart_max_weight = battle_config.max_cart_weight;
  1178. sd->cart_weight = 0;
  1179. sd->cart_max_num = MAX_CART;
  1180. sd->cart_num = 0;
  1181. for (i = 0; i < MAX_CART; i++)
  1182. {
  1183. if (sd->status.cart[i].nameid == 0)
  1184. continue;
  1185. sd->cart_weight +=
  1186. itemdb_weight (sd->status.cart[i].nameid) *
  1187. sd->status.cart[i].amount;
  1188. sd->cart_num++;
  1189. }
  1190. }
  1191. memset (sd->paramb, 0, sizeof (sd->paramb));
  1192. memset (sd->parame, 0, sizeof (sd->parame));
  1193. sd->hit = 0;
  1194. sd->flee = 0;
  1195. sd->flee2 = 0;
  1196. sd->critical = 0;
  1197. sd->aspd = 0;
  1198. sd->watk = 0;
  1199. sd->def = 0;
  1200. sd->mdef = 0;
  1201. sd->watk2 = 0;
  1202. sd->def2 = 0;
  1203. sd->mdef2 = 0;
  1204. sd->status.max_hp = 0;
  1205. sd->status.max_sp = 0;
  1206. sd->attackrange = 0;
  1207. sd->attackrange_ = 0;
  1208. sd->atk_ele = 0;
  1209. sd->def_ele = 0;
  1210. sd->star = 0;
  1211. sd->overrefine = 0;
  1212. sd->matk1 = 0;
  1213. sd->matk2 = 0;
  1214. sd->speed = DEFAULT_WALK_SPEED;
  1215. sd->hprate = 100;
  1216. sd->sprate = 100;
  1217. sd->castrate = 100;
  1218. sd->dsprate = 100;
  1219. sd->base_atk = 0;
  1220. sd->arrow_atk = 0;
  1221. sd->arrow_ele = 0;
  1222. sd->arrow_hit = 0;
  1223. sd->arrow_range = 0;
  1224. sd->nhealhp = sd->nhealsp = sd->nshealhp = sd->nshealsp = sd->nsshealhp =
  1225. sd->nsshealsp = 0;
  1226. memset (sd->addele, 0, sizeof (sd->addele));
  1227. memset (sd->addrace, 0, sizeof (sd->addrace));
  1228. memset (sd->addsize, 0, sizeof (sd->addsize));
  1229. memset (sd->addele_, 0, sizeof (sd->addele_));
  1230. memset (sd->addrace_, 0, sizeof (sd->addrace_));
  1231. memset (sd->addsize_, 0, sizeof (sd->addsize_));
  1232. memset (sd->subele, 0, sizeof (sd->subele));
  1233. memset (sd->subrace, 0, sizeof (sd->subrace));
  1234. memset (sd->addeff, 0, sizeof (sd->addeff));
  1235. memset (sd->addeff2, 0, sizeof (sd->addeff2));
  1236. memset (sd->reseff, 0, sizeof (sd->reseff));
  1237. memset (&sd->special_state, 0, sizeof (sd->special_state));
  1238. memset (sd->weapon_coma_ele, 0, sizeof (sd->weapon_coma_ele));
  1239. memset (sd->weapon_coma_race, 0, sizeof (sd->weapon_coma_race));
  1240. sd->watk_ = 0; //二刀流用(仮)
  1241. sd->watk_2 = 0;
  1242. sd->atk_ele_ = 0;
  1243. sd->star_ = 0;
  1244. sd->overrefine_ = 0;
  1245. sd->aspd_rate = 100;
  1246. sd->speed_rate = 100;
  1247. sd->hprecov_rate = 100;
  1248. sd->sprecov_rate = 100;
  1249. sd->critical_def = 0;
  1250. sd->double_rate = 0;
  1251. sd->near_attack_def_rate = sd->long_attack_def_rate = 0;
  1252. sd->atk_rate = sd->matk_rate = 100;
  1253. sd->ignore_def_ele = sd->ignore_def_race = 0;
  1254. sd->ignore_def_ele_ = sd->ignore_def_race_ = 0;
  1255. sd->ignore_mdef_ele = sd->ignore_mdef_race = 0;
  1256. sd->arrow_cri = 0;
  1257. sd->magic_def_rate = sd->misc_def_rate = 0;
  1258. memset (sd->arrow_addele, 0, sizeof (sd->arrow_addele));
  1259. memset (sd->arrow_addrace, 0, sizeof (sd->arrow_addrace));
  1260. memset (sd->arrow_addsize, 0, sizeof (sd->arrow_addsize));
  1261. memset (sd->arrow_addeff, 0, sizeof (sd->arrow_addeff));
  1262. memset (sd->arrow_addeff2, 0, sizeof (sd->arrow_addeff2));
  1263. memset (sd->magic_addele, 0, sizeof (sd->magic_addele));
  1264. memset (sd->magic_addrace, 0, sizeof (sd->magic_addrace));
  1265. memset (sd->magic_subrace, 0, sizeof (sd->magic_subrace));
  1266. sd->perfect_hit = 0;
  1267. sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100;
  1268. sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100;
  1269. sd->def_ratio_atk_ele = sd->def_ratio_atk_ele_ = 0;
  1270. sd->def_ratio_atk_race = sd->def_ratio_atk_race_ = 0;
  1271. sd->get_zeny_num = 0;
  1272. sd->add_damage_class_count = sd->add_damage_class_count_ =
  1273. sd->add_magic_damage_class_count = 0;
  1274. sd->add_def_class_count = sd->add_mdef_class_count = 0;
  1275. sd->monster_drop_item_count = 0;
  1276. memset (sd->add_damage_classrate, 0, sizeof (sd->add_damage_classrate));
  1277. memset (sd->add_damage_classrate_, 0, sizeof (sd->add_damage_classrate_));
  1278. memset (sd->add_magic_damage_classrate, 0,
  1279. sizeof (sd->add_magic_damage_classrate));
  1280. memset (sd->add_def_classrate, 0, sizeof (sd->add_def_classrate));
  1281. memset (sd->add_mdef_classrate, 0, sizeof (sd->add_mdef_classrate));
  1282. memset (sd->monster_drop_race, 0, sizeof (sd->monster_drop_race));
  1283. memset (sd->monster_drop_itemrate, 0, sizeof (sd->monster_drop_itemrate));
  1284. sd->speed_add_rate = sd->aspd_add_rate = 100;
  1285. sd->double_add_rate = sd->perfect_hit_add = sd->get_zeny_add_num = 0;
  1286. sd->splash_range = sd->splash_add_range = 0;
  1287. sd->autospell_id = sd->autospell_lv = sd->autospell_rate = 0;
  1288. sd->hp_drain_rate = sd->hp_drain_per = sd->sp_drain_rate =
  1289. sd->sp_drain_per = 0;
  1290. sd->hp_drain_rate_ = sd->hp_drain_per_ = sd->sp_drain_rate_ =
  1291. sd->sp_drain_per_ = 0;
  1292. sd->short_weapon_damage_return = sd->long_weapon_damage_return = 0;
  1293. sd->magic_damage_return = 0; //AppleGirl Was Here
  1294. sd->random_attack_increase_add = sd->random_attack_increase_per = 0;
  1295. if (!sd->disguiseflag && sd->disguise)
  1296. {
  1297. sd->disguise = 0;
  1298. pc_set_weapon_look (sd);
  1299. clif_changelook (&sd->bl, LOOK_SHIELD, sd->status.shield);
  1300. clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM, sd->status.head_bottom);
  1301. clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
  1302. clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
  1303. clif_clearchar (&sd->bl, 9);
  1304. pc_setpos (sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
  1305. }
  1306. sd->spellpower_bonus_target = 0;
  1307. for (i = 0; i < MAX_EQUIP_SIZE; i++)
  1308. {
  1309. //+++ skiping arrow slot?
  1310. if (i == 10)
  1311. continue;
  1312. index = sd->equip_index[i];
  1313. if (index < 0 || index >= MAX_INVENTORY)
  1314. continue;
  1315. if (i == 9 && sd->equip_index[8] == index)
  1316. continue;
  1317. if (i == 5 && sd->equip_index[4] == index)
  1318. continue;
  1319. if (i == 6
  1320. && (sd->equip_index[5] == index || sd->equip_index[4] == index))
  1321. continue;
  1322. if (sd->inventory_data[index])
  1323. {
  1324. sd->spellpower_bonus_target +=
  1325. sd->inventory_data[index]->magic_bonus;
  1326. if (sd->inventory_data[index]->type == 4)
  1327. {
  1328. if (sd->status.inventory[index].card[0] != 0x00ff
  1329. && sd->status.inventory[index].card[0] != 0x00fe
  1330. && sd->status.inventory[index].card[0] != (short) 0xff00)
  1331. {
  1332. int j;
  1333. for (j = 0; j < sd->inventory_data[index]->slot; j++)
  1334. { // カード
  1335. int c = sd->status.inventory[index].card[j];
  1336. if (c > 0)
  1337. {
  1338. argrec_t arg[2];
  1339. arg[0].name = "@slotId";
  1340. arg[0].v.i = i;
  1341. arg[1].name = "@itemId";
  1342. arg[1].v.i = sd->inventory_data[index]->nameid;
  1343. if (i == 8
  1344. && sd->status.inventory[index].equip == 0x20)
  1345. sd->state.lr_flag = 1;
  1346. run_script_l (itemdb_equipscript (c), 0, sd->bl.id,
  1347. 0, 2, arg);
  1348. sd->state.lr_flag = 0;
  1349. }
  1350. }
  1351. }
  1352. }
  1353. else if (sd->inventory_data[index]->type == 5)
  1354. { // 防具
  1355. if (sd->status.inventory[index].card[0] != 0x00ff
  1356. && sd->status.inventory[index].card[0] != 0x00fe
  1357. && sd->status.inventory[index].card[0] != (short) 0xff00)
  1358. {
  1359. int j;
  1360. for (j = 0; j < sd->inventory_data[index]->slot; j++)
  1361. { // カード
  1362. int c = sd->status.inventory[index].card[j];
  1363. if (c > 0) {
  1364. argrec_t arg[2];
  1365. arg[0].name = "@slotId";
  1366. arg[0].v.i = i;
  1367. arg[1].name = "@itemId";
  1368. arg[1].v.i = sd->inventory_data[index]->nameid;
  1369. run_script_l (itemdb_equipscript (c), 0, sd->bl.id,
  1370. 0, 2, arg);
  1371. }
  1372. }
  1373. }
  1374. }
  1375. }
  1376. }
  1377. #ifdef USE_ASTRAL_SOUL_SKILL
  1378. if (sd->spellpower_bonus_target < 0)
  1379. sd->spellpower_bonus_target =
  1380. (sd->spellpower_bonus_target * 256) /
  1381. (MIN (128 + skill_power (sd, TMW_ASTRAL_SOUL), 256));
  1382. #endif
  1383. if (sd->spellpower_bonus_target < sd->spellpower_bonus_current)
  1384. sd->spellpower_bonus_current = sd->spellpower_bonus_target;
  1385. wele = sd->atk_ele;
  1386. wele_ = sd->atk_ele_;
  1387. def_ele = sd->def_ele;
  1388. memcpy (sd->paramcard, sd->parame, sizeof (sd->paramcard));
  1389. // 装備品によるステータス変化はここで実行
  1390. for (i = 0; i < MAX_EQUIP_SIZE; i++)
  1391. {
  1392. //+++ skip arrow slot?
  1393. if (i == 10)
  1394. continue;
  1395. index = sd->equip_index[i];
  1396. if (index < 0 || index >= MAX_INVENTORY)
  1397. continue;
  1398. if (i == 9 && sd->equip_index[8] == index)
  1399. continue;
  1400. if (i == 5 && sd->equip_index[4] == index)
  1401. continue;
  1402. if (i == 6
  1403. && (sd->equip_index[5] == index || sd->equip_index[4] == index))
  1404. continue;
  1405. if (sd->inventory_data[index])
  1406. {
  1407. sd->def += sd->inventory_data[index]->def;
  1408. if (sd->inventory_data[index]->type == 4)
  1409. {
  1410. int r, wlv = sd->inventory_data[index]->wlv;
  1411. if (i == 8 && sd->status.inventory[index].equip == 0x20)
  1412. {
  1413. //二刀流用データ入力
  1414. sd->watk_ += sd->inventory_data[index]->atk;
  1415. sd->watk_2 = (r = sd->status.inventory[index].refine) * // 精錬攻撃力
  1416. refinebonus[wlv][0];
  1417. if ((r -= refinebonus[wlv][2]) > 0) // 過剰精錬ボーナス
  1418. sd->overrefine_ = r * refinebonus[wlv][1];
  1419. if (sd->status.inventory[index].card[0] == 0x00ff)
  1420. { // 製造武器
  1421. sd->star_ = (sd->status.inventory[index].card[1] >> 8); // 星のかけら
  1422. wele_ = (sd->status.inventory[index].card[1] & 0x0f); // 属 性
  1423. }
  1424. sd->attackrange_ += sd->inventory_data[index]->range;
  1425. sd->state.lr_flag = 1;
  1426. {
  1427. argrec_t arg[2];
  1428. arg[0].name = "@slotId";
  1429. arg[0].v.i = i;
  1430. arg[1].name = "@itemId";
  1431. arg[1].v.i = sd->inventory_data[index]->nameid;
  1432. run_script_l (sd->inventory_data[index]->equip_script, 0,
  1433. sd->bl.id, 0, 2, arg);
  1434. }
  1435. sd->state.lr_flag = 0;
  1436. }
  1437. else
  1438. { //二刀流武器以外
  1439. argrec_t arg[2];
  1440. arg[0].name = "@slotId";
  1441. arg[0].v.i = i;
  1442. arg[1].name = "@itemId";
  1443. arg[1].v.i = sd->inventory_data[index]->nameid;
  1444. sd->watk += sd->inventory_data[index]->atk;
  1445. sd->watk2 += (r = sd->status.inventory[index].refine) * // 精錬攻撃力
  1446. refinebonus[wlv][0];
  1447. if ((r -= refinebonus[wlv][2]) > 0) // 過剰精錬ボーナス
  1448. sd->overrefine += r * refinebonus[wlv][1];
  1449. if (sd->status.inventory[index].card[0] == 0x00ff)
  1450. { // 製造武器
  1451. sd->star += (sd->status.inventory[index].card[1] >> 8); // 星のかけら
  1452. wele = (sd->status.inventory[index].card[1] & 0x0f); // 属 性
  1453. }
  1454. sd->attackrange += sd->inventory_data[index]->range;
  1455. run_script_l (sd->inventory_data[index]->equip_script, 0,
  1456. sd->bl.id, 0, 2, arg);
  1457. }
  1458. }
  1459. else if (sd->inventory_data[index]->type == 5)
  1460. {
  1461. argrec_t arg[2];
  1462. arg[0].name = "@slotId";
  1463. arg[0].v.i = i;
  1464. arg[1].name = "@itemId";
  1465. arg[1].v.i = sd->inventory_data[index]->nameid;
  1466. sd->watk += sd->inventory_data[index]->atk;
  1467. refinedef +=
  1468. sd->status.inventory[index].refine * refinebonus[0][0];
  1469. run_script_l (sd->inventory_data[index]->equip_script, 0,
  1470. sd->bl.id, 0, 2, arg);
  1471. }
  1472. }
  1473. }
  1474. if (battle_is_unarmed (&sd->bl))
  1475. {
  1476. sd->watk += skill_power (sd, TMW_BRAWLING) / 3; // +66 for 200
  1477. sd->watk2 += skill_power (sd, TMW_BRAWLING) >> 3; // +25 for 200
  1478. sd->watk_ += skill_power (sd, TMW_BRAWLING) / 3; // +66 for 200
  1479. sd->watk_2 += skill_power (sd, TMW_BRAWLING) >> 3; // +25 for 200
  1480. }
  1481. if (sd->equip_index[10] >= 0)
  1482. { // 矢
  1483. index = sd->equip_index[10];
  1484. if (sd->inventory_data[index])
  1485. { //まだ属性が入っていない
  1486. argrec_t arg[2];
  1487. arg[0].name = "@slotId";
  1488. arg[0].v.i = i;
  1489. arg[1].name = "@itemId";
  1490. arg[1].v.i = sd->inventory_data[index]->nameid;
  1491. sd->state.lr_flag = 2;
  1492. run_script_l (sd->inventory_data[index]->equip_script, 0, sd->bl.id,
  1493. 0, 2, arg);
  1494. sd->state.lr_flag = 0;
  1495. sd->arrow_atk += sd->inventory_data[index]->atk;
  1496. }
  1497. }
  1498. sd->def += (refinedef + 50) / 100;
  1499. if (sd->attackrange < 1)
  1500. sd->attackrange = 1;
  1501. if (sd->attackrange_ < 1)
  1502. sd->attackrange_ = 1;
  1503. if (sd->attackrange < sd->attackrange_)
  1504. sd->attackrange = sd->attackrange_;
  1505. if (sd->status.weapon == 11)
  1506. sd->attackrange += sd->arrow_range;
  1507. if (wele > 0)
  1508. sd->atk_ele = wele;
  1509. if (wele_ > 0)
  1510. sd->atk_ele_ = wele_;
  1511. if (def_ele > 0)
  1512. sd->def_ele = def_ele;
  1513. sd->double_rate += sd->double_add_rate;
  1514. sd->perfect_hit += sd->perfect_hit_add;
  1515. sd->get_zeny_num += sd->get_zeny_add_num;
  1516. sd->splash_range += sd->splash_add_range;
  1517. if (sd->speed_add_rate != 100)
  1518. sd->speed_rate += sd->speed_add_rate - 100;
  1519. if (sd->aspd_add_rate != 100)
  1520. sd->aspd_rate += sd->aspd_add_rate - 100;
  1521. // 武器ATKサイズ補正 (右手)
  1522. sd->atkmods[0] = atkmods[0][sd->weapontype1];
  1523. sd->atkmods[1] = atkmods[1][sd->weapontype1];
  1524. sd->atkmods[2] = atkmods[2][sd->weapontype1];
  1525. //武器ATKサイズ補正 (左手)
  1526. sd->atkmods_[0] = atkmods[0][sd->weapontype2];
  1527. sd->atkmods_[1] = atkmods[1][sd->weapontype2];
  1528. sd->atkmods_[2] = atkmods[2][sd->weapontype2];
  1529. /*
  1530. // jobボーナス分
  1531. for(i=0;i<sd->status.job_level && i<MAX_LEVEL;i++){
  1532. if(job_bonus[s_class.upper][s_class.job][i])
  1533. sd->paramb[job_bonus[s_class.upper][s_class.job][i]-1]++;
  1534. }
  1535. */
  1536. if ((skill = pc_checkskill (sd, MC_INCCARRY)) > 0) // skill can be used with an item now, thanks to orn [Valaris]
  1537. sd->max_weight += skill * 1000;
  1538. // ステータス変化による基本パラメータ補正
  1539. if (sd->sc_count)
  1540. {
  1541. if (sd->sc_data[SC_CONCENTRATE].timer != -1
  1542. && sd->sc_data[SC_QUAGMIRE].timer == -1)
  1543. { // 集中力向上
  1544. sd->paramb[1] +=
  1545. (sd->status.agi + sd->paramb[1] + sd->parame[1] -
  1546. sd->paramcard[1]) * (2 +
  1547. sd->sc_data[SC_CONCENTRATE].val1) / 100;
  1548. sd->paramb[4] +=
  1549. (sd->status.dex + sd->paramb[4] + sd->parame[4] -
  1550. sd->paramcard[4]) * (2 +
  1551. sd->sc_data[SC_CONCENTRATE].val1) / 100;
  1552. }
  1553. if (sd->sc_data[SC_INCREASEAGI].timer != -1
  1554. && sd->sc_data[SC_QUAGMIRE].timer == -1
  1555. && sd->sc_data[SC_DONTFORGETME].timer == -1)
  1556. { // 速度増加
  1557. sd->paramb[1] += 2 + sd->sc_data[SC_INCREASEAGI].val1;
  1558. sd->speed -= sd->speed * 25 / 100;
  1559. }
  1560. if (sd->sc_data[SC_DECREASEAGI].timer != -1) // 速度減少(agiはbattle.cで)
  1561. sd->speed = sd->speed * 125 / 100;
  1562. if (sd->sc_data[SC_CLOAKING].timer != -1)
  1563. sd->speed =
  1564. (sd->speed * (76 + (sd->sc_data[SC_INCREASEAGI].val1 * 3))) /
  1565. 100;
  1566. if (sd->sc_data[SC_BLESSING].timer != -1)
  1567. { // ブレッシング
  1568. sd->paramb[0] += sd->sc_data[SC_BLESSING].val1;
  1569. sd->paramb[3] += sd->sc_data[SC_BLESSING].val1;
  1570. sd->paramb[4] += sd->sc_data[SC_BLESSING].val1;
  1571. }
  1572. if (sd->sc_data[SC_GLORIA].timer != -1) // グロリア
  1573. sd->paramb[5] += 30;
  1574. if (sd->sc_data[SC_LOUD].timer != -1 && sd->sc_data[SC_QUAGMIRE].timer == -1) // ラウドボイス
  1575. sd->paramb[0] += 4;
  1576. if (sd->sc_data[SC_QUAGMIRE].timer != -1)
  1577. { // クァグマイア
  1578. sd->speed = sd->speed * 3 / 2;
  1579. sd->paramb[1] -=
  1580. (sd->status.agi + sd->paramb[1] + sd->parame[1]) / 2;
  1581. sd->paramb[4] -=
  1582. (sd->status.dex + sd->paramb[4] + sd->parame[4]) / 2;
  1583. }
  1584. if (sd->sc_data[SC_TRUESIGHT].timer != -1)
  1585. { // トゥルーサイト
  1586. sd->paramb[0] += 5;
  1587. sd->paramb[1] += 5;
  1588. sd->paramb[2] += 5;
  1589. sd->paramb[3] += 5;
  1590. sd->paramb[4] += 5;
  1591. sd->paramb[5] += 5;
  1592. }
  1593. }
  1594. sd->speed -= skill_power (sd, TMW_SPEED) >> 3;
  1595. sd->aspd_rate -= skill_power (sd, TMW_SPEED) / 10;
  1596. if (sd->aspd_rate < 20)
  1597. sd->aspd_rate = 20;
  1598. /*
  1599. //1度も死んでないJob70スパノビに+10
  1600. if(s_class.job == 23 && sd->die_counter == 0 && sd->status.job_level >= 70){
  1601. sd->paramb[0]+= 15;
  1602. sd->paramb[1]+= 15;
  1603. sd->paramb[2]+= 15;
  1604. sd->paramb[3]+= 15;
  1605. sd->paramb[4]+= 15;
  1606. sd->paramb[5]+= 15;
  1607. }
  1608. */
  1609. sd->paramc[0] = sd->status.str + sd->paramb[0] + sd->parame[0];
  1610. sd->paramc[1] = sd->status.agi + sd->paramb[1] + sd->parame[1];
  1611. sd->paramc[2] = sd->status.vit + sd->paramb[2] + sd->parame[2];
  1612. sd->paramc[3] = sd->status.int_ + sd->paramb[3] + sd->parame[3];
  1613. sd->paramc[4] = sd->status.dex + sd->paramb[4] + sd->parame[4];
  1614. sd->paramc[5] = sd->status.luk + sd->paramb[5] + sd->parame[5];
  1615. for (i = 0; i < 6; i++)
  1616. if (sd->paramc[i] < 0)
  1617. sd->paramc[i] = 0;
  1618. if (sd->status.weapon == 11 || sd->status.weapon == 13
  1619. || sd->status.weapon == 14)
  1620. {
  1621. str = sd->paramc[4];
  1622. dex = sd->paramc[0];
  1623. }
  1624. else
  1625. {
  1626. str = sd->paramc[0];
  1627. dex = sd->paramc[4];
  1628. sd->critical += ((dex * 3) >> 1);
  1629. }
  1630. dstr = str / 10;
  1631. sd->base_atk += str + dstr * dstr + dex / 5 + sd->paramc[5] / 5;
  1632. //fprintf(stderr, "baseatk = %d = x + %d + %d + %d + %d\n", sd->base_atk, str, dstr*dstr, dex/5, sd->paramc[5]/5);
  1633. sd->matk1 += sd->paramc[3] + (sd->paramc[3] / 5) * (sd->paramc[3] / 5);
  1634. sd->matk2 += sd->paramc[3] + (sd->paramc[3] / 7) * (sd->paramc[3] / 7);
  1635. if (sd->matk1 < sd->matk2)
  1636. {
  1637. int temp = sd->matk2;
  1638. sd->matk2 = sd->matk1;
  1639. sd->matk1 = temp;
  1640. }
  1641. // [Fate] New tmw magic system
  1642. sd->matk1 += sd->status.base_level + sd->spellpower_bonus_current;
  1643. #ifdef USE_ASTRAL_SOUL_SKILL
  1644. if (sd->matk1 > MAGIC_SKILL_THRESHOLD)
  1645. {
  1646. int bonus = sd->matk1 - MAGIC_SKILL_THRESHOLD;
  1647. // Ok if you are above a certain threshold, you get only (1/8) of that matk1
  1648. // if you have Astral soul skill you can get the whole power again (and additionally the 1/8 added)
  1649. sd->matk1 = MAGIC_SKILL_THRESHOLD + (bonus>>3) + ((3*bonus*skill_power(sd, TMW_ASTRAL_SOUL))>>9);
  1650. }
  1651. #endif
  1652. sd->matk2 = 0;
  1653. if (sd->matk1 < 0)
  1654. sd->matk1 = 0;
  1655. sd->hit += sd->paramc[4] + sd->status.base_level;
  1656. sd->flee += sd->paramc[1] + sd->status.base_level;
  1657. sd->def2 += sd->paramc[2];
  1658. sd->mdef2 += sd->paramc[3];
  1659. sd->flee2 += sd->paramc[5] + 10;
  1660. sd->critical += (sd->paramc[5] * 3) + 10;
  1661. // 200 is the maximum of the skill
  1662. // so critical chance can get multiplied by ~1.5 and setting def2 to a third when skill maxed out
  1663. // def2 is the defence gained by vit, whereas "def", which is gained by armor, stays as is
  1664. int spbsk = skill_power (sd, TMW_RAGING);
  1665. if (spbsk!=0) {
  1666. sd->critical *= (128 + spbsk)/256;
  1667. sd->def2 /= (128 + spbsk)/128;
  1668. }
  1669. if (sd->base_atk < 1)
  1670. sd->base_atk = 1;
  1671. if (sd->critical_rate != 100)
  1672. sd->critical = (sd->critical * sd->critical_rate) / 100;
  1673. if (sd->critical < 10)
  1674. sd->critical = 10;
  1675. if (sd->hit_rate != 100)
  1676. sd->hit = (sd->hit * sd->hit_rate) / 100;
  1677. if (sd->hit < 1)
  1678. sd->hit = 1;
  1679. if (sd->flee_rate != 100)
  1680. sd->flee = (sd->flee * sd->flee_rate) / 100;
  1681. if (sd->flee < 1)
  1682. sd->flee = 1;
  1683. if (sd->flee2_rate != 100)
  1684. sd->flee2 = (sd->flee2 * sd->flee2_rate) / 100;
  1685. if (sd->flee2 < 10)
  1686. sd->flee2 = 10;
  1687. if (sd->def_rate != 100)
  1688. sd->def = (sd->def * sd->def_rate) / 100;
  1689. if (sd->def < 0)
  1690. sd->def = 0;
  1691. if (sd->def2_rate != 100)
  1692. sd->def2 = (sd->def2 * sd->def2_rate) / 100;
  1693. if (sd->def2 < 1)
  1694. sd->def2 = 1;
  1695. if (sd->mdef_rate != 100)
  1696. sd->mdef = (sd->mdef * sd->mdef_rate) / 100;
  1697. if (sd->mdef < 0)
  1698. sd->mdef = 0;
  1699. if (sd->mdef2_rate != 100)
  1700. sd->mdef2 = (sd->mdef2 * sd->mdef2_rate) / 100;
  1701. if (sd->mdef2 < 1)
  1702. sd->mdef2 = 1;
  1703. // 二刀流 ASPD 修正
  1704. if (sd->status.weapon <= 16)
  1705. sd->aspd +=
  1706. aspd_base[s_class.job][sd->status.weapon] - (sd->paramc[1] * 4 +
  1707. sd->paramc[4]) *
  1708. aspd_base[s_class.job][sd->status.weapon] / 1000;
  1709. else
  1710. sd->aspd += ((aspd_base[s_class.job][sd->weapontype1] -
  1711. (sd->paramc[1] * 4 +
  1712. sd->paramc[4]) *
  1713. aspd_base[s_class.job][sd->weapontype1] / 1000) +
  1714. (aspd_base[s_class.job][sd->weapontype2] -
  1715. (sd->paramc[1] * 4 +
  1716. sd->paramc[4]) *
  1717. aspd_base[s_class.job][sd->weapontype2] / 1000)) * 140 /
  1718. 200;
  1719. aspd_rate = sd->aspd_rate;
  1720. //攻撃速度増加
  1721. if ((skill = pc_checkskill (sd, AC_VULTURE)) > 0)
  1722. { // ワシの目
  1723. sd->hit += skill;
  1724. if (sd->status.weapon == 11)
  1725. sd->attackrange += skill;
  1726. }
  1727. if (sd->attackrange > 2)
  1728. { // [fate] ranged weapon?
  1729. sd->attackrange += MIN (skill_power (sd, AC_OWL) / 60, 3);
  1730. sd->hit += skill_power (sd, AC_OWL) / 10; // 20 for 200
  1731. }
  1732. if ((skill = pc_checkskill (sd, BS_WEAPONRESEARCH)) > 0) // 武器研究の命中率増加
  1733. sd->hit += skill * 2;
  1734. if (sd->status.option & 2 && (skill = pc_checkskill (sd, RG_TUNNELDRIVE)) > 0) // トンネルドライブ // トンネルドライブ
  1735. sd->speed += (1.2 * DEFAULT_WALK_SPEED - skill * 9);
  1736. if (pc_iscarton (sd) && (skill = pc_checkskill (sd, MC_PUSHCART)) > 0) // カートによる速度低下
  1737. sd->speed += (10 - skill) * (DEFAULT_WALK_SPEED * 0.1);
  1738. else if (pc_isriding (sd)) // ペコペコ乗りによる速度増加
  1739. sd->speed -= (0.25 * DEFAULT_WALK_SPEED);
  1740. sd->max_weight += 1000;
  1741. if (sd->sc_count)
  1742. {
  1743. if (sd->sc_data[SC_WINDWALK].timer != -1) //ウィンドウォーク時はLv*2%減算
  1744. sd->speed -=
  1745. sd->speed * (sd->sc_data[SC_WINDWALK].val1 * 2) / 100;
  1746. if (sd->sc_data[SC_CARTBOOST].timer != -1) // カートブースト
  1747. sd->speed -= (DEFAULT_WALK_SPEED * 20) / 100;
  1748. if (sd->sc_data[SC_BERSERK].timer != -1) //バーサーク中はIAと同じぐらい速い?
  1749. sd->speed -= sd->speed * 25 / 100;
  1750. if (sd->sc_data[SC_WEDDING].timer != -1) //結婚中は歩くのが遅い
  1751. sd->speed = 2 * DEFAULT_WALK_SPEED;
  1752. }
  1753. if ((skill = pc_checkskill (sd, CR_TRUST)) > 0)
  1754. { // フェイス
  1755. sd->status.max_hp += skill * 200;
  1756. sd->subele[6] += skill * 5;
  1757. }
  1758. if ((skill = pc_checkskill (sd, BS_SKINTEMPER)) > 0)
  1759. sd->subele[3] += skill * 4;
  1760. bl = sd->status.base_level;
  1761. sd->status.max_hp +=
  1762. (3500 + bl * hp_coefficient2[s_class.job] +
  1763. hp_sigma_val[s_class.job][(bl > 0) ? bl - 1 : 0]) / 100 * (100 +
  1764. sd->paramc
  1765. [2]) /
  1766. 100 + (sd->parame[2] - sd->paramcard[2]);
  1767. if (s_class.upper == 1) // [MouseJstr]
  1768. sd->status.max_hp = sd->status.max_hp * 130 / 100;
  1769. if (sd->hprate != 100)
  1770. sd->status.max_hp = sd->status.max_hp * sd->hprate / 100;
  1771. if (sd->sc_data && sd->sc_data[SC_BERSERK].timer != -1)
  1772. { // バーサーク
  1773. sd->status.max_hp = sd->status.max_hp * 3;
  1774. sd->status.hp = sd->status.hp * 3;
  1775. if (sd->status.max_hp > battle_config.max_hp) // removed negative max hp bug by Valaris
  1776. sd->status.max_hp = battle_config.max_hp;
  1777. if (sd->status.hp > battle_config.max_hp) // removed negative max hp bug by Valaris
  1778. sd->status.hp = battle_config.max_hp;
  1779. }
  1780. if (s_class.job == 23 && sd->status.base_level >= 99)
  1781. {
  1782. sd->status.max_hp = sd->status.max_hp + 2000;
  1783. }
  1784. if (sd->status.max_hp > battle_config.max_hp) // removed negative max hp bug by Valaris
  1785. sd->status.max_hp = battle_config.max_hp;
  1786. if (sd->status.max_hp <= 0)
  1787. sd->status.max_hp = 1; // end
  1788. // 最大SP計算
  1789. sd->status.max_sp +=
  1790. ((sp_coefficient[s_class.job] * bl) + 1000) / 100 * (100 +
  1791. sd->paramc[3]) /
  1792. 100 + (sd->parame[3] - sd->paramcard[3]);
  1793. if (s_class.upper == 1) // [MouseJstr]
  1794. sd->status.max_sp = sd->status.max_sp * 130 / 100;
  1795. if (sd->sprate != 100)
  1796. sd->status.max_sp = sd->status.max_sp * sd->sprate / 100;
  1797. if ((skill = pc_checkskill (sd, HP_MEDITATIO)) > 0) // メディテイティオ
  1798. sd->status.max_sp += sd->status.max_sp * skill / 100;
  1799. if ((skill = pc_checkskill (sd, HW_SOULDRAIN)) > 0) /* ソウルドレイン */
  1800. sd->status.max_sp += sd->status.max_sp * 2 * skill / 100;
  1801. if (sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp)
  1802. sd->status.max_sp = battle_config.max_sp;
  1803. //自然回復HP
  1804. sd->nhealhp = 1 + (sd->paramc[2] / 5) + (sd->status.max_hp / 200);
  1805. if ((skill = pc_checkskill (sd, SM_RECOVERY)) > 0)
  1806. { /* HP回復力向上 */
  1807. sd->nshealhp = skill * 5 + (sd->status.max_hp * skill / 500);
  1808. if (sd->nshealhp > 0x7fff)
  1809. sd->nshealhp = 0x7fff;
  1810. }
  1811. //自然回復SP
  1812. sd->nhealsp = 1 + (sd->paramc[3] / 6) + (sd->status.max_sp / 100);
  1813. if (sd->paramc[3] >= 120)
  1814. sd->nhealsp += ((sd->paramc[3] - 120) >> 1) + 4;
  1815. if ((skill = pc_checkskill (sd, MG_SRECOVERY)) > 0)
  1816. { /* SP回復力向上 */
  1817. sd->nshealsp = skill * 3 + (sd->status.max_sp * skill / 500);
  1818. if (sd->nshealsp > 0x7fff)
  1819. sd->nshealsp = 0x7fff;
  1820. }
  1821. if ((skill = pc_checkskill (sd, MO_SPIRITSRECOVERY)) > 0)
  1822. {
  1823. sd->nsshealhp = skill * 4 + (sd->status.max_hp * skill / 500);
  1824. sd->nsshealsp = skill * 2 + (sd->status.max_sp * skill / 500);
  1825. if (sd->nsshealhp > 0x7fff)
  1826. sd->nsshealhp = 0x7fff;
  1827. if (sd->nsshealsp > 0x7fff)
  1828. sd->nsshealsp = 0x7fff;
  1829. }
  1830. if (sd->hprecov_rate != 100)
  1831. {
  1832. sd->nhealhp = sd->nhealhp * sd->hprecov_rate / 100;
  1833. if (sd->nhealhp < 1)
  1834. sd->nhealhp = 1;
  1835. }
  1836. if (sd->sprecov_rate != 100)
  1837. {
  1838. sd->nhealsp = sd->nhealsp * sd->sprecov_rate / 100;
  1839. if (sd->nhealsp < 1)
  1840. sd->nhealsp = 1;
  1841. }
  1842. if ((skill = pc_checkskill (sd, HP_MEDITATIO)) > 0)
  1843. { // メディテイティオはSPRではなく自然回復にかかる
  1844. sd->nhealsp += 3 * skill * (sd->status.max_sp) / 100;
  1845. if (sd->nhealsp > 0x7fff)
  1846. sd->nhealsp = 0x7fff;
  1847. }
  1848. // 種族耐性(これでいいの? ディバインプロテクションと同じ処理がいるかも)
  1849. if ((skill = pc_checkskill (sd, SA_DRAGONOLOGY)) > 0)
  1850. { // ドラゴノロジー
  1851. skill = skill * 4;
  1852. sd->addrace[9] += skill;
  1853. sd->addrace_[9] += skill;
  1854. sd->subrace[9] += skill;
  1855. sd->magic_addrace[9] += skill;
  1856. sd->magic_subrace[9] -= skill;
  1857. }
  1858. //Flee上昇
  1859. if ((skill = pc_checkskill (sd, TF_MISS)) > 0)
  1860. { // 回避率増加
  1861. if (sd->status.class == 6 || sd->status.class == 4007
  1862. || sd->status.class == 23)
  1863. {
  1864. sd->flee += skill * 3;
  1865. }
  1866. if (sd->status.class == 12 || sd->status.class == 17
  1867. || sd->status.class == 4013 || sd->status.class == 4018)
  1868. sd->flee += skill * 4;
  1869. if (sd->status.class == 12 || sd->status.class == 4013)
  1870. sd->speed -= sd->speed * (skill * .5) / 100;
  1871. }
  1872. if ((skill = pc_checkskill (sd, MO_DODGE)) > 0) // 見切り
  1873. sd->flee += (skill * 3) >> 1;
  1874. // スキルやステータス異常による残りのパラメータ補正
  1875. if (sd->sc_count)
  1876. {
  1877. // ATK/DEF変化形
  1878. if (sd->sc_data[SC_ANGELUS].timer != -1) // エンジェラス
  1879. sd->def2 =
  1880. sd->def2 * (110 + 5 * sd->sc_data[SC_ANGELUS].val1) / 100;
  1881. if (sd->sc_data[SC_IMPOSITIO].timer != -1)
  1882. { // インポシティオマヌス
  1883. sd->watk += sd->sc_data[SC_IMPOSITIO].val1 * 5;
  1884. index = sd->equip_index[8];
  1885. if (index >= 0 && sd->inventory_data[index]
  1886. && sd->inventory_data[index]->type == 4)
  1887. sd->watk_ += sd->sc_data[SC_IMPOSITIO].val1 * 5;
  1888. }
  1889. if (sd->sc_data[SC_PROVOKE].timer != -1)
  1890. { // プロボック
  1891. sd->def2 =
  1892. sd->def2 * (100 - 6 * sd->sc_data[SC_PROVOKE].val1) / 100;
  1893. sd->base_atk =
  1894. sd->base_atk * (100 + 2 * sd->sc_data[SC_PROVOKE].val1) / 100;
  1895. sd->watk =
  1896. sd->watk * (100 + 2 * sd->sc_data[SC_PROVOKE].val1) / 100;
  1897. index = sd->equip_index[8];
  1898. if (index >= 0 && sd->inventory_data[index]
  1899. && sd->inventory_data[index]->type == 4)
  1900. sd->watk_ =
  1901. sd->watk_ * (100 +
  1902. 2 * sd->sc_data[SC_PROVOKE].val1) / 100;
  1903. }
  1904. if (sd->sc_data[SC_ENDURE].timer != -1)
  1905. sd->mdef2 += sd->sc_data[SC_ENDURE].val1;
  1906. if (sd->sc_data[SC_MINDBREAKER].timer != -1)
  1907. { // プロボック
  1908. sd->mdef2 =
  1909. sd->mdef2 * (100 -
  1910. 6 * sd->sc_data[SC_MINDBREAKER].val1) / 100;
  1911. sd->matk1 =
  1912. sd->matk1 * (100 +
  1913. 2 * sd->sc_data[SC_MINDBREAKER].val1) / 100;
  1914. sd->matk2 =
  1915. sd->matk2 * (100 +
  1916. 2 * sd->sc_data[SC_MINDBREAKER].val1) / 100;
  1917. }
  1918. if (sd->sc_data[SC_POISON].timer != -1) // 毒状態
  1919. sd->def2 = sd->def2 * 75 / 100;
  1920. if (sd->sc_data[SC_DRUMBATTLE].timer != -1)
  1921. { // 戦太鼓の響き
  1922. sd->watk += sd->sc_data[SC_DRUMBATTLE].val2;
  1923. sd->def += sd->sc_data[SC_DRUMBATTLE].val3;
  1924. index = sd->equip_index[8];
  1925. if (index >= 0 && sd->inventory_data[index]
  1926. && sd->inventory_data[index]->type == 4)
  1927. sd->watk_ += sd->sc_data[SC_DRUMBATTLE].val2;
  1928. }
  1929. if (sd->sc_data[SC_NIBELUNGEN].timer != -1)
  1930. { // ニーベルングの指輪
  1931. index = sd->equip_index[9];
  1932. if (index >= 0 && sd->inventory_data[index]
  1933. && sd->inventory_data[index]->wlv == 3)
  1934. sd->watk += sd->sc_data[SC_NIBELUNGEN].val3;
  1935. index = sd->equip_index[8];
  1936. if (index >= 0 && sd->inventory_data[index]
  1937. && sd->inventory_data[index]->wlv == 3)
  1938. sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val3;
  1939. if (index >= 0 && sd->inventory_data[index]
  1940. && sd->inventory_data[index]->wlv == 4)
  1941. sd->watk += sd->sc_data[SC_NIBELUNGEN].val2;
  1942. index = sd->equip_index[8];
  1943. if (index >= 0 && sd->inventory_data[index]
  1944. && sd->inventory_data[index]->wlv == 4)
  1945. sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val2;
  1946. }
  1947. if (sd->sc_data[SC_VOLCANO].timer != -1 && sd->def_ele == 3)
  1948. { // ボルケーノ
  1949. sd->watk += sd->sc_data[SC_VIOLENTGALE].val3;
  1950. }
  1951. if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1)
  1952. sd->def =
  1953. sd->def * (100 - sd->sc_data[SC_SIGNUMCRUCIS].val2) / 100;
  1954. if (sd->sc_data[SC_ETERNALCHAOS].timer != -1) // エターナルカオス
  1955. sd->def = 0;
  1956. if (sd->sc_data[SC_CONCENTRATION].timer != -1)
  1957. { //コンセントレーション
  1958. sd->watk =
  1959. sd->watk * (100 +
  1960. 5 * sd->sc_data[SC_CONCENTRATION].val1) / 100;
  1961. index = sd->equip_index[8];
  1962. if (index >= 0 && sd->inventory_data[index]
  1963. && sd->inventory_data[index]->type == 4)
  1964. sd->watk_ =
  1965. sd->watk * (100 +
  1966. 5 * sd->sc_data[SC_CONCENTRATION].val1) / 100;
  1967. sd->def =
  1968. sd->def * (100 -
  1969. 5 * sd->sc_data[SC_CONCENTRATION].val1) / 100;
  1970. }
  1971. if (sd->sc_data[SC_MAGICPOWER].timer != -1)
  1972. { //魔法力増幅
  1973. sd->matk1 =
  1974. sd->matk1 * (100 + 2 * sd->sc_data[SC_MAGICPOWER].val1) / 100;
  1975. sd->matk2 =
  1976. sd->matk2 * (100 + 2 * sd->sc_data[SC_MAGICPOWER].val1) / 100;
  1977. }
  1978. if (sd->sc_data[SC_ATKPOT].timer != -1)
  1979. sd->watk += sd->sc_data[SC_ATKPOT].val1;
  1980. if (sd->sc_data[SC_MATKPOT].timer != -1)
  1981. {
  1982. sd->matk1 += sd->sc_data[SC_MATKPOT].val1;
  1983. sd->matk2 += sd->sc_data[SC_MATKPOT].val1;
  1984. }
  1985. // ASPD/移動速度変化系
  1986. if (sd->sc_data[SC_TWOHANDQUICKEN].timer != -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
  1987. aspd_rate -= 30;
  1988. if (sd->sc_data[SC_ADRENALINE].timer != -1
  1989. && sd->sc_data[SC_TWOHANDQUICKEN].timer == -1
  1990. && sd->sc_data[SC_QUAGMIRE].timer == -1
  1991. && sd->sc_data[SC_DONTFORGETME].timer == -1)
  1992. { // アドレナリンラッシュ
  1993. if (sd->sc_data[SC_ADRENALINE].val2
  1994. || !battle_config.party_skill_penaly)
  1995. aspd_rate -= 30;
  1996. else
  1997. aspd_rate -= 25;
  1998. }
  1999. if (sd->sc_data[SC_SPEARSQUICKEN].timer != -1 && sd->sc_data[SC_ADRENALINE].timer == -1 && sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // スピアクィッケン
  2000. aspd_rate -= sd->sc_data[SC_SPEARSQUICKEN].val2;
  2001. if (sd->sc_data[SC_ASSNCROS].timer != -1 && // 夕陽のアサシンクロス
  2002. sd->sc_data[SC_TWOHANDQUICKEN].timer == -1
  2003. && sd->sc_data[SC_ADRENALINE].timer == -1
  2004. && sd->sc_data[SC_SPEARSQUICKEN].timer == -1
  2005. && sd->sc_data[SC_DONTFORGETME].timer == -1)
  2006. aspd_rate -=
  2007. 5 + sd->sc_data[SC_ASSNCROS].val1 +
  2008. sd->sc_data[SC_ASSNCROS].val2 + sd->sc_data[SC_ASSNCROS].val3;
  2009. if (sd->sc_data[SC_DONTFORGETME].timer != -1)
  2010. { // 私を忘れないで
  2011. aspd_rate +=
  2012. sd->sc_data[SC_DONTFORGETME].val1 * 3 +
  2013. sd->sc_data[SC_DONTFORGETME].val2 +
  2014. (sd->sc_data[SC_DONTFORGETME].val3 >> 16);
  2015. sd->speed =
  2016. sd->speed * (100 + sd->sc_data[SC_DONTFORGETME].val1 * 2 +
  2017. sd->sc_data[SC_DONTFORGETME].val2 +
  2018. (sd->sc_data[SC_DONTFORGETME].val3 & 0xffff)) /
  2019. 100;
  2020. }
  2021. if (sd->sc_data[i = SC_SPEEDPOTION2].timer != -1 || sd->sc_data[i = SC_SPEEDPOTION1].timer != -1 || sd->sc_data[i = SC_SPEEDPOTION0].timer != -1)
  2022. // 増 速ポーション
  2023. aspd_rate -= sd->sc_data[i].val1;
  2024. if (sd->sc_data[SC_HASTE].timer != -1)
  2025. aspd_rate -= sd->sc_data[SC_HASTE].val1;
  2026. /* Slow down if protected */
  2027. if (sd->sc_data[SC_PHYS_SHIELD].timer != -1)
  2028. aspd_rate += sd->sc_data[SC_PHYS_SHIELD].val1;
  2029. // HIT/FLEE変化系
  2030. if (sd->sc_data[SC_WHISTLE].timer != -1)
  2031. { // 口笛
  2032. sd->flee += sd->flee * (sd->sc_data[SC_WHISTLE].val1
  2033. + sd->sc_data[SC_WHISTLE].val2 +
  2034. (sd->sc_data[SC_WHISTLE].val3 >> 16)) /
  2035. 100;
  2036. sd->flee2 +=
  2037. (sd->sc_data[SC_WHISTLE].val1 + sd->sc_data[SC_WHISTLE].val2 +
  2038. (sd->sc_data[SC_WHISTLE].val3 & 0xffff)) * 10;
  2039. }
  2040. if (sd->sc_data[SC_HUMMING].timer != -1) // ハミング
  2041. sd->hit +=
  2042. (sd->sc_data[SC_HUMMING].val1 * 2 +
  2043. sd->sc_data[SC_HUMMING].val2 +
  2044. sd->sc_data[SC_HUMMING].val3) * sd->hit / 100;
  2045. if (sd->sc_data[SC_VIOLENTGALE].timer != -1 && sd->def_ele == 4)
  2046. { // バイオレントゲイル
  2047. sd->flee += sd->flee * sd->sc_data[SC_VIOLENTGALE].val3 / 100;
  2048. }
  2049. if (sd->sc_data[SC_BLIND].timer != -1)
  2050. { // 暗黒
  2051. sd->hit -= sd->hit * 25 / 100;
  2052. sd->flee -= sd->flee * 25 / 100;
  2053. }
  2054. if (sd->sc_data[SC_WINDWALK].timer != -1) // ウィンドウォーク
  2055. sd->flee += sd->flee * (sd->sc_data[SC_WINDWALK].val2) / 100;
  2056. if (sd->sc_data[SC_SPIDERWEB].timer != -1) //スパイダーウェブ
  2057. sd->flee -= sd->flee * 50 / 100;
  2058. if (sd->sc_data[SC_TRUESIGHT].timer != -1) //トゥルーサイト
  2059. sd->hit += 3 * (sd->sc_data[SC_TRUESIGHT].val1);
  2060. if (sd->sc_data[SC_CONCENTRATION].timer != -1) //コンセントレーション
  2061. sd->hit += (10 * (sd->sc_data[SC_CONCENTRATION].val1));
  2062. // 耐性
  2063. if (sd->sc_data[SC_SIEGFRIED].timer != -1)
  2064. { // 不死身のジークフリード
  2065. sd->subele[1] += sd->sc_data[SC_SIEGFRIED].val2; // 水
  2066. sd->subele[2] += sd->sc_data[SC_SIEGFRIED].val2; // 水
  2067. sd->subele[3] += sd->sc_data[SC_SIEGFRIED].val2; // 水
  2068. sd->subele[4] += sd->sc_data[SC_SIEGFRIED].val2; // 水
  2069. sd->subele[5] += sd->sc_data[SC_SIEGFRIED].val2; // 水
  2070. sd->subele[6] += sd->sc_data[SC_SIEGFRIED].val2; // 水
  2071. sd->subele[7] += sd->sc_data[SC_SIEGFRIED].val2; // 水
  2072. sd->subele[8] += sd->sc_data[SC_SIEGFRIED].val2; // 水
  2073. sd->subele[9] += sd->sc_data[SC_SIEGFRIED].val2; // 水
  2074. }
  2075. if (sd->sc_data[SC_PROVIDENCE].timer != -1)
  2076. { // プロヴィデンス
  2077. sd->subele[6] += sd->sc_data[SC_PROVIDENCE].val2; // 対 聖属性
  2078. sd->subrace[6] += sd->sc_data[SC_PROVIDENCE].val2; // 対 悪魔
  2079. }
  2080. // その他
  2081. if (sd->sc_data[SC_APPLEIDUN].timer != -1)
  2082. { // イドゥンの林檎
  2083. sd->status.max_hp +=
  2084. ((5 + sd->sc_data[SC_APPLEIDUN].val1 * 2 +
  2085. ((sd->sc_data[SC_APPLEIDUN].val2 + 1) >> 1) +
  2086. sd->sc_data[SC_APPLEIDUN].val3 / 10) * sd->status.max_hp) /
  2087. 100;
  2088. if (sd->status.max_hp < 0
  2089. || sd->status.max_hp > battle_config.max_hp)
  2090. sd->status.max_hp = battle_config.max_hp;
  2091. }
  2092. if (sd->sc_data[SC_DELUGE].timer != -1 && sd->def_ele == 1)
  2093. { // デリュージ
  2094. sd->status.max_hp +=
  2095. sd->status.max_hp * sd->sc_data[SC_DELUGE].val3 / 100;
  2096. if (sd->status.max_hp < 0
  2097. || sd->status.max_hp > battle_config.max_hp)
  2098. sd->status.max_hp = battle_config.max_hp;
  2099. }
  2100. if (sd->sc_data[SC_SERVICE4U].timer != -1)
  2101. { // サービスフォーユー
  2102. sd->status.max_sp +=
  2103. sd->status.max_sp * (10 + sd->sc_data[SC_SERVICE4U].val1 +
  2104. sd->sc_data[SC_SERVICE4U].val2 +
  2105. sd->sc_data[SC_SERVICE4U].val3) / 100;
  2106. if (sd->status.max_sp < 0
  2107. || sd->status.max_sp > battle_config.max_sp)
  2108. sd->status.max_sp = battle_config.max_sp;
  2109. sd->dsprate -=
  2110. (10 + sd->sc_data[SC_SERVICE4U].val1 * 3 +
  2111. sd->sc_data[SC_SERVICE4U].val2 +
  2112. sd->sc_data[SC_SERVICE4U].val3);
  2113. if (sd->dsprate < 0)
  2114. sd->dsprate = 0;
  2115. }
  2116. if (sd->sc_data[SC_FORTUNE].timer != -1) // 幸運のキス
  2117. sd->critical +=
  2118. (10 + sd->sc_data[SC_FORTUNE].val1 +
  2119. sd->sc_data[SC_FORTUNE].val2 +
  2120. sd->sc_data[SC_FORTUNE].val3) * 10;
  2121. if (sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
  2122. { // 爆裂波動
  2123. if (s_class.job == 23)
  2124. sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val1 * 100;
  2125. else
  2126. sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val2;
  2127. }
  2128. if (sd->sc_data[SC_STEELBODY].timer != -1)
  2129. { // 金剛
  2130. sd->def = 90;
  2131. sd->mdef = 90;
  2132. aspd_rate += 25;
  2133. sd->speed = (sd->speed * 125) / 100;
  2134. }
  2135. if (sd->sc_data[SC_DEFENDER].timer != -1)
  2136. {
  2137. sd->aspd += (550 - sd->sc_data[SC_DEFENDER].val1 * 50);
  2138. sd->speed =
  2139. (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1 * 5)) / 100;
  2140. }
  2141. if (sd->sc_data[SC_ENCPOISON].timer != -1)
  2142. sd->addeff[4] += sd->sc_data[SC_ENCPOISON].val2;
  2143. if (sd->sc_data[SC_DANCING].timer != -1)
  2144. { // 演奏/ダンス使用中
  2145. sd->speed *= 4;
  2146. sd->nhealsp = 0;
  2147. sd->nshealsp = 0;
  2148. sd->nsshealsp = 0;
  2149. }
  2150. if (sd->sc_data[SC_CURSE].timer != -1)
  2151. sd->speed += 450;
  2152. if (sd->sc_data[SC_TRUESIGHT].timer != -1) //トゥルーサイト
  2153. sd->critical +=
  2154. sd->critical * (sd->sc_data[SC_TRUESIGHT].val1) / 100;
  2155. /* if(sd->sc_data[SC_VOLCANO].timer!=-1) // エンチャントポイズン(属性はbattle.cで)
  2156. sd->addeff[2]+=sd->sc_data[SC_VOLCANO].val2;//% of granting
  2157. if(sd->sc_data[SC_DELUGE].timer!=-1) // エンチャントポイズン(属性はbattle.cで)
  2158. sd->addeff[0]+=sd->sc_data[SC_DELUGE].val2;//% of granting
  2159. */
  2160. }
  2161. if (sd->speed_rate != 100)
  2162. sd->speed = sd->speed * sd->speed_rate / 100;
  2163. if (sd->speed < 1)
  2164. sd->speed = 1;
  2165. if (aspd_rate != 100)
  2166. sd->aspd = sd->aspd * aspd_rate / 100;
  2167. if (pc_isriding (sd)) // 騎兵修練
  2168. sd->aspd =
  2169. sd->aspd * (100 +
  2170. 10 * (5 -
  2171. pc_checkskill (sd, KN_CAVALIERMASTERY))) / 100;
  2172. if (sd->attack_spell_override)
  2173. sd->aspd = sd->attack_spell_delay;
  2174. if (sd->aspd < battle_config.max_aspd)
  2175. sd->aspd = battle_config.max_aspd;
  2176. sd->amotion = sd->aspd;
  2177. sd->dmotion = 800 - sd->paramc[1] * 4;
  2178. if (sd->dmotion < 400)
  2179. sd->dmotion = 400;
  2180. if (sd->skilltimer != -1 && (skill = pc_checkskill (sd, SA_FREECAST)) > 0)
  2181. {
  2182. sd->prev_speed = sd->speed;
  2183. sd->speed = sd->speed * (175 - skill * 5) / 100;
  2184. }
  2185. if (sd->status.hp > sd->status.max_hp)
  2186. sd->status.hp = sd->status.max_hp;
  2187. if (sd->status.sp > sd->status.max_sp)
  2188. sd->status.sp = sd->status.max_sp;
  2189. if (first & 4)
  2190. return 0;
  2191. if (first & 3)
  2192. {
  2193. clif_updatestatus (sd, SP_SPEED);
  2194. clif_updatestatus (sd, SP_MAXHP);
  2195. clif_updatestatus (sd, SP_MAXSP);
  2196. if (first & 1)
  2197. {
  2198. clif_updatestatus (sd, SP_HP);
  2199. clif_updatestatus (sd, SP_SP);
  2200. }
  2201. return 0;
  2202. }
  2203. if (b_class != sd->view_class)
  2204. {
  2205. clif_changelook (&sd->bl, LOOK_BASE, sd->view_class);
  2206. clif_changelook (&sd->bl, LOOK_WEAPON, 0);
  2207. }
  2208. if (memcmp (b_skill, sd->status.skill, sizeof (sd->status.skill))
  2209. || b_attackrange != sd->attackrange)
  2210. clif_skillinfoblock (sd); // スキル送信
  2211. if (b_speed != sd->speed)
  2212. clif_updatestatus (sd, SP_SPEED);
  2213. if (b_weight != sd->weight)
  2214. clif_updatestatus (sd, SP_WEIGHT);
  2215. if (b_max_weight != sd->max_weight)
  2216. {
  2217. clif_updatestatus (sd, SP_MAXWEIGHT);
  2218. pc_checkweighticon (sd);
  2219. }
  2220. for (i = 0; i < 6; i++)
  2221. if (b_paramb[i] + b_parame[i] != sd->paramb[i] + sd->parame[i])
  2222. clif_updatestatus (sd, SP_STR + i);
  2223. if (b_hit != sd->hit)
  2224. clif_updatestatus (sd, SP_HIT);
  2225. if (b_flee != sd->flee)
  2226. clif_updatestatus (sd, SP_FLEE1);
  2227. if (b_aspd != sd->aspd)
  2228. clif_updatestatus (sd, SP_ASPD);
  2229. if (b_watk != sd->watk || b_base_atk != sd->base_atk)
  2230. clif_updatestatus (sd, SP_ATK1);
  2231. if (b_def != sd->def)
  2232. clif_updatestatus (sd, SP_DEF1);
  2233. if (b_watk2 != sd->watk2)
  2234. clif_updatestatus (sd, SP_ATK2);
  2235. if (b_def2 != sd->def2)
  2236. clif_updatestatus (sd, SP_DEF2);
  2237. if (b_flee2 != sd->flee2)
  2238. clif_updatestatus (sd, SP_FLEE2);
  2239. if (b_critical != sd->critical)
  2240. clif_updatestatus (sd, SP_CRITICAL);
  2241. if (b_matk1 != sd->matk1)
  2242. clif_updatestatus (sd, SP_MATK1);
  2243. if (b_matk2 != sd->matk2)
  2244. clif_updatestatus (sd, SP_MATK2);
  2245. if (b_mdef != sd->mdef)
  2246. clif_updatestatus (sd, SP_MDEF1);
  2247. if (b_mdef2 != sd->mdef2)
  2248. clif_updatestatus (sd, SP_MDEF2);
  2249. if (b_attackrange != sd->attackrange)
  2250. clif_updatestatus (sd, SP_ATTACKRANGE);
  2251. if (b_max_hp != sd->status.max_hp)
  2252. clif_updatestatus (sd, SP_MAXHP);
  2253. if (b_max_sp != sd->status.max_sp)
  2254. clif_updatestatus (sd, SP_MAXSP);
  2255. if (b_hp != sd->status.hp)
  2256. clif_updatestatus (sd, SP_HP);
  2257. if (b_sp != sd->status.sp)
  2258. clif_updatestatus (sd, SP_SP);
  2259. /* if(before.cart_num != before.cart_num || before.cart_max_num != before.cart_max_num ||
  2260. before.cart_weight != before.cart_weight || before.cart_max_weight != before.cart_max_weight )
  2261. clif_updatestatus(sd,SP_CARTINFO);*/
  2262. if (sd->status.hp < sd->status.max_hp >> 2
  2263. && pc_checkskill (sd, SM_AUTOBERSERK) > 0
  2264. && (sd->sc_data[SC_PROVOKE].timer == -1
  2265. || sd->sc_data[SC_PROVOKE].val2 == 0) && !pc_isdead (sd))
  2266. // オートバーサーク発動
  2267. skill_status_change_start (&sd->bl, SC_PROVOKE, 10, 1, 0, 0, 0, 0);
  2268. return 0;
  2269. }
  2270. /*==========================================
  2271. * 装 備品による能力等のボーナス設定
  2272. *------------------------------------------
  2273. */
  2274. int pc_bonus (struct map_session_data *sd, int type, int val)
  2275. {
  2276. nullpo_retr (0, sd);
  2277. switch (type)
  2278. {
  2279. case SP_STR:
  2280. case SP_AGI:
  2281. case SP_VIT:
  2282. case SP_INT:
  2283. case SP_DEX:
  2284. case SP_LUK:
  2285. if (sd->state.lr_flag != 2)
  2286. {
  2287. sd->parame[type - SP_STR] += val;
  2288. if (sd->parame[type - SP_STR] < 0)
  2289. sd->parame[type - SP_STR] = 0;
  2290. }
  2291. break;
  2292. case SP_ATK1:
  2293. if (!sd->state.lr_flag)
  2294. {
  2295. sd->watk += val;
  2296. if (sd->watk < 0)
  2297. sd->watk = 0;
  2298. }
  2299. else if (sd->state.lr_flag == 1)
  2300. {
  2301. sd->watk_ += val;
  2302. if (sd->watk_ < 0)
  2303. sd->watk_ = 0;
  2304. }
  2305. break;
  2306. case SP_ATK2:
  2307. if (!sd->state.lr_flag)
  2308. {
  2309. sd->watk2 += val;
  2310. if (sd->watk2 < 0)
  2311. sd->watk2 = 0;
  2312. }
  2313. else if (sd->state.lr_flag == 1)
  2314. {
  2315. sd->watk_2 += val;
  2316. if (sd->watk_2 < 0)
  2317. sd->watk_2 = 0;
  2318. }
  2319. break;
  2320. case SP_BASE_ATK:
  2321. if (sd->state.lr_flag != 2)
  2322. {
  2323. sd->base_atk += val;
  2324. if (sd->base_atk < 0)
  2325. sd->base_atk = 0;
  2326. }
  2327. break;
  2328. case SP_MATK1:
  2329. if (sd->state.lr_flag != 2)
  2330. {
  2331. sd->matk1 += val;
  2332. if (sd->matk1 < 0)
  2333. sd->matk1 = 0;
  2334. }
  2335. break;
  2336. case SP_MATK2:
  2337. if (sd->state.lr_flag != 2)
  2338. {
  2339. sd->matk2 += val;
  2340. if (sd->matk2 < 0)
  2341. sd->matk2 = 0;
  2342. }
  2343. break;
  2344. case SP_MATK:
  2345. if (sd->state.lr_flag != 2)
  2346. {
  2347. sd->matk1 += val;
  2348. sd->matk2 += val;
  2349. if (sd->matk1 < 0)
  2350. sd->matk1 = 0;
  2351. if (sd->matk2 < 0)
  2352. sd->matk2 = 0;
  2353. }
  2354. break;
  2355. case SP_DEF1:
  2356. if (sd->state.lr_flag != 2)
  2357. {
  2358. sd->def += val;
  2359. if (sd->def < 1)
  2360. sd->def = 1;
  2361. }
  2362. break;
  2363. case SP_MDEF1:
  2364. if (sd->state.lr_flag != 2)
  2365. {
  2366. sd->mdef += val;
  2367. if (sd->mdef < 0)
  2368. sd->mdef = 0;
  2369. }
  2370. break;
  2371. case SP_MDEF2:
  2372. if (sd->state.lr_flag != 2)
  2373. {
  2374. sd->mdef += val;
  2375. if (sd->mdef < 0)
  2376. sd->mdef = 0;
  2377. }
  2378. break;
  2379. case SP_HIT:
  2380. if (sd->state.lr_flag != 2)
  2381. {
  2382. sd->hit += val;
  2383. if (sd->hit < 0)
  2384. sd->hit = 0;
  2385. }
  2386. else
  2387. {
  2388. sd->arrow_hit += val;
  2389. if (sd->arrow_hit < 0)
  2390. sd->arrow_hit = 0;
  2391. }
  2392. break;
  2393. case SP_FLEE1:
  2394. if (sd->state.lr_flag != 2)
  2395. {
  2396. sd->flee += val;
  2397. if (sd->flee < 0)
  2398. sd->flee = 0;
  2399. }
  2400. break;
  2401. case SP_FLEE2:
  2402. if (sd->state.lr_flag != 2)
  2403. {
  2404. sd->flee2 += val * 10;
  2405. if (sd->flee2 < 0)
  2406. sd->flee2 = 0;
  2407. }
  2408. break;
  2409. case SP_CRITICAL:
  2410. if (sd->state.lr_flag != 2)
  2411. {
  2412. sd->critical += val * 10;
  2413. if (sd->critical < 0)
  2414. sd->critical = 0;
  2415. }
  2416. else
  2417. {
  2418. sd->arrow_cri += val * 10;
  2419. if (sd->arrow_cri < 0)
  2420. sd->arrow_cri = 0;
  2421. }
  2422. break;
  2423. case SP_ATKELE:
  2424. if (!sd->state.lr_flag)
  2425. {
  2426. sd->atk_ele = val;
  2427. if (sd->atk_ele < 0)
  2428. sd->atk_ele = 0;
  2429. }
  2430. else if (sd->state.lr_flag == 1)
  2431. {
  2432. sd->atk_ele_ = val;
  2433. if (sd->atk_ele_ < 0)
  2434. sd->atk_ele_ = 0;
  2435. }
  2436. else if (sd->state.lr_flag == 2)
  2437. {
  2438. sd->arrow_ele = val;
  2439. if (sd->arrow_ele < 0)
  2440. sd->arrow_ele = 0;
  2441. }
  2442. break;
  2443. case SP_DEFELE:
  2444. if (sd->state.lr_flag != 2)
  2445. {
  2446. sd->def_ele = val;
  2447. if (sd->def_ele < 0)
  2448. sd->def_ele = 0;
  2449. }
  2450. break;
  2451. case SP_MAXHP:
  2452. if (sd->state.lr_flag != 2)
  2453. {
  2454. sd->status.max_hp += val;
  2455. if (sd->status.max_hp < 1)
  2456. sd->status.max_hp = 1;
  2457. }
  2458. break;
  2459. case SP_MAXSP:
  2460. if (sd->state.lr_flag != 2)
  2461. {
  2462. sd->status.max_sp += val;
  2463. if (sd->status.max_sp < 1)
  2464. sd->status.max_sp = 1;
  2465. }
  2466. break;
  2467. case SP_CASTRATE:
  2468. if (sd->state.lr_flag != 2)
  2469. {
  2470. sd->castrate += val;
  2471. if (sd->castrate < 1)
  2472. sd->castrate = 1;
  2473. }
  2474. break;
  2475. case SP_MAXHPRATE:
  2476. if (sd->state.lr_flag != 2)
  2477. {
  2478. sd->hprate += val;
  2479. if (sd->hprate < 1)
  2480. sd->hprate = 1;
  2481. }
  2482. break;
  2483. case SP_MAXSPRATE:
  2484. if (sd->state.lr_flag != 2)
  2485. {
  2486. sd->sprate += val;
  2487. if (sd->sprate < 1)
  2488. sd->sprate = 1;
  2489. }
  2490. break;
  2491. case SP_SPRATE:
  2492. if (sd->state.lr_flag != 2)
  2493. {
  2494. sd->dsprate += val;
  2495. if (sd->dsprate < 1)
  2496. sd->dsprate = 1;
  2497. }
  2498. break;
  2499. case SP_ATTACKRANGE:
  2500. if (!sd->state.lr_flag)
  2501. {
  2502. sd->attackrange += val;
  2503. if (sd->attackrange < 1)
  2504. sd->attackrange = 1;
  2505. }
  2506. else if (sd->state.lr_flag == 1)
  2507. {
  2508. sd->attackrange_ += val;
  2509. if (sd->attackrange_ < 1)
  2510. sd->attackrange_ = 1;
  2511. }
  2512. else if (sd->state.lr_flag == 2)
  2513. {
  2514. sd->arrow_range += val;
  2515. if (sd->arrow_range < 1)
  2516. sd->arrow_range = 1;
  2517. }
  2518. break;
  2519. case SP_ADDATTACKRANGE:
  2520. if (!sd->state.lr_flag)
  2521. {
  2522. if (sd->attackrange == 0)
  2523. sd->attackrange = 1;
  2524. sd->attackrange += val;
  2525. if (sd->attackrange < 1)
  2526. sd->attackrange = 1;
  2527. }
  2528. else if (sd->state.lr_flag == 1)
  2529. {
  2530. if (sd->attackrange_ == 0)
  2531. sd->attackrange_ = 1;
  2532. sd->attackrange_ += val;
  2533. if (sd->attackrange_ < 1)
  2534. sd->attackrange_ = 1;
  2535. }
  2536. else if (sd->state.lr_flag == 2)
  2537. {
  2538. if (sd->arrow_range == 0)
  2539. sd->arrow_range = 1;
  2540. sd->arrow_range = +val;
  2541. if (sd->arrow_range < 1)
  2542. sd->arrow_range = 1;
  2543. }
  2544. break;
  2545. case SP_ADD_SPEED:
  2546. if (sd->state.lr_flag != 2)
  2547. sd->speed -= val;
  2548. break;
  2549. case SP_SPEED_RATE:
  2550. if (sd->state.lr_flag != 2)
  2551. {
  2552. if (val < 100)
  2553. {
  2554. if (sd->speed_rate > 100 - val)
  2555. sd->speed_rate = 100 - val;
  2556. }
  2557. else
  2558. {
  2559. sd->speed_rate = 1;
  2560. }
  2561. }
  2562. break;
  2563. case SP_SPEED_ADDRATE:
  2564. if (sd->state.lr_flag != 2)
  2565. {
  2566. sd->speed_add_rate = sd->speed_add_rate * (100 - val) / 100;
  2567. // if (sd->speed_add_rate < 0)
  2568. // sd->speed_add_rate = 0;
  2569. }
  2570. break;
  2571. case SP_ASPD:
  2572. if (sd->state.lr_flag != 2)
  2573. {
  2574. if (sd->aspd >= val * 10)
  2575. sd->aspd -= val * 10;
  2576. else
  2577. sd->aspd = 1;
  2578. }
  2579. break;
  2580. case SP_ASPD_RATE:
  2581. if (sd->state.lr_flag != 2)
  2582. {
  2583. if (val < 100)
  2584. {
  2585. if (sd->aspd_rate > 100 - val)
  2586. sd->aspd_rate = 100 - val;
  2587. }
  2588. else
  2589. {
  2590. sd->aspd_rate = 1;
  2591. }
  2592. }
  2593. break;
  2594. case SP_ASPD_ADDRATE:
  2595. if (sd->state.lr_flag != 2)
  2596. {
  2597. sd->aspd_add_rate = sd->aspd_add_rate * (100 - val) / 100;
  2598. // if (sd->aspd_add_rate < 0)
  2599. // sd->aspd_add_rate = 1;
  2600. }
  2601. break;
  2602. case SP_HP_RECOV_RATE:
  2603. if (sd->state.lr_flag != 2)
  2604. {
  2605. sd->hprecov_rate += val;
  2606. if (sd->hprecov_rate < 0)
  2607. sd->hprecov_rate = 0;
  2608. }
  2609. break;
  2610. case SP_SP_RECOV_RATE:
  2611. if (sd->state.lr_flag != 2)
  2612. {
  2613. sd->sprecov_rate += val;
  2614. if (sd->sprecov_rate < 0)
  2615. sd->sprecov_rate = 0;
  2616. }
  2617. break;
  2618. case SP_CRITICAL_DEF:
  2619. if (sd->state.lr_flag != 2)
  2620. {
  2621. sd->critical_def += val;
  2622. if (sd->critical_def < 0)
  2623. sd->critical_def = 0;
  2624. }
  2625. break;
  2626. case SP_NEAR_ATK_DEF:
  2627. if (sd->state.lr_flag != 2)
  2628. {
  2629. sd->near_attack_def_rate += val;
  2630. if (sd->near_attack_def_rate < 0)
  2631. sd->near_attack_def_rate = 0;
  2632. }
  2633. break;
  2634. case SP_LONG_ATK_DEF:
  2635. if (sd->state.lr_flag != 2)
  2636. {
  2637. sd->long_attack_def_rate += val;
  2638. if (sd->long_attack_def_rate < 0)
  2639. sd->long_attack_def_rate = 0;
  2640. }
  2641. break;
  2642. case SP_DOUBLE_RATE:
  2643. if (sd->state.lr_flag == 0 && sd->double_rate < val)
  2644. {
  2645. sd->double_rate = val;
  2646. if (sd->double_rate < 0)
  2647. sd->double_rate = 0;
  2648. }
  2649. break;
  2650. case SP_DOUBLE_ADD_RATE:
  2651. if (sd->state.lr_flag == 0)
  2652. {
  2653. sd->double_add_rate += val;
  2654. // if (sd->double_add_rate < 0)
  2655. // sd->double_add_rate = 0;
  2656. }
  2657. break;
  2658. case SP_MATK_RATE:
  2659. if (sd->state.lr_flag != 2)
  2660. {
  2661. sd->matk_rate += val;
  2662. if (sd->matk_rate < 0)
  2663. sd->matk_rate = 0;
  2664. }
  2665. break;
  2666. case SP_IGNORE_DEF_ELE:
  2667. if (!sd->state.lr_flag)
  2668. sd->ignore_def_ele |= 1 << val;
  2669. else if (sd->state.lr_flag == 1)
  2670. sd->ignore_def_ele_ |= 1 << val;
  2671. break;
  2672. case SP_IGNORE_DEF_RACE:
  2673. if (!sd->state.lr_flag)
  2674. sd->ignore_def_race |= 1 << val;
  2675. else if (sd->state.lr_flag == 1)
  2676. sd->ignore_def_race_ |= 1 << val;
  2677. break;
  2678. case SP_ATK_RATE:
  2679. if (sd->state.lr_flag != 2)
  2680. {
  2681. sd->atk_rate += val;
  2682. if (sd->atk_rate < 0)
  2683. sd->atk_rate = 0;
  2684. }
  2685. break;
  2686. case SP_MAGIC_ATK_DEF:
  2687. if (sd->state.lr_flag != 2)
  2688. {
  2689. sd->magic_def_rate += val;
  2690. if (sd->magic_def_rate < 0)
  2691. sd->magic_def_rate = 0;
  2692. }
  2693. break;
  2694. case SP_MISC_ATK_DEF:
  2695. if (sd->state.lr_flag != 2)
  2696. {
  2697. sd->misc_def_rate += val;
  2698. if (sd->misc_def_rate < 0)
  2699. sd->misc_def_rate = 0;
  2700. }
  2701. break;
  2702. case SP_IGNORE_MDEF_ELE:
  2703. if (sd->state.lr_flag != 2)
  2704. sd->ignore_mdef_ele |= 1 << val;
  2705. break;
  2706. case SP_IGNORE_MDEF_RACE:
  2707. if (sd->state.lr_flag != 2)
  2708. sd->ignore_mdef_race |= 1 << val;
  2709. break;
  2710. case SP_PERFECT_HIT_RATE:
  2711. if (sd->state.lr_flag != 2 && sd->perfect_hit < val)
  2712. {
  2713. sd->perfect_hit = val;
  2714. if (sd->perfect_hit < 0)
  2715. sd->perfect_hit = 0;
  2716. }
  2717. break;
  2718. case SP_PERFECT_HIT_ADD_RATE:
  2719. if (sd->state.lr_flag != 2)
  2720. {
  2721. sd->perfect_hit_add += val;
  2722. // if (sd->perfect_hit_add < 0)
  2723. // sd->perfect_hit_add = 0;
  2724. }
  2725. break;
  2726. case SP_CRITICAL_RATE:
  2727. if (sd->state.lr_flag != 2)
  2728. {
  2729. sd->critical_rate += val;
  2730. if (sd->critical_rate < 0)
  2731. sd->critical_rate = 0;
  2732. }
  2733. break;
  2734. case SP_GET_ZENY_NUM:
  2735. if (sd->state.lr_flag != 2 && sd->get_zeny_num < val)
  2736. {
  2737. sd->get_zeny_num = val;
  2738. if (sd->get_zeny_num < 0)
  2739. sd->get_zeny_num = 0;
  2740. }
  2741. break;
  2742. case SP_ADD_GET_ZENY_NUM:
  2743. if (sd->state.lr_flag != 2)
  2744. {
  2745. sd->get_zeny_add_num += val;
  2746. // if (sd->get_zeny_add_num < 0)
  2747. // sd->get_zeny_add_num = 0;
  2748. }
  2749. break;
  2750. case SP_DEF_RATIO_ATK_ELE:
  2751. if (!sd->state.lr_flag)
  2752. sd->def_ratio_atk_ele |= 1 << val;
  2753. else if (sd->state.lr_flag == 1)
  2754. sd->def_ratio_atk_ele_ |= 1 << val;
  2755. break;
  2756. case SP_DEF_RATIO_ATK_RACE:
  2757. if (!sd->state.lr_flag)
  2758. sd->def_ratio_atk_race |= 1 << val;
  2759. else if (sd->state.lr_flag == 1)
  2760. sd->def_ratio_atk_race_ |= 1 << val;
  2761. break;
  2762. case SP_HIT_RATE:
  2763. if (sd->state.lr_flag != 2)
  2764. {
  2765. sd->hit_rate += val;
  2766. if (sd->hit_rate < 0)
  2767. sd->hit_rate = 0;
  2768. }
  2769. break;
  2770. case SP_FLEE_RATE:
  2771. if (sd->state.lr_flag != 2)
  2772. {
  2773. sd->flee_rate += val;
  2774. if (sd->flee_rate < 0)
  2775. sd->flee_rate = 0;
  2776. }
  2777. break;
  2778. case SP_FLEE2_RATE:
  2779. if (sd->state.lr_flag != 2)
  2780. {
  2781. sd->flee2_rate += val;
  2782. if (sd->flee2_rate < 0)
  2783. sd->flee2_rate = 0;
  2784. }
  2785. break;
  2786. case SP_DEF_RATE:
  2787. if (sd->state.lr_flag != 2)
  2788. {
  2789. sd->def_rate += val;
  2790. if (sd->def_rate < 0)
  2791. sd->def_rate = 0;
  2792. }
  2793. break;
  2794. case SP_DEF2_RATE:
  2795. if (sd->state.lr_flag != 2)
  2796. {
  2797. sd->def2_rate += val;
  2798. if (sd->def2_rate < 0)
  2799. sd->def2_rate = 0;
  2800. }
  2801. break;
  2802. case SP_MDEF_RATE:
  2803. if (sd->state.lr_flag != 2)
  2804. {
  2805. sd->mdef_rate += val;
  2806. if (sd->mdef_rate < 0)
  2807. sd->mdef_rate = 0;
  2808. }
  2809. break;
  2810. case SP_MDEF2_RATE:
  2811. if (sd->state.lr_flag != 2)
  2812. {
  2813. sd->mdef2_rate += val;
  2814. if (sd->mdef2_rate < 0)
  2815. sd->mdef2_rate = 0;
  2816. }
  2817. break;
  2818. case SP_RESTART_FULL_RECORVER:
  2819. if (sd->state.lr_flag != 2)
  2820. sd->special_state.restart_full_recover = 1;
  2821. break;
  2822. case SP_NO_CASTCANCEL:
  2823. if (sd->state.lr_flag != 2)
  2824. sd->special_state.no_castcancel = 1;
  2825. break;
  2826. case SP_NO_CASTCANCEL2:
  2827. if (sd->state.lr_flag != 2)
  2828. sd->special_state.no_castcancel2 = 1;
  2829. break;
  2830. case SP_NO_SIZEFIX:
  2831. if (sd->state.lr_flag != 2)
  2832. sd->special_state.no_sizefix = 1;
  2833. break;
  2834. case SP_NO_MAGIC_DAMAGE:
  2835. if (sd->state.lr_flag != 2)
  2836. sd->special_state.no_magic_damage = 1;
  2837. break;
  2838. case SP_NO_WEAPON_DAMAGE:
  2839. if (sd->state.lr_flag != 2)
  2840. sd->special_state.no_weapon_damage = 1;
  2841. break;
  2842. case SP_NO_GEMSTONE:
  2843. if (sd->state.lr_flag != 2)
  2844. sd->special_state.no_gemstone = 1;
  2845. break;
  2846. case SP_INFINITE_ENDURE:
  2847. if (sd->state.lr_flag != 2)
  2848. sd->special_state.infinite_endure = 1;
  2849. break;
  2850. case SP_SPLASH_RANGE:
  2851. if (sd->state.lr_flag != 2 && sd->splash_range < val)
  2852. {
  2853. sd->splash_range = val;
  2854. if (sd->splash_range < 0)
  2855. sd->splash_range = 0;
  2856. }
  2857. break;
  2858. case SP_SPLASH_ADD_RANGE:
  2859. if (sd->state.lr_flag != 2)
  2860. {
  2861. sd->splash_add_range += val;
  2862. // if (sd->splash_add_range < 0)
  2863. // sd->splash_add_range = 0;
  2864. }
  2865. break;
  2866. case SP_SHORT_WEAPON_DAMAGE_RETURN:
  2867. if (sd->state.lr_flag != 2)
  2868. {
  2869. sd->short_weapon_damage_return += val;
  2870. if (sd->short_weapon_damage_return < 0)
  2871. sd->short_weapon_damage_return = 0;
  2872. }
  2873. break;
  2874. case SP_LONG_WEAPON_DAMAGE_RETURN:
  2875. if (sd->state.lr_flag != 2)
  2876. {
  2877. sd->long_weapon_damage_return += val;
  2878. if (sd->long_weapon_damage_return < 0)
  2879. sd->long_weapon_damage_return = 0;
  2880. }
  2881. break;
  2882. case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here
  2883. if (sd->state.lr_flag != 2)
  2884. {
  2885. sd->magic_damage_return += val;
  2886. if (sd->magic_damage_return < 0)
  2887. sd->magic_damage_return = 0;
  2888. }
  2889. break;
  2890. case SP_ALL_STATS: // [Valaris]
  2891. if (sd->state.lr_flag != 2)
  2892. {
  2893. sd->parame[SP_STR - SP_STR] += val;
  2894. if (sd->parame[SP_STR - SP_STR] < 1)
  2895. sd->parame[SP_STR - SP_STR] = 1;
  2896. sd->parame[SP_AGI - SP_STR] += val;
  2897. if (sd->parame[SP_AGI - SP_STR] < 1)
  2898. sd->parame[SP_AGI - SP_STR] = 1;
  2899. sd->parame[SP_VIT - SP_STR] += val;
  2900. if (sd->parame[SP_VIT - SP_STR] < 1)
  2901. sd->parame[SP_VIT - SP_STR] = 1;
  2902. sd->parame[SP_INT - SP_STR] += val;
  2903. if (sd->parame[SP_INT - SP_STR] < 1)
  2904. sd->parame[SP_INT - SP_STR] = 1;
  2905. sd->parame[SP_DEX - SP_STR] += val;
  2906. if (sd->parame[SP_DEX - SP_STR] < 1)
  2907. sd->parame[SP_DEX - SP_STR] = 1;
  2908. sd->parame[SP_LUK - SP_STR] += val;
  2909. if (sd->parame[SP_LUK - SP_STR] < 1)
  2910. sd->parame[SP_LUK - SP_STR] = 1;
  2911. clif_updatestatus (sd, 13);
  2912. clif_updatestatus (sd, 14);
  2913. clif_updatestatus (sd, 15);
  2914. clif_updatestatus (sd, 16);
  2915. clif_updatestatus (sd, 17);
  2916. clif_updatestatus (sd, 18);
  2917. }
  2918. break;
  2919. case SP_AGI_VIT: // [Valaris]
  2920. if (sd->state.lr_flag != 2)
  2921. {
  2922. sd->parame[SP_AGI - SP_STR] += val;
  2923. if (sd->parame[SP_AGI - SP_STR] < 1)
  2924. sd->parame[SP_AGI - SP_STR] = 1;
  2925. sd->parame[SP_VIT - SP_STR] += val;
  2926. if (sd->parame[SP_VIT - SP_STR] < 1)
  2927. sd->parame[SP_VIT - SP_STR] = 1;
  2928. clif_updatestatus (sd, 14);
  2929. clif_updatestatus (sd, 15);
  2930. }
  2931. break;
  2932. case SP_AGI_DEX_STR: // [Valaris]
  2933. if (sd->state.lr_flag != 2)
  2934. {
  2935. sd->parame[SP_AGI - SP_STR] += val;
  2936. if (sd->parame[SP_AGI - SP_STR] < 1)
  2937. sd->parame[SP_AGI - SP_STR] = 1;
  2938. sd->parame[SP_DEX - SP_STR] += val;
  2939. if (sd->parame[SP_DEX - SP_STR] < 1)
  2940. sd->parame[SP_DEX - SP_STR] = 1;
  2941. sd->parame[SP_STR - SP_STR] += val;
  2942. if (sd->parame[SP_STR - SP_STR] < 1)
  2943. sd->parame[SP_STR - SP_STR] = 1;
  2944. clif_updatestatus (sd, 14);
  2945. clif_updatestatus (sd, 17);
  2946. clif_updatestatus (sd, 13);
  2947. }
  2948. break;
  2949. case SP_PERFECT_HIDE: // [Valaris]
  2950. if (sd->state.lr_flag != 2)
  2951. {
  2952. sd->perfect_hiding = 1;
  2953. }
  2954. break;
  2955. case SP_DISGUISE: // Disguise script for items [Valaris]
  2956. if (sd->state.lr_flag != 2 && sd->disguiseflag == 0)
  2957. {
  2958. if (pc_isriding (sd))
  2959. { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
  2960. clif_displaymessage (sd->fd,
  2961. "Cannot wear disguise when riding a Peco.");
  2962. break;
  2963. }
  2964. sd->disguise = val;
  2965. clif_clearchar (&sd->bl, 9);
  2966. pc_setpos (sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
  2967. }
  2968. break;
  2969. case SP_UNBREAKABLE:
  2970. if (sd->state.lr_flag != 2)
  2971. {
  2972. sd->unbreakable += val;
  2973. if (sd->unbreakable < 0)
  2974. sd->unbreakable = 0;
  2975. }
  2976. break;
  2977. case SP_DEAF:
  2978. sd->special_state.deaf = 1;
  2979. break;
  2980. default:
  2981. if (battle_config.error_log)
  2982. printf ("pc_bonus: unknown type %d %d !\n", type, val);
  2983. break;
  2984. }
  2985. return 0;
  2986. }
  2987. /*==========================================
  2988. * 装 備品による能力等のボーナス設定
  2989. *------------------------------------------
  2990. */
  2991. int pc_bonus2 (struct map_session_data *sd, int type, int type2, int val)
  2992. {
  2993. int i;
  2994. nullpo_retr (0, sd);
  2995. switch (type)
  2996. {
  2997. case SP_ADDELE:
  2998. if (type2 < 0 || type2 >= 10)
  2999. break;
  3000. if (!sd->state.lr_flag)
  3001. sd->addele[type2] += val;
  3002. else if (sd->state.lr_flag == 1)
  3003. sd->addele_[type2] += val;
  3004. else if (sd->state.lr_flag == 2)
  3005. sd->arrow_addele[type2] += val;
  3006. break;
  3007. case SP_ADDRACE:
  3008. if (type2 < 0 || type2 >= 12)
  3009. break;
  3010. if (!sd->state.lr_flag)
  3011. sd->addrace[type2] += val;
  3012. else if (sd->state.lr_flag == 1)
  3013. sd->addrace_[type2] += val;
  3014. else if (sd->state.lr_flag == 2)
  3015. sd->arrow_addrace[type2] += val;
  3016. break;
  3017. case SP_ADDSIZE:
  3018. if (type2 < 0 || type2 >= 3)
  3019. break;
  3020. if (!sd->state.lr_flag)
  3021. sd->addsize[type2] += val;
  3022. else if (sd->state.lr_flag == 1)
  3023. sd->addsize_[type2] += val;
  3024. else if (sd->state.lr_flag == 2)
  3025. sd->arrow_addsize[type2] += val;
  3026. break;
  3027. case SP_SUBELE:
  3028. if (type2 < 0 || type2 >= 10)
  3029. break;
  3030. if (sd->state.lr_flag != 2)
  3031. sd->subele[type2] += val;
  3032. break;
  3033. case SP_SUBRACE:
  3034. if (type2 < 0 || type2 >= 12)
  3035. break;
  3036. if (sd->state.lr_flag != 2)
  3037. sd->subrace[type2] += val;
  3038. break;
  3039. case SP_ADDEFF:
  3040. if (type2 < 0 || type2 >= 10)
  3041. break;
  3042. if (sd->state.lr_flag != 2)
  3043. sd->addeff[type2] += val;
  3044. else
  3045. sd->arrow_addeff[type2] += val;
  3046. break;
  3047. case SP_ADDEFF2:
  3048. if (type2 < 0 || type2 >= 10)
  3049. break;
  3050. if (sd->state.lr_flag != 2)
  3051. sd->addeff2[type2] += val;
  3052. else
  3053. sd->arrow_addeff2[type2] += val;
  3054. break;
  3055. case SP_RESEFF:
  3056. if (type2 < 0 || type2 >= 10)
  3057. break;
  3058. if (sd->state.lr_flag != 2)
  3059. sd->reseff[type2] += val;
  3060. break;
  3061. case SP_MAGIC_ADDELE:
  3062. if (type2 < 0 || type2 >= 10)
  3063. break;
  3064. if (sd->state.lr_flag != 2)
  3065. sd->magic_addele[type2] += val;
  3066. break;
  3067. case SP_MAGIC_ADDRACE:
  3068. if (type2 < 0 || type2 >= 12)
  3069. break;
  3070. if (sd->state.lr_flag != 2)
  3071. sd->magic_addrace[type2] += val;
  3072. break;
  3073. case SP_MAGIC_SUBRACE:
  3074. if (type2 < 0 || type2 >= 12)
  3075. break;
  3076. if (sd->state.lr_flag != 2)
  3077. sd->magic_subrace[type2] += val;
  3078. break;
  3079. case SP_ADD_DAMAGE_CLASS:
  3080. if (!sd->state.lr_flag)
  3081. {
  3082. for (i = 0; i < sd->add_damage_class_count; i++)
  3083. {
  3084. if (sd->add_damage_classid[i] == type2)
  3085. {
  3086. sd->add_damage_classrate[i] += val;
  3087. break;
  3088. }
  3089. }
  3090. if (i >= sd->add_damage_class_count
  3091. && sd->add_damage_class_count < 10)
  3092. {
  3093. sd->add_damage_classid[sd->add_damage_class_count] =
  3094. type2;
  3095. sd->add_damage_classrate[sd->add_damage_class_count] +=
  3096. val;
  3097. sd->add_damage_class_count++;
  3098. }
  3099. }
  3100. else if (sd->state.lr_flag == 1)
  3101. {
  3102. for (i = 0; i < sd->add_damage_class_count_; i++)
  3103. {
  3104. if (sd->add_damage_classid_[i] == type2)
  3105. {
  3106. sd->add_damage_classrate_[i] += val;
  3107. break;
  3108. }
  3109. }
  3110. if (i >= sd->add_damage_class_count_
  3111. && sd->add_damage_class_count_ < 10)
  3112. {
  3113. sd->add_damage_classid_[sd->add_damage_class_count_] =
  3114. type2;
  3115. sd->add_damage_classrate_[sd->add_damage_class_count_] +=
  3116. val;
  3117. sd->add_damage_class_count_++;
  3118. }
  3119. }
  3120. break;
  3121. case SP_ADD_MAGIC_DAMAGE_CLASS:
  3122. if (sd->state.lr_flag != 2)
  3123. {
  3124. for (i = 0; i < sd->add_magic_damage_class_count; i++)
  3125. {
  3126. if (sd->add_magic_damage_classid[i] == type2)
  3127. {
  3128. sd->add_magic_damage_classrate[i] += val;
  3129. break;
  3130. }
  3131. }
  3132. if (i >= sd->add_magic_damage_class_count
  3133. && sd->add_magic_damage_class_count < 10)
  3134. {
  3135. sd->add_magic_damage_classid
  3136. [sd->add_magic_damage_class_count] = type2;
  3137. sd->add_magic_damage_classrate
  3138. [sd->add_magic_damage_class_count] += val;
  3139. sd->add_magic_damage_class_count++;
  3140. }
  3141. }
  3142. break;
  3143. case SP_ADD_DEF_CLASS:
  3144. if (sd->state.lr_flag != 2)
  3145. {
  3146. for (i = 0; i < sd->add_def_class_count; i++)
  3147. {
  3148. if (sd->add_def_classid[i] == type2)
  3149. {
  3150. sd->add_def_classrate[i] += val;
  3151. break;
  3152. }
  3153. }
  3154. if (i >= sd->add_def_class_count
  3155. && sd->add_def_class_count < 10)
  3156. {
  3157. sd->add_def_classid[sd->add_def_class_count] = type2;
  3158. sd->add_def_classrate[sd->add_def_class_count] += val;
  3159. sd->add_def_class_count++;
  3160. }
  3161. }
  3162. break;
  3163. case SP_ADD_MDEF_CLASS:
  3164. if (sd->state.lr_flag != 2)
  3165. {
  3166. for (i = 0; i < sd->add_mdef_class_count; i++)
  3167. {
  3168. if (sd->add_mdef_classid[i] == type2)
  3169. {
  3170. sd->add_mdef_classrate[i] += val;
  3171. break;
  3172. }
  3173. }
  3174. if (i >= sd->add_mdef_class_count
  3175. && sd->add_mdef_class_count < 10)
  3176. {
  3177. sd->add_mdef_classid[sd->add_mdef_class_count] = type2;
  3178. sd->add_mdef_classrate[sd->add_mdef_class_count] += val;
  3179. sd->add_mdef_class_count++;
  3180. }
  3181. }
  3182. break;
  3183. case SP_HP_DRAIN_RATE:
  3184. if (!sd->state.lr_flag)
  3185. {
  3186. sd->hp_drain_rate += type2;
  3187. sd->hp_drain_per += val;
  3188. }
  3189. else if (sd->state.lr_flag == 1)
  3190. {
  3191. sd->hp_drain_rate_ += type2;
  3192. sd->hp_drain_per_ += val;
  3193. }
  3194. break;
  3195. case SP_SP_DRAIN_RATE:
  3196. if (!sd->state.lr_flag)
  3197. {
  3198. sd->sp_drain_rate += type2;
  3199. sd->sp_drain_per += val;
  3200. }
  3201. else if (sd->state.lr_flag == 1)
  3202. {
  3203. sd->sp_drain_rate_ += type2;
  3204. sd->sp_drain_per_ += val;
  3205. }
  3206. break;
  3207. case SP_WEAPON_COMA_ELE:
  3208. if (type2 < 0 || type2 >= 10)
  3209. break;
  3210. if (sd->state.lr_flag != 2)
  3211. sd->weapon_coma_ele[type2] += val;
  3212. break;
  3213. case SP_WEAPON_COMA_RACE:
  3214. if (type2 < 0 || type2 >= 12)
  3215. break;
  3216. if (sd->state.lr_flag != 2)
  3217. sd->weapon_coma_race[type2] += val;
  3218. break;
  3219. case SP_RANDOM_ATTACK_INCREASE: // [Valaris]
  3220. if (sd->state.lr_flag != 2)
  3221. {
  3222. sd->random_attack_increase_add = type2;
  3223. sd->random_attack_increase_per += val;
  3224. break;
  3225. } // end addition
  3226. default:
  3227. if (battle_config.error_log)
  3228. printf ("pc_bonus2: unknown type %d %d %d!\n", type, type2,
  3229. val);
  3230. break;
  3231. }
  3232. return 0;
  3233. }
  3234. int pc_bonus3 (struct map_session_data *sd, int type, int type2, int type3,
  3235. int val)
  3236. {
  3237. int i;
  3238. nullpo_retr (0, sd);
  3239. switch (type)
  3240. {
  3241. case SP_ADD_MONSTER_DROP_ITEM:
  3242. if (sd->state.lr_flag != 2)
  3243. {
  3244. for (i = 0; i < sd->monster_drop_item_count; i++)
  3245. {
  3246. if (sd->monster_drop_itemid[i] == type2)
  3247. {
  3248. sd->monster_drop_race[i] |= 1 << type3;
  3249. if (sd->monster_drop_itemrate[i] < val)
  3250. sd->monster_drop_itemrate[i] = val;
  3251. break;
  3252. }
  3253. }
  3254. if (i >= sd->monster_drop_item_count
  3255. && sd->monster_drop_item_count < 10)
  3256. {
  3257. sd->monster_drop_itemid[sd->monster_drop_item_count] =
  3258. type2;
  3259. sd->monster_drop_race[sd->monster_drop_item_count] |=
  3260. 1 << type3;
  3261. sd->monster_drop_itemrate[sd->monster_drop_item_count] =
  3262. val;
  3263. sd->monster_drop_item_count++;
  3264. }
  3265. }
  3266. break;
  3267. case SP_AUTOSPELL:
  3268. if (sd->state.lr_flag != 2)
  3269. {
  3270. sd->autospell_id = type2;
  3271. sd->autospell_lv = type3;
  3272. sd->autospell_rate = val;
  3273. }
  3274. break;
  3275. default:
  3276. if (battle_config.error_log)
  3277. printf ("pc_bonus3: unknown type %d %d %d %d!\n", type, type2,
  3278. type3, val);
  3279. break;
  3280. }
  3281. return 0;
  3282. }
  3283. /*==========================================
  3284. * スクリプトによるスキル所得
  3285. *------------------------------------------
  3286. */
  3287. int pc_skill (struct map_session_data *sd, int id, int level, int flag)
  3288. {
  3289. nullpo_retr (0, sd);
  3290. if (id < 0 || id >= MAX_SKILL)
  3291. return 0;
  3292. if (level > MAX_SKILL_LEVEL)
  3293. {
  3294. if (battle_config.error_log)
  3295. printf ("support card skill only!\n");
  3296. return 0;
  3297. }
  3298. if (!flag && (sd->status.skill[id].id == id || level == 0))
  3299. { // クエスト所得ならここで条件を確認して送信する
  3300. sd->status.skill[id].lv = level;
  3301. pc_calcstatus (sd, 0);
  3302. clif_skillinfoblock (sd);
  3303. }
  3304. else if (sd->status.skill[id].lv < level)
  3305. { // 覚えられるがlvが小さいなら
  3306. sd->status.skill[id].id = id;
  3307. sd->status.skill[id].lv = level;
  3308. }
  3309. return 0;
  3310. }
  3311. /*==========================================
  3312. * カード挿入
  3313. *------------------------------------------
  3314. */
  3315. int pc_insert_card (struct map_session_data *sd, int idx_card, int idx_equip)
  3316. {
  3317. nullpo_retr (0, sd);
  3318. if (idx_card >= 0 && idx_card < MAX_INVENTORY && idx_equip >= 0
  3319. && idx_equip < MAX_INVENTORY && sd->inventory_data[idx_card])
  3320. {
  3321. int i;
  3322. int nameid = sd->status.inventory[idx_equip].nameid;
  3323. int cardid = sd->status.inventory[idx_card].nameid;
  3324. int ep = sd->inventory_data[idx_card]->equip;
  3325. if (nameid <= 0 || sd->inventory_data[idx_equip] == NULL || (sd->inventory_data[idx_equip]->type != 4 && sd->inventory_data[idx_equip]->type != 5) ||
  3326. // 装 備じゃない
  3327. (sd->status.inventory[idx_equip].identify == 0) || // 未鑑定
  3328. (sd->status.inventory[idx_equip].card[0] == 0x00ff) || // 製造武器
  3329. (sd->status.inventory[idx_equip].card[0] == 0x00fe) || ((sd->inventory_data[idx_equip]->equip & ep) == 0) || // 装 備個所違い
  3330. (sd->inventory_data[idx_equip]->type == 4 && ep == 32) || // 両 手武器と盾カード
  3331. (sd->status.inventory[idx_equip].card[0] == (short) 0xff00)
  3332. || sd->status.inventory[idx_equip].equip)
  3333. {
  3334. clif_insert_card (sd, idx_equip, idx_card, 1);
  3335. return 0;
  3336. }
  3337. for (i = 0; i < sd->inventory_data[idx_equip]->slot; i++)
  3338. {
  3339. if (sd->status.inventory[idx_equip].card[i] == 0)
  3340. {
  3341. // 空きスロットがあったので差し込む
  3342. sd->status.inventory[idx_equip].card[i] = cardid;
  3343. // カードは減らす
  3344. clif_insert_card (sd, idx_equip, idx_card, 0);
  3345. pc_delitem (sd, idx_card, 1, 1);
  3346. return 0;
  3347. }
  3348. }
  3349. }
  3350. else
  3351. clif_insert_card (sd, idx_equip, idx_card, 1);
  3352. return 0;
  3353. }
  3354. //
  3355. // アイテム物
  3356. //
  3357. /*==========================================
  3358. * スキルによる買い値修正
  3359. *------------------------------------------
  3360. */
  3361. int pc_modifybuyvalue (struct map_session_data *sd, int orig_value)
  3362. {
  3363. int skill, val = orig_value, rate1 = 0, rate2 = 0;
  3364. if ((skill = pc_checkskill (sd, MC_DISCOUNT)) > 0) // ディスカウント
  3365. rate1 = 5 + skill * 2 - ((skill == 10) ? 1 : 0);
  3366. if ((skill = pc_checkskill (sd, RG_COMPULSION)) > 0) // コムパルションディスカウント
  3367. rate2 = 5 + skill * 4;
  3368. if (rate1 < rate2)
  3369. rate1 = rate2;
  3370. if (rate1)
  3371. val = (int) ((double) orig_value * (double) (100 - rate1) / 100.);
  3372. if (val < 0)
  3373. val = 0;
  3374. if (orig_value > 0 && val < 1)
  3375. val = 1;
  3376. return val;
  3377. }
  3378. /*==========================================
  3379. * スキルによる売り値修正
  3380. *------------------------------------------
  3381. */
  3382. int pc_modifysellvalue (struct map_session_data *sd, int orig_value)
  3383. {
  3384. int skill, val = orig_value, rate = 0;
  3385. if ((skill = pc_checkskill (sd, MC_OVERCHARGE)) > 0) // オーバーチャージ
  3386. rate = 5 + skill * 2 - ((skill == 10) ? 1 : 0);
  3387. if (rate)
  3388. val = (int) ((double) orig_value * (double) (100 + rate) / 100.);
  3389. if (val < 0)
  3390. val = 0;
  3391. if (orig_value > 0 && val < 1)
  3392. val = 1;
  3393. return val;
  3394. }
  3395. /*==========================================
  3396. * アイテムを買った時に、新しいアイテム欄を使うか、
  3397. * 3万個制限にかかるか確認
  3398. *------------------------------------------
  3399. */
  3400. int pc_checkadditem (struct map_session_data *sd, int nameid, int amount)
  3401. {
  3402. int i;
  3403. nullpo_retr (0, sd);
  3404. if (itemdb_isequip (nameid))
  3405. return ADDITEM_NEW;
  3406. for (i = 0; i < MAX_INVENTORY; i++)
  3407. {
  3408. if (sd->status.inventory[i].nameid == nameid)
  3409. {
  3410. if (sd->status.inventory[i].amount + amount > MAX_AMOUNT)
  3411. return ADDITEM_OVERAMOUNT;
  3412. return ADDITEM_EXIST;
  3413. }
  3414. }
  3415. if (amount > MAX_AMOUNT)
  3416. return ADDITEM_OVERAMOUNT;
  3417. return ADDITEM_NEW;
  3418. }
  3419. /*==========================================
  3420. * 空きアイテム欄の個数
  3421. *------------------------------------------
  3422. */
  3423. int pc_inventoryblank (struct map_session_data *sd)
  3424. {
  3425. int i, b;
  3426. nullpo_retr (0, sd);
  3427. for (i = 0, b = 0; i < MAX_INVENTORY; i++)
  3428. {
  3429. if (sd->status.inventory[i].nameid == 0)
  3430. b++;
  3431. }
  3432. return b;
  3433. }
  3434. /*==========================================
  3435. * お金を払う
  3436. *------------------------------------------
  3437. */
  3438. int pc_payzeny (struct map_session_data *sd, int zeny)
  3439. {
  3440. double z;
  3441. nullpo_retr (0, sd);
  3442. z = (double) sd->status.zeny;
  3443. if (sd->status.zeny < zeny || z - (double) zeny > MAX_ZENY)
  3444. return 1;
  3445. sd->status.zeny -= zeny;
  3446. clif_updatestatus (sd, SP_ZENY);
  3447. return 0;
  3448. }
  3449. /*==========================================
  3450. * お金を得る
  3451. *------------------------------------------
  3452. */
  3453. int pc_getzeny (struct map_session_data *sd, int zeny)
  3454. {
  3455. double z;
  3456. nullpo_retr (0, sd);
  3457. z = (double) sd->status.zeny;
  3458. if (z + (double) zeny > MAX_ZENY)
  3459. {
  3460. zeny = 0;
  3461. sd->status.zeny = MAX_ZENY;
  3462. }
  3463. sd->status.zeny += zeny;
  3464. clif_updatestatus (sd, SP_ZENY);
  3465. return 0;
  3466. }
  3467. /*==========================================
  3468. * アイテムを探して、インデックスを返す
  3469. *------------------------------------------
  3470. */
  3471. int pc_search_inventory (struct map_session_data *sd, int item_id)
  3472. {
  3473. int i;
  3474. nullpo_retr (-1, sd);
  3475. for (i = 0; i < MAX_INVENTORY; i++)
  3476. {
  3477. if (sd->status.inventory[i].nameid == item_id &&
  3478. (sd->status.inventory[i].amount > 0 || item_id == 0))
  3479. return i;
  3480. }
  3481. return -1;
  3482. }
  3483. int pc_count_all_items (struct map_session_data *player, int item_id)
  3484. {
  3485. int i;
  3486. int count = 0;
  3487. nullpo_retr (0, player);
  3488. for (i = 0; i < MAX_INVENTORY; i++)
  3489. {
  3490. if (player->status.inventory[i].nameid == item_id)
  3491. count += player->status.inventory[i].amount;
  3492. }
  3493. return count;
  3494. }
  3495. int pc_remove_items (struct map_session_data *player, int item_id, int count)
  3496. {
  3497. int i;
  3498. nullpo_retr (0, player);
  3499. for (i = 0; i < MAX_INVENTORY && count; i++)
  3500. {
  3501. if (player->status.inventory[i].nameid == item_id)
  3502. {
  3503. int to_delete = count;
  3504. /* only delete as much as we have */
  3505. if (to_delete > player->status.inventory[i].amount)
  3506. to_delete = player->status.inventory[i].amount;
  3507. count -= to_delete;
  3508. pc_delitem (player, i, to_delete,
  3509. 0 /* means `really delete and update status' */ );
  3510. if (!count || count < 0)
  3511. return 0;
  3512. }
  3513. }
  3514. return 0;
  3515. }
  3516. /*==========================================
  3517. * アイテム追加。個数のみitem構造体の数字を無視
  3518. *------------------------------------------
  3519. */
  3520. int pc_additem (struct map_session_data *sd, struct item *item_data,
  3521. int amount)
  3522. {
  3523. struct item_data *data;
  3524. int i, w;
  3525. nullpo_retr (1, sd);
  3526. nullpo_retr (1, item_data);
  3527. MAP_LOG_PC (sd, "PICKUP %d %d", item_data->nameid, amount);
  3528. if (item_data->nameid <= 0 || amount <= 0)
  3529. return 1;
  3530. data = itemdb_search (item_data->nameid);
  3531. if (!data)
  3532. return 1;
  3533. if ((w = data->weight * amount) + sd->weight > sd->max_weight)
  3534. return 2;
  3535. i = MAX_INVENTORY;
  3536. if (!itemdb_isequip2 (data))
  3537. {
  3538. // 装 備品ではないので、既所有品なら個数のみ変化させる
  3539. for (i = 0; i < MAX_INVENTORY; i++)
  3540. if (sd->status.inventory[i].nameid == item_data->nameid &&
  3541. sd->status.inventory[i].card[0] == item_data->card[0]
  3542. && sd->status.inventory[i].card[1] == item_data->card[1]
  3543. && sd->status.inventory[i].card[2] == item_data->card[2]
  3544. && sd->status.inventory[i].card[3] == item_data->card[3])
  3545. {
  3546. if (sd->status.inventory[i].amount + amount > MAX_AMOUNT)
  3547. return 5;
  3548. sd->status.inventory[i].amount += amount;
  3549. clif_additem (sd, i, amount, 0);
  3550. break;
  3551. }
  3552. }
  3553. if (i >= MAX_INVENTORY)
  3554. {
  3555. // 装 備品か未所有品だったので空き欄へ追加
  3556. i = pc_search_inventory (sd, 0);
  3557. if (i >= 0)
  3558. {
  3559. memcpy (&sd->status.inventory[i], item_data,
  3560. sizeof (sd->status.inventory[0]));
  3561. if (item_data->equip)
  3562. sd->status.inventory[i].equip = 0;
  3563. sd->status.inventory[i].amount = amount;
  3564. sd->inventory_data[i] = data;
  3565. clif_additem (sd, i, amount, 0);
  3566. }
  3567. else
  3568. return 4;
  3569. }
  3570. sd->weight += w;
  3571. clif_updatestatus (sd, SP_WEIGHT);
  3572. return 0;
  3573. }
  3574. /*==========================================
  3575. * アイテムを減らす
  3576. *------------------------------------------
  3577. */
  3578. int pc_delitem (struct map_session_data *sd, int n, int amount, int type)
  3579. {
  3580. nullpo_retr (1, sd);
  3581. if (n < 0 || n >= MAX_INVENTORY)
  3582. return 1;
  3583. if (amount <= 0)
  3584. return 1;
  3585. if (sd->trade_partner != 0)
  3586. trade_tradecancel (sd);
  3587. if (sd->status.inventory[n].nameid == 0 || amount <= 0
  3588. || sd->status.inventory[n].amount < amount
  3589. || sd->inventory_data[n] == NULL)
  3590. return 1;
  3591. sd->status.inventory[n].amount -= amount;
  3592. sd->weight -= sd->inventory_data[n]->weight * amount;
  3593. if (sd->status.inventory[n].amount <= 0)
  3594. {
  3595. if (sd->status.inventory[n].equip)
  3596. pc_unequipitem (sd, n, 0);
  3597. memset (&sd->status.inventory[n], 0,
  3598. sizeof (sd->status.inventory[0]));
  3599. sd->inventory_data[n] = NULL;
  3600. }
  3601. if (!(type & 1))
  3602. clif_delitem (sd, n, amount);
  3603. if (!(type & 2))
  3604. clif_updatestatus (sd, SP_WEIGHT);
  3605. return 0;
  3606. }
  3607. /*==========================================
  3608. * アイテムを落す
  3609. *------------------------------------------
  3610. */
  3611. int pc_dropitem (struct map_session_data *sd, int n, int amount)
  3612. {
  3613. nullpo_retr (1, sd);
  3614. if (sd->trade_partner != 0 || sd->npc_id != 0 || sd->state.storage_flag)
  3615. return 0; // no dropping while trading/npc/storage
  3616. if (n < 0 || n >= MAX_INVENTORY)
  3617. return 0;
  3618. if (amount <= 0)
  3619. return 0;
  3620. if (sd->status.inventory[n].nameid <= 0 ||
  3621. sd->status.inventory[n].amount < amount ||
  3622. sd->trade_partner != 0 || sd->status.inventory[n].amount <= 0 ||
  3623. (itemdb_attr (sd->status.inventory[n].nameid) & ITEM_ATTR_DONTDROP))
  3624. return 1;
  3625. pc_unequipinvyitem (sd, n, 0);
  3626. map_addflooritem (&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x,
  3627. sd->bl.y, NULL, NULL, NULL, 0);
  3628. pc_delitem (sd, n, amount, 0);
  3629. return 0;
  3630. }
  3631. /*==========================================
  3632. * アイテムを拾う
  3633. *------------------------------------------
  3634. */
  3635. static int can_pick_item_up_from (struct map_session_data *self, int other_id)
  3636. {
  3637. /* From ourselves or from no-one? */
  3638. if (!self || self->bl.id == other_id || !other_id)
  3639. return 1;
  3640. struct party *p = party_search (self->status.party_id);
  3641. struct map_session_data *other = map_id2sd (other_id);
  3642. /* Other no longer exists? */
  3643. if (!other)
  3644. return 1;
  3645. /* From our partner? */
  3646. if (self->status.partner_id == other->status.char_id)
  3647. return 1;
  3648. /* From a party member? */
  3649. if (self->status.party_id
  3650. && self->status.party_id == other->status.party_id
  3651. && p && p->item != 0)
  3652. return 1;
  3653. /* From someone who is far away? */
  3654. /* On another map? */
  3655. if (other->bl.m != self->bl.m)
  3656. return 1;
  3657. else
  3658. {
  3659. int distance_x = abs (other->bl.x - self->bl.x);
  3660. int distance_y = abs (other->bl.y - self->bl.y);
  3661. int distance = (distance_x > distance_y) ? distance_x : distance_y;
  3662. return distance > battle_config.drop_pickup_safety_zone;
  3663. }
  3664. }
  3665. int pc_takeitem (struct map_session_data *sd, struct flooritem_data *fitem)
  3666. {
  3667. unsigned int tick = gettick ();
  3668. int can_take;
  3669. nullpo_retr (0, sd);
  3670. nullpo_retr (0, fitem);
  3671. /* Sometimes the owners reported to us are buggy: */
  3672. if (fitem->first_get_id == fitem->third_get_id
  3673. || fitem->second_get_id == fitem->third_get_id)
  3674. fitem->third_get_id = 0;
  3675. if (fitem->first_get_id == fitem->second_get_id)
  3676. {
  3677. fitem->second_get_id = fitem->third_get_id;
  3678. fitem->third_get_id = 0;
  3679. }
  3680. can_take = can_pick_item_up_from (sd, fitem->first_get_id);
  3681. if (!can_take)
  3682. can_take = fitem->first_get_tick <= tick
  3683. && can_pick_item_up_from (sd, fitem->second_get_id);
  3684. if (!can_take)
  3685. can_take = fitem->second_get_tick <= tick
  3686. && can_pick_item_up_from (sd, fitem->third_get_id);
  3687. if (!can_take)
  3688. can_take = fitem->third_get_tick <= tick;
  3689. if (can_take)
  3690. {
  3691. /* Can pick up */
  3692. int flag;
  3693. if ((flag =
  3694. pc_additem (sd, &fitem->item_data, fitem->item_data.amount)))
  3695. // 重量overで取得失敗
  3696. clif_additem (sd, 0, 0, flag);
  3697. else
  3698. {
  3699. /* 取得成功 */
  3700. if (sd->attacktimer != -1)
  3701. pc_stopattack (sd);
  3702. clif_takeitem (&sd->bl, &fitem->bl);
  3703. map_clearflooritem (fitem->bl.id);
  3704. }
  3705. return 0;
  3706. }
  3707. /* Otherwise, we can't pick up */
  3708. clif_additem (sd, 0, 0, 6);
  3709. return 0;
  3710. }
  3711. int pc_isUseitem (struct map_session_data *sd, int n)
  3712. {
  3713. struct item_data *item;
  3714. int nameid;
  3715. nullpo_retr (0, sd);
  3716. if (n < 0 || n >= MAX_INVENTORY)
  3717. return 0;
  3718. item = sd->inventory_data[n];
  3719. nameid = sd->status.inventory[n].nameid;
  3720. if (item == NULL)
  3721. return 0;
  3722. if (itemdb_type (nameid) != 0 && itemdb_type (nameid) != 2)
  3723. return 0;
  3724. /*
  3725. if ((nameid == 605) && map[sd->bl.m].flag.gvg)
  3726. return 0;
  3727. if (nameid == 601
  3728. && (map[sd->bl.m].flag.noteleport || map[sd->bl.m].flag.gvg))
  3729. {
  3730. clif_skill_teleportmessage (sd, 0);
  3731. return 0;
  3732. }
  3733. if (nameid == 602 && map[sd->bl.m].flag.noreturn)
  3734. return 0;
  3735. if (nameid == 604
  3736. && (map[sd->bl.m].flag.nobranch || map[sd->bl.m].flag.gvg))
  3737. return 0;
  3738. */
  3739. if (item->sex != 2 && sd->status.sex != item->sex)
  3740. return 0;
  3741. if (item->elv > 0 && sd->status.base_level < item->elv)
  3742. return 0;
  3743. return 1;
  3744. }
  3745. /*==========================================
  3746. * アイテムを使う
  3747. *------------------------------------------
  3748. */
  3749. int pc_useitem (struct map_session_data *sd, int n)
  3750. {
  3751. nullpo_retr (1, sd);
  3752. if (n >= 0 && n < MAX_INVENTORY && sd->inventory_data[n])
  3753. {
  3754. const int amount = sd->status.inventory[n].amount;
  3755. if (sd->status.inventory[n].nameid <= 0
  3756. || amount <= 0
  3757. || sd->sc_data[SC_BERSERK].timer != -1 || !pc_isUseitem (sd, n))
  3758. {
  3759. clif_useitemack (sd, n, 0, 0);
  3760. return 1;
  3761. }
  3762. if (itemdb_attr (sd->status.inventory[n].nameid) && ITEM_ATTR_DONTUSE)
  3763. return 0;
  3764. run_script (sd->inventory_data[n]->use_script, 0, sd->bl.id, 0);
  3765. if (itemdb_type (sd->status.inventory[n].nameid) != 2 &&
  3766. !(itemdb_attr (sd->status.inventory[n].nameid) && ITEM_ATTR_DONTREMOVE))
  3767. {
  3768. clif_useitemack (sd, n, amount - 1, 1);
  3769. pc_delitem (sd, n, 1, 1);
  3770. }
  3771. }
  3772. return 0;
  3773. }
  3774. /*==========================================
  3775. * カートアイテム追加。個数のみitem構造体の数字を無視
  3776. *------------------------------------------
  3777. */
  3778. int pc_cart_additem (struct map_session_data *sd, struct item *item_data,
  3779. int amount)
  3780. {
  3781. struct item_data *data;
  3782. int i, w;
  3783. nullpo_retr (1, sd);
  3784. nullpo_retr (1, item_data);
  3785. if (item_data->nameid <= 0 || amount <= 0)
  3786. return 1;
  3787. data = itemdb_search (item_data->nameid);
  3788. if ((w = data->weight * amount) + sd->cart_weight > sd->cart_max_weight)
  3789. return 1;
  3790. i = MAX_CART;
  3791. if (!itemdb_isequip2 (data))
  3792. {
  3793. // 装 備品ではないので、既所有品なら個数のみ変化させる
  3794. for (i = 0; i < MAX_CART; i++)
  3795. {
  3796. if (sd->status.cart[i].nameid == item_data->nameid &&
  3797. sd->status.cart[i].card[0] == item_data->card[0]
  3798. && sd->status.cart[i].card[1] == item_data->card[1]
  3799. && sd->status.cart[i].card[2] == item_data->card[2]
  3800. && sd->status.cart[i].card[3] == item_data->card[3])
  3801. {
  3802. if (sd->status.cart[i].amount + amount > MAX_AMOUNT)
  3803. return 1;
  3804. sd->status.cart[i].amount += amount;
  3805. clif_cart_additem (sd, i, amount, 0);
  3806. break;
  3807. }
  3808. }
  3809. }
  3810. if (i >= MAX_CART)
  3811. {
  3812. // 装 備品か未所有品だったので空き欄へ追加
  3813. for (i = 0; i < MAX_CART; i++)
  3814. {
  3815. if (sd->status.cart[i].nameid == 0)
  3816. {
  3817. memcpy (&sd->status.cart[i], item_data,
  3818. sizeof (sd->status.cart[0]));
  3819. sd->status.cart[i].amount = amount;
  3820. sd->cart_num++;
  3821. clif_cart_additem (sd, i, amount, 0);
  3822. break;
  3823. }
  3824. }
  3825. if (i >= MAX_CART)
  3826. return 1;
  3827. }
  3828. sd->cart_weight += w;
  3829. clif_updatestatus (sd, SP_CARTINFO);
  3830. return 0;
  3831. }
  3832. /*==========================================
  3833. * カートアイテムを減らす
  3834. *------------------------------------------
  3835. */
  3836. int pc_cart_delitem (struct map_session_data *sd, int n, int amount, int type)
  3837. {
  3838. nullpo_retr (1, sd);
  3839. if (n < 0 || n >= MAX_CART || amount <= 0)
  3840. return 1;
  3841. if (!pc_iscarton (sd))
  3842. return 1;
  3843. if (sd->status.cart[n].nameid == 0 || sd->status.cart[n].amount < amount)
  3844. return 1;
  3845. sd->status.cart[n].amount -= amount;
  3846. sd->cart_weight -= itemdb_weight (sd->status.cart[n].nameid) * amount;
  3847. if (sd->status.cart[n].amount <= 0)
  3848. {
  3849. memset (&sd->status.cart[n], 0, sizeof (sd->status.cart[0]));
  3850. sd->cart_num--;
  3851. }
  3852. if (!type)
  3853. {
  3854. clif_cart_delitem (sd, n, amount);
  3855. clif_updatestatus (sd, SP_CARTINFO);
  3856. }
  3857. return 0;
  3858. }
  3859. /*==========================================
  3860. * カートへアイテム移動
  3861. *------------------------------------------
  3862. */
  3863. int pc_putitemtocart (struct map_session_data *sd, int idx, int amount)
  3864. {
  3865. struct item *item_data;
  3866. nullpo_retr (0, sd);
  3867. if (idx < 0 || idx >= MAX_INVENTORY)
  3868. return 1;
  3869. nullpo_retr (0, item_data = &sd->status.inventory[idx]);
  3870. if (!pc_iscarton (sd))
  3871. return 1;
  3872. if (item_data->nameid == 0 || item_data->amount < amount)
  3873. return 1;
  3874. if (itemdb_attr (sd->status.inventory[idx].nameid) & ITEM_ATTR_DONTMOVETOCART)
  3875. return 1;
  3876. if (pc_cart_additem (sd, item_data, amount) == 0)
  3877. return pc_delitem (sd, idx, amount, 0);
  3878. return 1;
  3879. }
  3880. /*==========================================
  3881. * カート内のアイテム数確認(個数の差分を返す)
  3882. *------------------------------------------
  3883. */
  3884. int pc_cartitem_amount (struct map_session_data *sd, int idx, int amount)
  3885. {
  3886. struct item *item_data;
  3887. nullpo_retr (-1, sd);
  3888. if (idx < 0 || idx >= MAX_CART)
  3889. return -1;
  3890. nullpo_retr (-1, item_data = &sd->status.cart[idx]);
  3891. if (!pc_iscarton (sd))
  3892. return -1;
  3893. if (item_data->nameid == 0 || !item_data->amount)
  3894. return -1;
  3895. return item_data->amount - amount;
  3896. }
  3897. /*==========================================
  3898. * カートからアイテム移動
  3899. *------------------------------------------
  3900. */
  3901. int pc_getitemfromcart (struct map_session_data *sd, int idx, int amount)
  3902. {
  3903. struct item *item_data;
  3904. int flag;
  3905. nullpo_retr (0, sd);
  3906. if (idx < 0 || idx >= MAX_CART)
  3907. return 1;
  3908. nullpo_retr (0, item_data = &sd->status.cart[idx]);
  3909. if (!pc_iscarton (sd))
  3910. return 1;
  3911. if (item_data->nameid == 0 || item_data->amount < amount)
  3912. return 1;
  3913. if ((flag = pc_additem (sd, item_data, amount)) == 0)
  3914. return pc_cart_delitem (sd, idx, amount, 0);
  3915. clif_additem (sd, 0, 0, flag);
  3916. return 1;
  3917. }
  3918. /*==========================================
  3919. * アイテム鑑定
  3920. *------------------------------------------
  3921. */
  3922. int pc_item_identify (struct map_session_data *sd, int idx)
  3923. {
  3924. int flag = 1;
  3925. nullpo_retr (0, sd);
  3926. if (idx >= 0 && idx < MAX_INVENTORY)
  3927. {
  3928. if (sd->status.inventory[idx].nameid > 0
  3929. && sd->status.inventory[idx].identify == 0)
  3930. {
  3931. flag = 0;
  3932. sd->status.inventory[idx].identify = 1;
  3933. }
  3934. clif_item_identified (sd, idx, flag);
  3935. }
  3936. else
  3937. clif_item_identified (sd, idx, flag);
  3938. return !flag;
  3939. }
  3940. /*==========================================
  3941. * スティル品公開
  3942. *------------------------------------------
  3943. */
  3944. int pc_show_steal (struct block_list *bl, va_list ap)
  3945. {
  3946. struct map_session_data *sd;
  3947. int itemid;
  3948. int type;
  3949. struct item_data *item = NULL;
  3950. char output[100];
  3951. nullpo_retr (0, bl);
  3952. nullpo_retr (0, ap);
  3953. nullpo_retr (0, sd = va_arg (ap, struct map_session_data *));
  3954. itemid = va_arg (ap, int);
  3955. type = va_arg (ap, int);
  3956. if (!type)
  3957. {
  3958. if ((item = itemdb_exists (itemid)) == NULL)
  3959. sprintf (output, "%s stole an Unknown_Item.", sd->status.name);
  3960. else
  3961. sprintf (output, "%s stole %s.", sd->status.name, item->jname);
  3962. clif_displaymessage (((struct map_session_data *) bl)->fd, output);
  3963. }
  3964. else
  3965. {
  3966. sprintf (output,
  3967. "%s has not stolen the item because of being overweight.",
  3968. sd->status.name);
  3969. clif_displaymessage (((struct map_session_data *) bl)->fd, output);
  3970. }
  3971. return 0;
  3972. }
  3973. /*==========================================
  3974. *
  3975. *------------------------------------------
  3976. */
  3977. //** pc.c: Small Steal Item fix by fritz
  3978. int pc_steal_item (struct map_session_data *sd, struct block_list *bl)
  3979. {
  3980. if (sd != NULL && bl != NULL && bl->type == BL_MOB)
  3981. {
  3982. struct mob_data *md;
  3983. md = (struct mob_data *) bl;
  3984. if (!md->state.steal_flag && mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode & 0x20) && md->sc_data[SC_STONE].timer == -1 && md->sc_data[SC_FREEZE].timer == -1 && (!(md->class > 1324 && md->class < 1364))) // prevent stealing from treasure boxes [Valaris]
  3985. {
  3986. int skill;
  3987. skill =
  3988. sd->paramc[4] - mob_db[md->class].dex + pc_checkskill (sd,
  3989. TF_STEAL)
  3990. + 10;
  3991. if (0 < skill)
  3992. {
  3993. int i, rate, itemid, flag, count;
  3994. for (count = 8; count <= 8 && count != 0; count--)
  3995. {
  3996. i = rand () % 8;
  3997. itemid = mob_db[md->class].dropitem[i].nameid;
  3998. if (itemid > 0 && itemdb_type (itemid) != 6)
  3999. {
  4000. if (!battle_config.item_rate_common)
  4001. {
  4002. rate =
  4003. (mob_db[md->class].dropitem[i].p /
  4004. battle_config.item_rate_common * 100 * skill) /
  4005. 100;
  4006. }
  4007. else
  4008. {
  4009. rate =
  4010. (mob_db[md->class].dropitem[i].p /
  4011. 1 * 100 * skill) / 100;
  4012. }
  4013. if (rand () % 10000 < rate)
  4014. {
  4015. struct item tmp_item;
  4016. memset (&tmp_item, 0, sizeof (tmp_item));
  4017. tmp_item.nameid = itemid;
  4018. tmp_item.amount = 1;
  4019. tmp_item.identify = 1;
  4020. flag = pc_additem (sd, &tmp_item, 1);
  4021. if (battle_config.show_steal_in_same_party)
  4022. {
  4023. party_foreachsamemap (pc_show_steal, sd, 1,
  4024. sd, tmp_item.nameid, 0);
  4025. }
  4026. if (flag)
  4027. {
  4028. if (battle_config.show_steal_in_same_party)
  4029. {
  4030. party_foreachsamemap (pc_show_steal, sd,
  4031. 1, sd,
  4032. tmp_item.nameid, 1);
  4033. }
  4034. clif_additem (sd, 0, 0, flag);
  4035. }
  4036. md->state.steal_flag = 1;
  4037. return 1;
  4038. }
  4039. }
  4040. }
  4041. }
  4042. }
  4043. }
  4044. return 0;
  4045. }
  4046. /*==========================================
  4047. *
  4048. *------------------------------------------
  4049. */
  4050. int pc_steal_coin (struct map_session_data *sd, struct block_list *bl)
  4051. {
  4052. if (sd != NULL && bl != NULL && bl->type == BL_MOB)
  4053. {
  4054. struct mob_data *md = (struct mob_data *) bl;
  4055. if (md && !md->state.steal_coin_flag && md->sc_data
  4056. && md->sc_data[SC_STONE].timer == -1
  4057. && md->sc_data[SC_FREEZE].timer == -1)
  4058. {
  4059. int rate, skill;
  4060. skill = pc_checkskill (sd, RG_STEALCOIN) * 10;
  4061. rate =
  4062. skill + (sd->status.base_level - mob_db[md->class].lv) * 3 +
  4063. sd->paramc[4] * 2 + sd->paramc[5] * 2;
  4064. if (MRAND (1000) < rate)
  4065. {
  4066. pc_getzeny (sd, mob_db[md->class].lv * 10 + MRAND (100));
  4067. md->state.steal_coin_flag = 1;
  4068. return 1;
  4069. }
  4070. }
  4071. }
  4072. return 0;
  4073. }
  4074. //
  4075. //
  4076. //
  4077. /*==========================================
  4078. * PCの位置設定
  4079. *------------------------------------------
  4080. */
  4081. int pc_setpos (struct map_session_data *sd, char *mapname_org, int x, int y,
  4082. int clrtype)
  4083. {
  4084. char mapname[24];
  4085. int m = 0, c = 0, disguise = 0;
  4086. nullpo_retr (0, sd);
  4087. nullpo_retr (0, mapname_org);
  4088. if (sd->chatID) // チャットから出る
  4089. chat_leavechat (sd);
  4090. if (sd->trade_partner) // 取引を中断する
  4091. trade_tradecancel (sd);
  4092. if (sd->state.storage_flag == 1)
  4093. storage_storage_quit (sd); // 倉庫を開いてるなら保存する
  4094. else if (sd->state.storage_flag == 2)
  4095. storage_guild_storage_quit (sd, 0);
  4096. if (sd->party_invite > 0) // パーティ勧誘を拒否する
  4097. party_reply_invite (sd, sd->party_invite_account, 0);
  4098. if (sd->guild_invite > 0) // ギルド勧誘を拒否する
  4099. guild_reply_invite (sd, sd->guild_invite, 0);
  4100. if (sd->guild_alliance > 0) // ギルド同盟勧誘を拒否する
  4101. guild_reply_reqalliance (sd, sd->guild_alliance_account, 0);
  4102. skill_castcancel (&sd->bl, 0); // 詠唱中断
  4103. pc_stop_walking (sd, 0); // 歩行中断
  4104. pc_stopattack (sd); // 攻撃中断
  4105. if (pc_issit (sd))
  4106. {
  4107. // pc_setstand (sd); // [fate] Nothing wrong with warping while sitting
  4108. skill_gangsterparadise (sd, 0);
  4109. }
  4110. if (sd->sc_data[SC_TRICKDEAD].timer != -1)
  4111. skill_status_change_end (&sd->bl, SC_TRICKDEAD, -1);
  4112. if (sd->status.option & 2)
  4113. skill_status_change_end (&sd->bl, SC_HIDING, -1);
  4114. if (sd->status.option & 4)
  4115. skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
  4116. if (sd->status.option & 16386)
  4117. skill_status_change_end (&sd->bl, SC_CHASEWALK, -1);
  4118. if (sd->sc_data[SC_BLADESTOP].timer != -1)
  4119. skill_status_change_end (&sd->bl, SC_BLADESTOP, -1);
  4120. if (sd->sc_data[SC_DANCING].timer != -1) // clear dance effect when warping [Valaris]
  4121. skill_stop_dancing (&sd->bl, 0);
  4122. if (sd->disguise)
  4123. { // clear disguises when warping [Valaris]
  4124. clif_clearchar (&sd->bl, 9);
  4125. disguise = sd->disguise;
  4126. sd->disguise = 0;
  4127. }
  4128. memcpy (mapname, mapname_org, 16);
  4129. mapname[16] = 0;
  4130. if (strstr (mapname, ".gat") == NULL && strlen (mapname) < 16)
  4131. {
  4132. strcat (mapname, ".gat");
  4133. }
  4134. m = map_mapname2mapid (mapname);
  4135. if (m < 0)
  4136. {
  4137. if (sd->mapname[0])
  4138. {
  4139. int ip, port;
  4140. if (map_mapname2ipport (mapname, &ip, &port) == 0)
  4141. {
  4142. skill_stop_dancing (&sd->bl, 1);
  4143. skill_unit_out_all (&sd->bl, gettick (), 1);
  4144. clif_clearchar_area (&sd->bl, clrtype & 0xffff);
  4145. skill_gangsterparadise (sd, 0);
  4146. map_delblock (&sd->bl);
  4147. memcpy (sd->mapname, mapname, 24);
  4148. sd->bl.x = x;
  4149. sd->bl.y = y;
  4150. sd->state.waitingdisconnect = 1;
  4151. pc_makesavestatus (sd);
  4152. //The storage close routines save the char data. [Skotlex]
  4153. if (!sd->state.storage_flag)
  4154. chrif_save (sd);
  4155. else if (sd->state.storage_flag == 1)
  4156. storage_storage_quit (sd);
  4157. else if (sd->state.storage_flag == 2)
  4158. storage_guild_storage_quit (sd, 1);
  4159. chrif_changemapserver (sd, mapname, x, y, ip, port);
  4160. return 0;
  4161. }
  4162. }
  4163. #if 0
  4164. clif_authfail_fd (sd->fd, 0); // cancel
  4165. clif_setwaitclose (sd->fd);
  4166. #endif
  4167. return 1;
  4168. }
  4169. if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys)
  4170. x = y = 0;
  4171. if ((x == 0 && y == 0) || (c = read_gat (m, x, y)) == 1 || c == 5)
  4172. {
  4173. if (x || y)
  4174. {
  4175. if (battle_config.error_log)
  4176. printf ("stacked (%d,%d)\n", x, y);
  4177. }
  4178. do
  4179. {
  4180. x = MRAND (map[m].xs - 2) + 1;
  4181. y = MRAND (map[m].ys - 2) + 1;
  4182. }
  4183. while ((c = read_gat (m, x, y)) == 1 || c == 5);
  4184. }
  4185. if (sd->mapname[0] && sd->bl.prev != NULL)
  4186. {
  4187. skill_unit_out_all (&sd->bl, gettick (), 1);
  4188. clif_clearchar_area (&sd->bl, clrtype & 0xffff);
  4189. skill_gangsterparadise (sd, 0);
  4190. map_delblock (&sd->bl);
  4191. clif_changemap (sd, map[m].name, x, y); // [MouseJstr]
  4192. }
  4193. if (disguise) // disguise teleport fix [Valaris]
  4194. sd->disguise = disguise;
  4195. memcpy (sd->mapname, mapname, 24);
  4196. sd->bl.m = m;
  4197. sd->to_x = x;
  4198. sd->to_y = y;
  4199. // moved and changed dance effect stopping
  4200. sd->bl.x = x;
  4201. sd->bl.y = y;
  4202. // map_addblock(&sd->bl); /// ブロック登録とspawnは
  4203. // clif_spawnpc(sd);
  4204. return 0;
  4205. }
  4206. /*==========================================
  4207. * PCのランダムワープ
  4208. *------------------------------------------
  4209. */
  4210. int pc_randomwarp (struct map_session_data *sd, int type)
  4211. {
  4212. int x, y, c, i = 0;
  4213. int m;
  4214. nullpo_retr (0, sd);
  4215. m = sd->bl.m;
  4216. if (map[sd->bl.m].flag.noteleport) // テレポート禁止
  4217. return 0;
  4218. do
  4219. {
  4220. x = MRAND (map[m].xs - 2) + 1;
  4221. y = MRAND (map[m].ys - 2) + 1;
  4222. }
  4223. while (((c = read_gat (m, x, y)) == 1 || c == 5) && (i++) < 1000);
  4224. if (i < 1000)
  4225. pc_setpos (sd, map[m].name, x, y, type);
  4226. return 0;
  4227. }
  4228. /*==========================================
  4229. * 現在位置のメモ
  4230. *------------------------------------------
  4231. */
  4232. int pc_memo (struct map_session_data *sd, int i)
  4233. {
  4234. int skill;
  4235. int j;
  4236. nullpo_retr (0, sd);
  4237. skill = pc_checkskill (sd, AL_WARP);
  4238. if (i >= MIN_PORTAL_MEMO)
  4239. i -= MIN_PORTAL_MEMO;
  4240. else if (map[sd->bl.m].flag.nomemo
  4241. || (map[sd->bl.m].flag.nowarpto
  4242. && battle_config.any_warp_GM_min_level > pc_isGM (sd)))
  4243. {
  4244. clif_skill_teleportmessage (sd, 1);
  4245. return 0;
  4246. }
  4247. if (skill < 1)
  4248. {
  4249. clif_skill_memo (sd, 2);
  4250. }
  4251. if (skill < 2 || i < -1 || i > 2)
  4252. {
  4253. clif_skill_memo (sd, 1);
  4254. return 0;
  4255. }
  4256. for (j = 0; j < 3; j++)
  4257. {
  4258. if (strcmp (sd->status.memo_point[j].map, map[sd->bl.m].name) == 0)
  4259. {
  4260. i = j;
  4261. break;
  4262. }
  4263. }
  4264. if (i == -1)
  4265. {
  4266. for (i = skill - 3; i >= 0; i--)
  4267. {
  4268. memcpy (&sd->status.memo_point[i + 1], &sd->status.memo_point[i],
  4269. sizeof (struct point));
  4270. }
  4271. i = 0;
  4272. }
  4273. memcpy (sd->status.memo_point[i].map, map[sd->bl.m].name, 24);
  4274. sd->status.memo_point[i].x = sd->bl.x;
  4275. sd->status.memo_point[i].y = sd->bl.y;
  4276. clif_skill_memo (sd, 0);
  4277. return 1;
  4278. }
  4279. /*==========================================
  4280. *
  4281. *------------------------------------------
  4282. */
  4283. int pc_can_reach (struct map_session_data *sd, int x, int y)
  4284. {
  4285. struct walkpath_data wpd;
  4286. nullpo_retr (0, sd);
  4287. if (sd->bl.x == x && sd->bl.y == y) // 同じマス
  4288. return 1;
  4289. // 障害物判定
  4290. wpd.path_len = 0;
  4291. wpd.path_pos = 0;
  4292. wpd.path_half = 0;
  4293. return (path_search (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, x, y, 0) !=
  4294. -1) ? 1 : 0;
  4295. }
  4296. //
  4297. // 歩 行物
  4298. //
  4299. /*==========================================
  4300. * 次の1歩にかかる時間を計算
  4301. *------------------------------------------
  4302. */
  4303. static int calc_next_walk_step (struct map_session_data *sd)
  4304. {
  4305. nullpo_retr (0, sd);
  4306. if (sd->walkpath.path_pos >= sd->walkpath.path_len)
  4307. return -1;
  4308. if (sd->walkpath.path[sd->walkpath.path_pos] & 1)
  4309. return sd->speed * 14 / 10;
  4310. return sd->speed;
  4311. }
  4312. /*==========================================
  4313. * 半歩進む(timer関数)
  4314. *------------------------------------------
  4315. */
  4316. static int pc_walk (int tid, unsigned int tick, int id, int data)
  4317. {
  4318. struct map_session_data *sd;
  4319. int i;
  4320. sd = map_id2sd (id);
  4321. if (sd == NULL)
  4322. return 0;
  4323. if (sd->walktimer != tid)
  4324. {
  4325. if (battle_config.error_log)
  4326. printf ("pc_walk %d != %d\n", sd->walktimer, tid);
  4327. return 0;
  4328. }
  4329. sd->walktimer = -1;
  4330. if (sd->walkpath.path_pos >= sd->walkpath.path_len
  4331. || sd->walkpath.path_pos != data)
  4332. return 0;
  4333. //歩いたので息吹のタイマーを初期化
  4334. sd->inchealspirithptick = 0;
  4335. sd->inchealspiritsptick = 0;
  4336. sd->walkpath.path_half ^= 1;
  4337. if (sd->walkpath.path_half == 0)
  4338. { // マス目中心へ到着
  4339. sd->walkpath.path_pos++;
  4340. if (sd->state.change_walk_target)
  4341. {
  4342. pc_walktoxy_sub (sd);
  4343. return 0;
  4344. }
  4345. }
  4346. else
  4347. { // マス目境界へ到着
  4348. int ctype;
  4349. int moveblock;
  4350. int x, y, dx, dy;
  4351. if (sd->walkpath.path[sd->walkpath.path_pos] >= 8)
  4352. return 1;
  4353. x = sd->bl.x;
  4354. y = sd->bl.y;
  4355. ctype = map_getcell (sd->bl.m, x, y);
  4356. if (ctype == 1 || ctype == 5)
  4357. {
  4358. pc_stop_walking (sd, 1);
  4359. return 0;
  4360. }
  4361. sd->dir = sd->head_dir = sd->walkpath.path[sd->walkpath.path_pos];
  4362. dx = dirx[(int) sd->dir];
  4363. dy = diry[(int) sd->dir];
  4364. ctype = map_getcell (sd->bl.m, x + dx, y + dy);
  4365. if (ctype == 1 || ctype == 5)
  4366. {
  4367. pc_walktoxy_sub (sd);
  4368. return 0;
  4369. }
  4370. moveblock = (x / BLOCK_SIZE != (x + dx) / BLOCK_SIZE
  4371. || y / BLOCK_SIZE != (y + dy) / BLOCK_SIZE);
  4372. sd->walktimer = 1;
  4373. map_foreachinmovearea (clif_pcoutsight, sd->bl.m, x - AREA_SIZE,
  4374. y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
  4375. dx, dy, 0, sd);
  4376. x += dx;
  4377. y += dy;
  4378. if (moveblock)
  4379. map_delblock (&sd->bl);
  4380. sd->bl.x = x;
  4381. sd->bl.y = y;
  4382. if (moveblock)
  4383. map_addblock (&sd->bl);
  4384. if (sd->sc_data[SC_DANCING].timer != -1)
  4385. skill_unit_move_unit_group ((struct skill_unit_group *)
  4386. sd->sc_data[SC_DANCING].val2,
  4387. sd->bl.m, dx, dy);
  4388. map_foreachinmovearea (clif_pcinsight, sd->bl.m, x - AREA_SIZE,
  4389. y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
  4390. -dx, -dy, 0, sd);
  4391. sd->walktimer = -1;
  4392. if (sd->status.party_id > 0)
  4393. { // パーティのHP情報通知検査
  4394. struct party *p = party_search (sd->status.party_id);
  4395. if (p != NULL)
  4396. {
  4397. int p_flag = 0;
  4398. map_foreachinmovearea (party_send_hp_check, sd->bl.m,
  4399. x - AREA_SIZE, y - AREA_SIZE,
  4400. x + AREA_SIZE, y + AREA_SIZE, -dx, -dy,
  4401. BL_PC, sd->status.party_id, &p_flag);
  4402. if (p_flag)
  4403. sd->party_hp = -1;
  4404. }
  4405. }
  4406. if (sd->status.option & 4) // クローキングの消滅検査
  4407. skill_check_cloaking (&sd->bl);
  4408. /* ディボーション検査 */
  4409. for (i = 0; i < 5; i++)
  4410. if (sd->dev.val1[i])
  4411. {
  4412. skill_devotion3 (&sd->bl, sd->dev.val1[i]);
  4413. break;
  4414. }
  4415. /* 被ディボーション検査 */
  4416. if (sd->sc_data && sd->sc_data[SC_DEVOTION].val1)
  4417. {
  4418. skill_devotion2 (&sd->bl, sd->sc_data[SC_DEVOTION].val1);
  4419. }
  4420. skill_unit_move (&sd->bl, tick, 1); // スキルユニットの検査
  4421. if (map_getcell (sd->bl.m, x, y) & 0x80)
  4422. npc_touch_areanpc (sd, sd->bl.m, x, y);
  4423. else
  4424. npc_untouch_areanpc(sd);
  4425. }
  4426. if ((i = calc_next_walk_step (sd)) > 0)
  4427. {
  4428. i = i >> 1;
  4429. if (i < 1 && sd->walkpath.path_half == 0)
  4430. i = 1;
  4431. sd->walktimer =
  4432. add_timer (tick + i, pc_walk, id, sd->walkpath.path_pos);
  4433. }
  4434. return 0;
  4435. }
  4436. /*==========================================
  4437. * 移動可能か確認して、可能なら歩行開始
  4438. *------------------------------------------
  4439. */
  4440. static int pc_walktoxy_sub (struct map_session_data *sd)
  4441. {
  4442. struct walkpath_data wpd;
  4443. int i;
  4444. nullpo_retr (1, sd);
  4445. if (path_search
  4446. (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, sd->to_x, sd->to_y, 0))
  4447. return 1;
  4448. memcpy (&sd->walkpath, &wpd, sizeof (wpd));
  4449. clif_walkok (sd);
  4450. sd->state.change_walk_target = 0;
  4451. if ((i = calc_next_walk_step (sd)) > 0)
  4452. {
  4453. i = i >> 2;
  4454. sd->walktimer = add_timer (gettick () + i, pc_walk, sd->bl.id, 0);
  4455. }
  4456. clif_movechar (sd);
  4457. return 0;
  4458. }
  4459. /*==========================================
  4460. * pc歩 行要求
  4461. *------------------------------------------
  4462. */
  4463. int pc_walktoxy (struct map_session_data *sd, int x, int y)
  4464. {
  4465. nullpo_retr (0, sd);
  4466. sd->to_x = x;
  4467. sd->to_y = y;
  4468. if (pc_issit (sd))
  4469. pc_setstand (sd);
  4470. if (sd->walktimer != -1 && sd->state.change_walk_target == 0)
  4471. {
  4472. // 現在歩いている最中の目的地変更なのでマス目の中心に来た時に
  4473. // timer関数からpc_walktoxy_subを呼ぶようにする
  4474. sd->state.change_walk_target = 1;
  4475. }
  4476. else
  4477. {
  4478. pc_walktoxy_sub (sd);
  4479. }
  4480. return 0;
  4481. }
  4482. /*==========================================
  4483. * 歩 行停止
  4484. *------------------------------------------
  4485. */
  4486. int pc_stop_walking (struct map_session_data *sd, int type)
  4487. {
  4488. nullpo_retr (0, sd);
  4489. if (sd->walktimer != -1)
  4490. {
  4491. delete_timer (sd->walktimer, pc_walk);
  4492. sd->walktimer = -1;
  4493. }
  4494. sd->walkpath.path_len = 0;
  4495. sd->to_x = sd->bl.x;
  4496. sd->to_y = sd->bl.y;
  4497. if (type & 0x01)
  4498. clif_fixpos (&sd->bl);
  4499. if (type & 0x02 && battle_config.pc_damage_delay)
  4500. {
  4501. unsigned int tick = gettick ();
  4502. int delay = battle_get_dmotion (&sd->bl);
  4503. if (sd->canmove_tick < tick)
  4504. sd->canmove_tick = tick + delay;
  4505. }
  4506. return 0;
  4507. }
  4508. void pc_touch_all_relevant_npcs (struct map_session_data *sd)
  4509. {
  4510. if (!sd)
  4511. return;
  4512. if (map_getcell (sd->bl.m, sd->bl.x, sd->bl.y) & 0x80)
  4513. npc_touch_areanpc (sd, sd->bl.m, sd->bl.x, sd->bl.y);
  4514. else
  4515. npc_untouch_areanpc(sd);
  4516. }
  4517. /*==========================================
  4518. *
  4519. *------------------------------------------
  4520. */
  4521. int pc_movepos (struct map_session_data *sd, int dst_x, int dst_y)
  4522. {
  4523. int moveblock;
  4524. int dx, dy, dist;
  4525. struct walkpath_data wpd;
  4526. nullpo_retr (0, sd);
  4527. if (path_search (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, dst_x, dst_y, 0))
  4528. return 1;
  4529. sd->dir = sd->head_dir = map_calc_dir (&sd->bl, dst_x, dst_y);
  4530. dx = dst_x - sd->bl.x;
  4531. dy = dst_y - sd->bl.y;
  4532. dist = distance (sd->bl.x, sd->bl.y, dst_x, dst_y);
  4533. moveblock = (sd->bl.x / BLOCK_SIZE != dst_x / BLOCK_SIZE
  4534. || sd->bl.y / BLOCK_SIZE != dst_y / BLOCK_SIZE);
  4535. map_foreachinmovearea (clif_pcoutsight, sd->bl.m, sd->bl.x - AREA_SIZE,
  4536. sd->bl.y - AREA_SIZE, sd->bl.x + AREA_SIZE,
  4537. sd->bl.y + AREA_SIZE, dx, dy, 0, sd);
  4538. if (moveblock)
  4539. map_delblock (&sd->bl);
  4540. sd->bl.x = dst_x;
  4541. sd->bl.y = dst_y;
  4542. if (moveblock)
  4543. map_addblock (&sd->bl);
  4544. map_foreachinmovearea (clif_pcinsight, sd->bl.m, sd->bl.x - AREA_SIZE,
  4545. sd->bl.y - AREA_SIZE, sd->bl.x + AREA_SIZE,
  4546. sd->bl.y + AREA_SIZE, -dx, -dy, 0, sd);
  4547. if (sd->status.party_id > 0)
  4548. { // パーティのHP情報通知検査
  4549. struct party *p = party_search (sd->status.party_id);
  4550. if (p != NULL)
  4551. {
  4552. int flag = 0;
  4553. map_foreachinmovearea (party_send_hp_check, sd->bl.m,
  4554. sd->bl.x - AREA_SIZE, sd->bl.y - AREA_SIZE,
  4555. sd->bl.x + AREA_SIZE, sd->bl.y + AREA_SIZE,
  4556. -dx, -dy, BL_PC, sd->status.party_id,
  4557. &flag);
  4558. if (flag)
  4559. sd->party_hp = -1;
  4560. }
  4561. }
  4562. if (sd->status.option & 4) // クローキングの消滅検査
  4563. skill_check_cloaking (&sd->bl);
  4564. skill_unit_move (&sd->bl, gettick (), dist + 7); // スキルユニットの検査
  4565. pc_touch_all_relevant_npcs (sd);
  4566. return 0;
  4567. }
  4568. //
  4569. // 武器戦闘
  4570. //
  4571. /*==========================================
  4572. * スキルの検索 所有していた場合Lvが返る
  4573. *------------------------------------------
  4574. */
  4575. int pc_checkskill (struct map_session_data *sd, int skill_id)
  4576. {
  4577. if (sd == NULL)
  4578. return 0;
  4579. if (skill_id >= 10000)
  4580. {
  4581. struct guild *g;
  4582. if (sd->status.guild_id > 0
  4583. && (g = guild_search (sd->status.guild_id)) != NULL)
  4584. return guild_checkskill (g, skill_id);
  4585. return 0;
  4586. }
  4587. if (skill_id < 0 || skill_id >= MAX_SKILL)
  4588. return 0;
  4589. if (sd->status.skill[skill_id].id == skill_id)
  4590. return (sd->status.skill[skill_id].lv);
  4591. return 0;
  4592. }
  4593. /*==========================================
  4594. * 武器変更によるスキルの継続チェック
  4595. * 引数:
  4596. * struct map_session_data *sd セッションデータ
  4597. * int nameid 装備品ID
  4598. * 返り値:
  4599. * 0 変更なし
  4600. * -1 スキルを解除
  4601. *------------------------------------------
  4602. */
  4603. int pc_checkallowskill (struct map_session_data *sd)
  4604. {
  4605. nullpo_retr (0, sd);
  4606. if (sd->sc_data == NULL)
  4607. return 0;
  4608. if (!(skill_get_weapontype (KN_TWOHANDQUICKEN) & (1 << sd->status.weapon))
  4609. && sd->sc_data[SC_TWOHANDQUICKEN].timer != -1)
  4610. { // 2HQ
  4611. skill_status_change_end (&sd->bl, SC_TWOHANDQUICKEN, -1); // 2HQを解除
  4612. return -1;
  4613. }
  4614. if (!(skill_get_weapontype (LK_AURABLADE) & (1 << sd->status.weapon))
  4615. && sd->sc_data[SC_AURABLADE].timer != -1)
  4616. { /* オーラブレード */
  4617. skill_status_change_end (&sd->bl, SC_AURABLADE, -1); /* オーラブレードを解除 */
  4618. return -1;
  4619. }
  4620. if (!(skill_get_weapontype (LK_PARRYING) & (1 << sd->status.weapon))
  4621. && sd->sc_data[SC_PARRYING].timer != -1)
  4622. { /* パリイング */
  4623. skill_status_change_end (&sd->bl, SC_PARRYING, -1); /* パリイングを解除 */
  4624. return -1;
  4625. }
  4626. if (!(skill_get_weapontype (LK_CONCENTRATION) & (1 << sd->status.weapon))
  4627. && sd->sc_data[SC_CONCENTRATION].timer != -1)
  4628. { /* コンセントレーション */
  4629. skill_status_change_end (&sd->bl, SC_CONCENTRATION, -1); /* コンセントレーションを解除 */
  4630. return -1;
  4631. }
  4632. if (!(skill_get_weapontype (CR_SPEARQUICKEN) & (1 << sd->status.weapon))
  4633. && sd->sc_data[SC_SPEARSQUICKEN].timer != -1)
  4634. { // スピアクィッケン
  4635. skill_status_change_end (&sd->bl, SC_SPEARSQUICKEN, -1); // スピアクイッケンを解除
  4636. return -1;
  4637. }
  4638. if (!(skill_get_weapontype (BS_ADRENALINE) & (1 << sd->status.weapon))
  4639. && sd->sc_data[SC_ADRENALINE].timer != -1)
  4640. { // アドレナリンラッシュ
  4641. skill_status_change_end (&sd->bl, SC_ADRENALINE, -1); // アドレナリンラッシュを解除
  4642. return -1;
  4643. }
  4644. if (sd->status.shield <= 0)
  4645. {
  4646. if (sd->sc_data[SC_AUTOGUARD].timer != -1)
  4647. { // オートガード
  4648. skill_status_change_end (&sd->bl, SC_AUTOGUARD, -1);
  4649. return -1;
  4650. }
  4651. if (sd->sc_data[SC_DEFENDER].timer != -1)
  4652. { // ディフェンダー
  4653. skill_status_change_end (&sd->bl, SC_DEFENDER, -1);
  4654. return -1;
  4655. }
  4656. if (sd->sc_data[SC_REFLECTSHIELD].timer != -1)
  4657. { //リフレクトシールド
  4658. skill_status_change_end (&sd->bl, SC_REFLECTSHIELD, -1);
  4659. return -1;
  4660. }
  4661. }
  4662. return 0;
  4663. }
  4664. /*==========================================
  4665. * 装 備品のチェック
  4666. *------------------------------------------
  4667. */
  4668. int pc_checkequip (struct map_session_data *sd, int pos)
  4669. {
  4670. int i;
  4671. nullpo_retr (-1, sd);
  4672. for (i = 0; i < MAX_EQUIP_SIZE; i++)
  4673. {
  4674. if (pos & equip_pos[i])
  4675. return sd->equip_index[i];
  4676. }
  4677. return -1;
  4678. }
  4679. /*==========================================
  4680. * 転生職や養子職の元の職業を返す
  4681. *------------------------------------------
  4682. */
  4683. struct pc_base_job pc_calc_base_job (int b_class)
  4684. {
  4685. struct pc_base_job bj;
  4686. //転生や養子の場合の元の職業を算出する
  4687. if (b_class < MAX_PC_CLASS)
  4688. { //通常
  4689. bj.job = b_class;
  4690. bj.upper = 0;
  4691. }
  4692. else if (b_class >= 4001 && b_class < 4023)
  4693. { //転生職
  4694. bj.job = b_class - 4001;
  4695. bj.upper = 1;
  4696. }
  4697. else if (b_class == 23 + 4023 - 1)
  4698. { //養子スパノビ
  4699. bj.job = b_class - (4023 - 1);
  4700. bj.upper = 2;
  4701. }
  4702. else
  4703. { //養子スパノビ以外の養子
  4704. bj.job = b_class - 4023;
  4705. bj.upper = 2;
  4706. }
  4707. if (battle_config.enable_upper_class == 0)
  4708. { //confで無効になっていたらupper=0
  4709. bj.upper = 0;
  4710. }
  4711. if (bj.job == 0)
  4712. {
  4713. bj.type = 0;
  4714. }
  4715. else if (bj.job < 7)
  4716. {
  4717. bj.type = 1;
  4718. }
  4719. else
  4720. {
  4721. bj.type = 2;
  4722. }
  4723. return bj;
  4724. }
  4725. /*==========================================
  4726. * PCの攻撃 (timer関数)
  4727. *------------------------------------------
  4728. */
  4729. int pc_attack_timer (int tid, unsigned int tick, int id,
  4730. int data __attribute__ ((unused)))
  4731. {
  4732. struct map_session_data *sd;
  4733. struct block_list *bl;
  4734. struct status_change *sc_data;
  4735. short *opt;
  4736. int attack_spell_delay;
  4737. sd = map_id2sd (id);
  4738. if (sd == NULL)
  4739. return 0;
  4740. if (sd->attacktimer != tid)
  4741. {
  4742. if (battle_config.error_log)
  4743. printf ("pc_attack_timer %d != %d\n", sd->attacktimer, tid);
  4744. return 0;
  4745. }
  4746. if (sd->attacktimer != -1)
  4747. pc_delattacktimer (sd);
  4748. // sd->attacktimer = -1;
  4749. if (sd->bl.prev == NULL)
  4750. return 0;
  4751. bl = map_id2bl (sd->attacktarget);
  4752. if (bl == NULL || bl->prev == NULL)
  4753. return 0;
  4754. if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl))
  4755. return 0;
  4756. // 同じmapでないなら攻撃しない
  4757. // PCが死んでても攻撃しない
  4758. if (sd->bl.m != bl->m || pc_isdead (sd))
  4759. return 0;
  4760. if (sd->opt1 > 0 || sd->status.option & 2 || sd->status.option & 16388) // 異常などで攻撃できない
  4761. return 0;
  4762. if (sd->sc_data[SC_AUTOCOUNTER].timer != -1)
  4763. return 0;
  4764. if (sd->sc_data[SC_BLADESTOP].timer != -1)
  4765. return 0;
  4766. if ((opt = battle_get_option (bl)) != NULL && *opt & 0x46)
  4767. return 0;
  4768. if (((sc_data = battle_get_sc_data (bl)) != NULL
  4769. && sc_data[SC_TRICKDEAD].timer != -1)
  4770. || ((sc_data = battle_get_sc_data (bl)) != NULL
  4771. && sc_data[SC_BASILICA].timer != -1))
  4772. return 0;
  4773. if (sd->skilltimer != -1 && pc_checkskill (sd, SA_FREECAST) <= 0)
  4774. return 0;
  4775. if (!battle_config.sdelay_attack_enable
  4776. && pc_checkskill (sd, SA_FREECAST) <= 0)
  4777. {
  4778. if (DIFF_TICK (tick, sd->canact_tick) < 0)
  4779. {
  4780. clif_skill_fail (sd, 1, 4, 0);
  4781. return 0;
  4782. }
  4783. }
  4784. if (sd->attackabletime > tick)
  4785. return 0; // cannot attack yet
  4786. attack_spell_delay = sd->attack_spell_delay;
  4787. if (attack_spell_delay < battle_config.max_aspd)
  4788. {
  4789. attack_spell_delay = battle_config.max_aspd;
  4790. }
  4791. if (sd->attack_spell_override // [Fate] If we have an active attack spell, use that
  4792. && spell_attack (id, sd->attacktarget))
  4793. {
  4794. // Return if the spell succeeded. If the spell had disspiated, spell_attack() may fail.
  4795. sd->attackabletime = tick + attack_spell_delay;
  4796. }
  4797. else
  4798. {
  4799. int dist, range;
  4800. dist = distance (sd->bl.x, sd->bl.y, bl->x, bl->y);
  4801. range = sd->attackrange;
  4802. if (sd->status.weapon != 11)
  4803. range++;
  4804. if (dist > range)
  4805. { // 届 かないので移動
  4806. //if(pc_can_reach(sd,bl->x,bl->y))
  4807. //clif_movetoattack(sd,bl);
  4808. return 0;
  4809. }
  4810. if (dist <= range && !battle_check_range (&sd->bl, bl, range))
  4811. {
  4812. if (pc_can_reach (sd, bl->x, bl->y) && sd->canmove_tick < tick
  4813. && (sd->sc_data[SC_ANKLE].timer == -1
  4814. || sd->sc_data[SC_SPIDERWEB].timer == -1))
  4815. // TMW client doesn't support this
  4816. //pc_walktoxy(sd,bl->x,bl->y);
  4817. clif_movetoattack (sd, bl);
  4818. sd->attackabletime = tick + (sd->aspd << 1);
  4819. }
  4820. else
  4821. {
  4822. int skill;
  4823. if (battle_config.pc_attack_direction_change)
  4824. sd->dir = sd->head_dir = map_calc_dir (&sd->bl, bl->x, bl->y); // 向き設定
  4825. if (sd->walktimer != -1)
  4826. pc_stop_walking (sd, 1);
  4827. if (sd->sc_data[SC_COMBO].timer == -1)
  4828. {
  4829. map_freeblock_lock ();
  4830. pc_stop_walking (sd, 0);
  4831. sd->attacktarget_lv =
  4832. battle_weapon_attack (&sd->bl, bl, tick, 0);
  4833. if (!(battle_config.pc_cloak_check_type & 2)
  4834. && sd->sc_data[SC_CLOAKING].timer != -1)
  4835. skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
  4836. map_freeblock_unlock ();
  4837. if (sd->skilltimer != -1 && (skill = pc_checkskill (sd, SA_FREECAST)) > 0) // フリーキャスト
  4838. sd->attackabletime =
  4839. tick + ((sd->aspd << 1) * (150 - skill * 5) / 100);
  4840. else
  4841. sd->attackabletime = tick + (sd->aspd << 1);
  4842. }
  4843. else if (sd->attackabletime <= tick)
  4844. {
  4845. if (sd->skilltimer != -1 && (skill = pc_checkskill (sd, SA_FREECAST)) > 0)
  4846. sd->attackabletime =
  4847. tick + ((sd->aspd << 1) * (150 - skill * 5) / 100);
  4848. else
  4849. sd->attackabletime = tick + (sd->aspd << 1);
  4850. }
  4851. if (sd->attackabletime <= tick)
  4852. sd->attackabletime = tick + (battle_config.max_aspd << 1);
  4853. }
  4854. }
  4855. if (sd->state.attack_continue)
  4856. {
  4857. sd->attacktimer =
  4858. add_timer (sd->attackabletime, pc_attack_timer, sd->bl.id, 0);
  4859. }
  4860. return 0;
  4861. }
  4862. /*==========================================
  4863. * 攻撃要求
  4864. * typeが1なら継続攻撃
  4865. *------------------------------------------
  4866. */
  4867. int pc_attack (struct map_session_data *sd, int target_id, int type)
  4868. {
  4869. struct block_list *bl;
  4870. int d;
  4871. nullpo_retr (0, sd);
  4872. bl = map_id2bl (target_id);
  4873. if (bl == NULL)
  4874. return 1;
  4875. if (bl->type == BL_NPC)
  4876. { // monster npcs [Valaris]
  4877. npc_click (sd, RFIFOL (sd->fd, 2), 0);
  4878. return 0;
  4879. }
  4880. if (!battle_check_target (&sd->bl, bl, BCT_ENEMY))
  4881. return 1;
  4882. if (sd->attacktimer != -1)
  4883. pc_stopattack (sd);
  4884. sd->attacktarget = target_id;
  4885. sd->state.attack_continue = type;
  4886. d = DIFF_TICK (sd->attackabletime, gettick ());
  4887. if (d > 0 && d < 2000)
  4888. { // 攻撃delay中
  4889. sd->attacktimer =
  4890. add_timer (sd->attackabletime, pc_attack_timer, sd->bl.id, 0);
  4891. }
  4892. else
  4893. {
  4894. // 本来timer関数なので引数を合わせる
  4895. pc_attack_timer (-1, gettick (), sd->bl.id, 0);
  4896. }
  4897. return 0;
  4898. }
  4899. /*==========================================
  4900. * 継続攻撃停止
  4901. *------------------------------------------
  4902. */
  4903. int pc_stopattack (struct map_session_data *sd)
  4904. {
  4905. nullpo_retr (0, sd);
  4906. if (sd->attacktimer != -1)
  4907. {
  4908. delete_timer (sd->attacktimer, pc_attack_timer);
  4909. sd->attacktimer = -1;
  4910. }
  4911. sd->attacktarget = 0;
  4912. sd->state.attack_continue = 0;
  4913. return 0;
  4914. }
  4915. int pc_follow_timer (int tid, unsigned int tick, int id,
  4916. int data __attribute__ ((unused)))
  4917. {
  4918. struct map_session_data *sd, *bl;
  4919. sd = map_id2sd (id);
  4920. if (sd == NULL || sd->followtimer != tid)
  4921. return 0;
  4922. sd->followtimer = -1;
  4923. do
  4924. {
  4925. if (sd->bl.prev == NULL)
  4926. break;
  4927. bl = (struct map_session_data *) map_id2bl (sd->followtarget);
  4928. if (bl == NULL)
  4929. return 0;
  4930. if (bl->bl.prev == NULL)
  4931. break;
  4932. if (bl->bl.type == BL_PC
  4933. && pc_isdead ((struct map_session_data *) bl))
  4934. return 0;
  4935. if (sd->skilltimer == -1 && sd->attacktimer == -1
  4936. && sd->walktimer == -1)
  4937. {
  4938. if ((sd->bl.m == bl->bl.m)
  4939. && pc_can_reach (sd, bl->bl.x, bl->bl.y))
  4940. {
  4941. if (distance (sd->bl.x, sd->bl.y, bl->bl.x, bl->bl.y) > 5)
  4942. pc_walktoxy (sd, bl->bl.x, bl->bl.y);
  4943. }
  4944. else
  4945. pc_setpos ((struct map_session_data *) sd, bl->mapname,
  4946. bl->bl.x, bl->bl.y, 3);
  4947. }
  4948. }
  4949. while (0);
  4950. sd->followtimer =
  4951. add_timer (tick + sd->aspd, pc_follow_timer, sd->bl.id, 0);
  4952. return 0;
  4953. }
  4954. int pc_follow (struct map_session_data *sd, int target_id)
  4955. {
  4956. struct block_list *bl;
  4957. nullpo_retr (0, sd);
  4958. bl = map_id2bl (target_id);
  4959. if (bl == NULL)
  4960. return 1;
  4961. sd->followtarget = target_id;
  4962. if (sd->followtimer != -1)
  4963. {
  4964. delete_timer (sd->followtimer, pc_follow_timer);
  4965. sd->followtimer = -1;
  4966. }
  4967. pc_follow_timer (-1, gettick (), sd->bl.id, 0);
  4968. return 0;
  4969. }
  4970. int pc_checkbaselevelup (struct map_session_data *sd)
  4971. {
  4972. nullpo_retr (0, sd);
  4973. int next = pc_nextbaseexp (sd);
  4974. if (sd->status.base_exp >= next && next > 0)
  4975. {
  4976. struct pc_base_job s_class = pc_calc_base_job (sd->status.class);
  4977. // base側レベルアップ処理
  4978. sd->status.base_exp -= next;
  4979. sd->status.base_level++;
  4980. sd->status.status_point += (sd->status.base_level + 14) / 4;
  4981. clif_updatestatus (sd, SP_STATUSPOINT);
  4982. clif_updatestatus (sd, SP_BASELEVEL);
  4983. clif_updatestatus (sd, SP_NEXTBASEEXP);
  4984. pc_calcstatus (sd, 0);
  4985. pc_heal (sd, sd->status.max_hp, sd->status.max_sp);
  4986. //スパノビはキリエ、イムポ、マニピ、グロ、サフラLv1がかかる
  4987. if (s_class.job == 23)
  4988. {
  4989. skill_status_change_start (&sd->bl,
  4990. SkillStatusChangeTable[PR_KYRIE], 1, 0,
  4991. 0, 0, skill_get_time (PR_KYRIE, 1), 0);
  4992. skill_status_change_start (&sd->bl,
  4993. SkillStatusChangeTable[PR_IMPOSITIO],
  4994. 1, 0, 0, 0,
  4995. skill_get_time (PR_IMPOSITIO, 1), 0);
  4996. skill_status_change_start (&sd->bl,
  4997. SkillStatusChangeTable[PR_MAGNIFICAT],
  4998. 1, 0, 0, 0,
  4999. skill_get_time (PR_MAGNIFICAT, 1), 0);
  5000. skill_status_change_start (&sd->bl,
  5001. SkillStatusChangeTable[PR_GLORIA], 1,
  5002. 0, 0, 0, skill_get_time (PR_GLORIA, 1),
  5003. 0);
  5004. skill_status_change_start (&sd->bl,
  5005. SkillStatusChangeTable[PR_SUFFRAGIUM],
  5006. 1, 0, 0, 0,
  5007. skill_get_time (PR_SUFFRAGIUM, 1), 0);
  5008. }
  5009. clif_misceffect (&sd->bl, 0);
  5010. //レベルアップしたのでパーティー情報を更新する
  5011. //(公平範囲チェック)
  5012. party_send_movemap (sd);
  5013. MAP_LOG_XP (sd, "LEVELUP") return 1;
  5014. }
  5015. return 0;
  5016. }
  5017. /*========================================
  5018. * Compute the maximum for sd->skill_point, i.e., the max. number of skill points that can still be filled in
  5019. *----------------------------------------
  5020. */
  5021. int pc_skillpt_potential (struct map_session_data *sd)
  5022. {
  5023. int skill_id;
  5024. int potential = 0;
  5025. nullpo_retr (0, sd);
  5026. #define RAISE_COST(x) (((x)*((x)-1))>>1)
  5027. for (skill_id = 0; skill_id < MAX_SKILL; skill_id++)
  5028. if (sd->status.skill[skill_id].id != 0
  5029. && sd->status.skill[skill_id].lv < skill_db[skill_id].max_raise)
  5030. potential += RAISE_COST (skill_db[skill_id].max_raise)
  5031. - RAISE_COST (sd->status.skill[skill_id].lv);
  5032. #undef RAISE_COST
  5033. return potential;
  5034. }
  5035. int pc_checkjoblevelup (struct map_session_data *sd)
  5036. {
  5037. nullpo_retr (0, sd);
  5038. int next = pc_nextjobexp (sd);
  5039. if (sd->status.job_exp >= next && next > 0)
  5040. {
  5041. if (pc_skillpt_potential (sd) < sd->status.skill_point)
  5042. { // [Fate] Bah, this is is painful.
  5043. // But the alternative is quite error-prone, and eAthena has far worse performance issues...
  5044. sd->status.job_exp = next - 1;
  5045. pc_calcstatus(sd,0);
  5046. return 0;
  5047. }
  5048. // job側レベルアップ処理
  5049. sd->status.job_exp -= next;
  5050. clif_updatestatus (sd, SP_NEXTJOBEXP);
  5051. sd->status.skill_point++;
  5052. clif_updatestatus (sd, SP_SKILLPOINT);
  5053. pc_calcstatus (sd, 0);
  5054. MAP_LOG_PC (sd, "SKILLPOINTS-UP %d", sd->status.skill_point);
  5055. if (sd->status.job_level < 250
  5056. && sd->status.job_level < sd->status.base_level * 2)
  5057. sd->status.job_level++; // Make levelling up a little harder
  5058. clif_misceffect (&sd->bl, 1);
  5059. return 1;
  5060. }
  5061. return 0;
  5062. }
  5063. /*==========================================
  5064. * 経験値取得
  5065. *------------------------------------------
  5066. */
  5067. int pc_gainexp (struct map_session_data *sd, int base_exp, int job_exp)
  5068. {
  5069. return pc_gainexp_reason (sd, base_exp, job_exp,
  5070. PC_GAINEXP_REASON_KILLING);
  5071. }
  5072. int pc_gainexp_reason (struct map_session_data *sd, int base_exp, int job_exp,
  5073. int reason)
  5074. {
  5075. char output[256];
  5076. nullpo_retr (0, sd);
  5077. if (sd->bl.prev == NULL || pc_isdead (sd))
  5078. return 0;
  5079. if ((battle_config.pvp_exp == 0) && map[sd->bl.m].flag.pvp) // [MouseJstr]
  5080. return 0; // no exp on pvp maps
  5081. MAP_LOG_PC (sd, "GAINXP %d %d %s", base_exp, job_exp,
  5082. ((reason ==
  5083. 2) ? "SCRIPTXP" : ((reason == 1) ? "HEALXP" : "KILLXP")));
  5084. if (sd->sc_data[SC_RICHMANKIM].timer != -1)
  5085. { // added bounds checking [Vaalris]
  5086. base_exp +=
  5087. base_exp * (25 + sd->sc_data[SC_RICHMANKIM].val1 * 25) / 100;
  5088. job_exp +=
  5089. job_exp * (25 + sd->sc_data[SC_RICHMANKIM].val1 * 25) / 100;
  5090. }
  5091. if (sd->status.guild_id > 0)
  5092. { // ギルドに上納
  5093. base_exp -= guild_payexp (sd, base_exp);
  5094. if (base_exp < 0)
  5095. base_exp = 0;
  5096. }
  5097. if (!battle_config.multi_level_up && pc_nextbaseafter (sd))
  5098. {
  5099. while (sd->status.base_exp + base_exp >= pc_nextbaseafter (sd)
  5100. && sd->status.base_exp <= pc_nextbaseexp (sd)
  5101. && pc_nextbaseafter (sd) > 0)
  5102. {
  5103. base_exp *= .90;
  5104. }
  5105. }
  5106. sd->status.base_exp += base_exp;
  5107. // [Fate] Adjust experience points that healers can extract from this character
  5108. if (reason != PC_GAINEXP_REASON_HEALING)
  5109. {
  5110. const int max_heal_xp =
  5111. 20 + (sd->status.base_level * sd->status.base_level);
  5112. sd->heal_xp += base_exp;
  5113. if (sd->heal_xp > max_heal_xp)
  5114. sd->heal_xp = max_heal_xp;
  5115. }
  5116. if (sd->status.base_exp < 0)
  5117. sd->status.base_exp = 0;
  5118. while (pc_checkbaselevelup (sd));
  5119. clif_updatestatus (sd, SP_BASEEXP);
  5120. if (!battle_config.multi_level_up && pc_nextjobafter (sd))
  5121. {
  5122. while (sd->status.job_exp + job_exp >= pc_nextjobafter (sd)
  5123. && sd->status.job_exp <= pc_nextjobexp (sd)
  5124. && pc_nextjobafter (sd) > 0)
  5125. {
  5126. job_exp *= .90;
  5127. }
  5128. }
  5129. sd->status.job_exp += job_exp;
  5130. if (sd->status.job_exp < 0)
  5131. sd->status.job_exp = 0;
  5132. while (pc_checkjoblevelup (sd));
  5133. clif_updatestatus (sd, SP_JOBEXP);
  5134. if (battle_config.disp_experience)
  5135. {
  5136. sprintf (output,
  5137. "Experienced Gained Base:%d Job:%d", base_exp, job_exp);
  5138. clif_disp_onlyself (sd, output, strlen (output));
  5139. }
  5140. return 0;
  5141. }
  5142. int pc_extract_healer_exp (struct map_session_data *sd, int max)
  5143. {
  5144. int amount;
  5145. nullpo_retr (0, sd);
  5146. amount = sd->heal_xp;
  5147. if (max < amount)
  5148. amount = max;
  5149. sd->heal_xp -= amount;
  5150. return amount;
  5151. }
  5152. /*==========================================
  5153. * base level側必要経験値計算
  5154. *------------------------------------------
  5155. */
  5156. int pc_nextbaseexp (struct map_session_data *sd)
  5157. {
  5158. int i;
  5159. nullpo_retr (0, sd);
  5160. if (sd->status.base_level >= MAX_LEVEL || sd->status.base_level <= 0)
  5161. return 0;
  5162. if (sd->status.class <= MAX_PLAYER_CLASS)
  5163. i = 0;
  5164. else if (sd->status.class <= 6)
  5165. i = 1;
  5166. else if (sd->status.class <= 22)
  5167. i = 2;
  5168. else if (sd->status.class == 23)
  5169. i = 3;
  5170. else if (sd->status.class == 4001)
  5171. i = 4;
  5172. else if (sd->status.class <= 4007)
  5173. i = 5;
  5174. else
  5175. i = 6;
  5176. return exp_table[i][sd->status.base_level - 1];
  5177. }
  5178. /*==========================================
  5179. * job level側必要経験値計算
  5180. *------------------------------------------
  5181. */
  5182. int pc_nextjobexp (struct map_session_data *sd)
  5183. {
  5184. nullpo_retr (0, sd);
  5185. // [fate] For normal levels, this ranges from 20k to 50k, depending on job level.
  5186. // Job level is at most twice the player's experience level (base_level). Levelling
  5187. // from 2 to 9 is 44 points, i.e., 880k to 2.2M job experience points (this is per
  5188. // skill, obviously.)
  5189. return 20000 + sd->status.job_level * 150;
  5190. }
  5191. /*==========================================
  5192. * base level after next [Valaris]
  5193. *------------------------------------------
  5194. */
  5195. int pc_nextbaseafter (struct map_session_data *sd)
  5196. {
  5197. int i;
  5198. nullpo_retr (0, sd);
  5199. if (sd->status.base_level >= MAX_LEVEL || sd->status.base_level <= 0)
  5200. return 0;
  5201. if (sd->status.class <= MAX_PLAYER_CLASS)
  5202. i = 0;
  5203. else if (sd->status.class <= 6)
  5204. i = 1;
  5205. else if (sd->status.class <= 22)
  5206. i = 2;
  5207. else if (sd->status.class == 23)
  5208. i = 3;
  5209. else if (sd->status.class == 4001)
  5210. i = 4;
  5211. else if (sd->status.class <= 4007)
  5212. i = 5;
  5213. else
  5214. i = 6;
  5215. return exp_table[i][sd->status.base_level];
  5216. }
  5217. /*==========================================
  5218. * job level after next [Valaris]
  5219. *------------------------------------------
  5220. */
  5221. int pc_nextjobafter (struct map_session_data *sd)
  5222. {
  5223. int i;
  5224. nullpo_retr (0, sd);
  5225. if (sd->status.job_level >= MAX_LEVEL || sd->status.job_level <= 0)
  5226. return 0;
  5227. if (sd->status.class <= MAX_PLAYER_CLASS)
  5228. i = 7;
  5229. else if (sd->status.class <= 6)
  5230. i = 8;
  5231. else if (sd->status.class <= 22)
  5232. i = 9;
  5233. else if (sd->status.class == 23)
  5234. i = 10;
  5235. else if (sd->status.class == 4001)
  5236. i = 11;
  5237. else if (sd->status.class <= 4007)
  5238. i = 12;
  5239. else
  5240. i = 13;
  5241. return exp_table[i][sd->status.job_level];
  5242. }
  5243. /*==========================================
  5244. * 必要ステータスポイント計算
  5245. *------------------------------------------
  5246. */
  5247. int pc_need_status_point (struct map_session_data *sd, int type)
  5248. {
  5249. int val;
  5250. nullpo_retr (-1, sd);
  5251. if (type < SP_STR || type > SP_LUK)
  5252. return -1;
  5253. val =
  5254. type == SP_STR ? sd->status.str :
  5255. type == SP_AGI ? sd->status.agi :
  5256. type == SP_VIT ? sd->status.vit :
  5257. type == SP_INT ? sd->status.int_ :
  5258. type == SP_DEX ? sd->status.dex : sd->status.luk;
  5259. return (val + 9) / 10 + 1;
  5260. }
  5261. /*==========================================
  5262. * 能力値成長
  5263. *------------------------------------------
  5264. */
  5265. int pc_statusup (struct map_session_data *sd, int type)
  5266. {
  5267. int need, val = 0;
  5268. nullpo_retr (0, sd);
  5269. switch (type)
  5270. {
  5271. case SP_STR:
  5272. val = sd->status.str;
  5273. break;
  5274. case SP_AGI:
  5275. val = sd->status.agi;
  5276. break;
  5277. case SP_VIT:
  5278. val = sd->status.vit;
  5279. break;
  5280. case SP_INT:
  5281. val = sd->status.int_;
  5282. break;
  5283. case SP_DEX:
  5284. val = sd->status.dex;
  5285. break;
  5286. case SP_LUK:
  5287. val = sd->status.luk;
  5288. break;
  5289. default:
  5290. break;
  5291. }
  5292. need = pc_need_status_point (sd, type);
  5293. if (type < SP_STR || type > SP_LUK || need < 0
  5294. || need > sd->status.status_point
  5295. || val >= battle_config.max_parameter)
  5296. {
  5297. clif_statusupack (sd, type, 0, val);
  5298. return 1;
  5299. }
  5300. switch (type)
  5301. {
  5302. case SP_STR:
  5303. val = ++sd->status.str;
  5304. break;
  5305. case SP_AGI:
  5306. val = ++sd->status.agi;
  5307. break;
  5308. case SP_VIT:
  5309. val = ++sd->status.vit;
  5310. break;
  5311. case SP_INT:
  5312. val = ++sd->status.int_;
  5313. break;
  5314. case SP_DEX:
  5315. val = ++sd->status.dex;
  5316. break;
  5317. case SP_LUK:
  5318. val = ++sd->status.luk;
  5319. break;
  5320. default:
  5321. break;
  5322. }
  5323. sd->status.status_point -= need;
  5324. if (need != pc_need_status_point (sd, type))
  5325. {
  5326. clif_updatestatus (sd, type - SP_STR + SP_USTR);
  5327. }
  5328. clif_updatestatus (sd, SP_STATUSPOINT);
  5329. clif_updatestatus (sd, type);
  5330. pc_calcstatus (sd, 0);
  5331. clif_statusupack (sd, type, 1, val);
  5332. MAP_LOG_STATS (sd, "STATUP");
  5333. return 0;
  5334. }
  5335. /*==========================================
  5336. * 能力値成長
  5337. *------------------------------------------
  5338. */
  5339. int pc_statusup2 (struct map_session_data *sd, int type, int val)
  5340. {
  5341. nullpo_retr (0, sd);
  5342. if (type < SP_STR || type > SP_LUK)
  5343. {
  5344. clif_statusupack (sd, type, 0, 0);
  5345. return 1;
  5346. }
  5347. switch (type)
  5348. {
  5349. case SP_STR:
  5350. if (sd->status.str + val >= battle_config.max_parameter)
  5351. val = battle_config.max_parameter;
  5352. else if (sd->status.str + val < 1)
  5353. val = 1;
  5354. else
  5355. val += sd->status.str;
  5356. sd->status.str = val;
  5357. break;
  5358. case SP_AGI:
  5359. if (sd->status.agi + val >= battle_config.max_parameter)
  5360. val = battle_config.max_parameter;
  5361. else if (sd->status.agi + val < 1)
  5362. val = 1;
  5363. else
  5364. val += sd->status.agi;
  5365. sd->status.agi = val;
  5366. break;
  5367. case SP_VIT:
  5368. if (sd->status.vit + val >= battle_config.max_parameter)
  5369. val = battle_config.max_parameter;
  5370. else if (sd->status.vit + val < 1)
  5371. val = 1;
  5372. else
  5373. val += sd->status.vit;
  5374. sd->status.vit = val;
  5375. break;
  5376. case SP_INT:
  5377. if (sd->status.int_ + val >= battle_config.max_parameter)
  5378. val = battle_config.max_parameter;
  5379. else if (sd->status.int_ + val < 1)
  5380. val = 1;
  5381. else
  5382. val += sd->status.int_;
  5383. sd->status.int_ = val;
  5384. break;
  5385. case SP_DEX:
  5386. if (sd->status.dex + val >= battle_config.max_parameter)
  5387. val = battle_config.max_parameter;
  5388. else if (sd->status.dex + val < 1)
  5389. val = 1;
  5390. else
  5391. val += sd->status.dex;
  5392. sd->status.dex = val;
  5393. break;
  5394. case SP_LUK:
  5395. if (sd->status.luk + val >= battle_config.max_parameter)
  5396. val = battle_config.max_parameter;
  5397. else if (sd->status.luk + val < 1)
  5398. val = 1;
  5399. else
  5400. val = sd->status.luk + val;
  5401. sd->status.luk = val;
  5402. break;
  5403. default:
  5404. break;
  5405. }
  5406. clif_updatestatus (sd, type - SP_STR + SP_USTR);
  5407. clif_updatestatus (sd, type);
  5408. pc_calcstatus (sd, 0);
  5409. clif_statusupack (sd, type, 1, val);
  5410. MAP_LOG_STATS (sd, "STATUP2");
  5411. return 0;
  5412. }
  5413. /*==========================================
  5414. * スキルポイント割り振り
  5415. *------------------------------------------
  5416. */
  5417. int pc_skillup (struct map_session_data *sd, int skill_num)
  5418. {
  5419. nullpo_retr (0, sd);
  5420. if (skill_num < 0 || skill_num >= MAX_SKILL)
  5421. return 0;
  5422. if (sd->status.skill[skill_num].id != 0
  5423. && sd->status.skill_point >= sd->status.skill[skill_num].lv
  5424. && sd->status.skill[skill_num].lv < skill_db[skill_num].max_raise)
  5425. {
  5426. sd->status.skill_point -= sd->status.skill[skill_num].lv;
  5427. sd->status.skill[skill_num].lv++;
  5428. pc_calcstatus (sd, 0);
  5429. clif_skillup (sd, skill_num);
  5430. clif_updatestatus (sd, SP_SKILLPOINT);
  5431. clif_skillinfoblock (sd);
  5432. MAP_LOG_PC(sd, "SKILLUP %d %d %d",
  5433. skill_num, sd->status.skill[skill_num].lv, skill_power(sd, skill_num));
  5434. }
  5435. return 0;
  5436. }
  5437. /*==========================================
  5438. * /allskill
  5439. *------------------------------------------
  5440. */
  5441. int pc_allskillup (struct map_session_data *sd)
  5442. {
  5443. int i, id;
  5444. int c = 0, s = 0;
  5445. //転生や養子の場合の元の職業を算出する
  5446. struct pc_base_job s_class;
  5447. nullpo_retr (0, sd);
  5448. s_class = pc_calc_base_job (sd->status.class);
  5449. c = s_class.job;
  5450. s = (s_class.upper == 1) ? 1 : 0; //転生以外は通常のスキル?
  5451. for (i = 0; i < MAX_SKILL; i++)
  5452. sd->status.skill[i].id = 0;
  5453. if (battle_config.gm_allskill > 0
  5454. && pc_isGM (sd) >= battle_config.gm_allskill)
  5455. {
  5456. // 全てのスキル
  5457. for (i = 1; i < 158; i++)
  5458. sd->status.skill[i].lv = skill_get_max (i);
  5459. for (i = 210; i < 291; i++)
  5460. sd->status.skill[i].lv = skill_get_max (i);
  5461. for (i = 304; i < MAX_SKILL; i++)
  5462. sd->status.skill[i].lv = skill_get_max (i);
  5463. }
  5464. else
  5465. {
  5466. for (i = 0; (id = skill_tree[s][c][i].id) > 0; i++)
  5467. {
  5468. if (sd->status.skill[id].id == 0 && skill_get_inf2 (id) & 0x01)
  5469. sd->status.skill[id].lv = skill_get_max (id);
  5470. }
  5471. }
  5472. pc_calcstatus (sd, 0);
  5473. return 0;
  5474. }
  5475. /*==========================================
  5476. * /resetlvl
  5477. *------------------------------------------
  5478. */
  5479. int pc_resetlvl (struct map_session_data *sd, int type)
  5480. {
  5481. int i;
  5482. nullpo_retr (0, sd);
  5483. for (i = 1; i < MAX_SKILL; i++)
  5484. {
  5485. sd->status.skill[i].lv = 0;
  5486. }
  5487. if (type == 1)
  5488. {
  5489. sd->status.skill_point = 0;
  5490. sd->status.base_level = 1;
  5491. sd->status.job_level = 1;
  5492. sd->status.base_exp = 0;
  5493. sd->status.job_exp = 0;
  5494. if (sd->status.option != 0)
  5495. sd->status.option = 0;
  5496. sd->status.str = 1;
  5497. sd->status.agi = 1;
  5498. sd->status.vit = 1;
  5499. sd->status.int_ = 1;
  5500. sd->status.dex = 1;
  5501. sd->status.luk = 1;
  5502. if (sd->status.class == 4001)
  5503. sd->status.status_point = 100;
  5504. }
  5505. if (type == 2)
  5506. {
  5507. sd->status.skill_point = 0;
  5508. sd->status.base_level = 1;
  5509. sd->status.job_level = 1;
  5510. sd->status.base_exp = 0;
  5511. sd->status.job_exp = 0;
  5512. }
  5513. if (type == 3)
  5514. {
  5515. sd->status.base_level = 1;
  5516. sd->status.base_exp = 0;
  5517. }
  5518. if (type == 4)
  5519. {
  5520. sd->status.job_level = 1;
  5521. sd->status.job_exp = 0;
  5522. }
  5523. clif_updatestatus (sd, SP_STATUSPOINT);
  5524. clif_updatestatus (sd, SP_STR);
  5525. clif_updatestatus (sd, SP_AGI);
  5526. clif_updatestatus (sd, SP_VIT);
  5527. clif_updatestatus (sd, SP_INT);
  5528. clif_updatestatus (sd, SP_DEX);
  5529. clif_updatestatus (sd, SP_LUK);
  5530. clif_updatestatus (sd, SP_BASELEVEL);
  5531. clif_updatestatus (sd, SP_JOBLEVEL);
  5532. clif_updatestatus (sd, SP_STATUSPOINT);
  5533. clif_updatestatus (sd, SP_NEXTBASEEXP);
  5534. clif_updatestatus (sd, SP_NEXTJOBEXP);
  5535. clif_updatestatus (sd, SP_SKILLPOINT);
  5536. clif_updatestatus (sd, SP_USTR); // Updates needed stat points - Valaris
  5537. clif_updatestatus (sd, SP_UAGI);
  5538. clif_updatestatus (sd, SP_UVIT);
  5539. clif_updatestatus (sd, SP_UINT);
  5540. clif_updatestatus (sd, SP_UDEX);
  5541. clif_updatestatus (sd, SP_ULUK); // End Addition
  5542. for (i = 0; i < MAX_EQUIP_SIZE; i++)
  5543. { // unequip items that can't be equipped by base 1 [Valaris]
  5544. if (sd->equip_index[i] >= 0)
  5545. if (!pc_isequip (sd, sd->equip_index[i]))
  5546. {
  5547. pc_unequipitem (sd, sd->equip_index[i], 1);
  5548. sd->equip_index[i] = -1;
  5549. }
  5550. }
  5551. clif_skillinfoblock (sd);
  5552. pc_calcstatus (sd, 0);
  5553. MAP_LOG_STATS (sd, "STATRESET");
  5554. return 0;
  5555. }
  5556. /*==========================================
  5557. * /resetstate
  5558. *------------------------------------------
  5559. */
  5560. int pc_resetstate (struct map_session_data *sd)
  5561. {
  5562. #define sumsp(a) ((a)*((a-2)/10+2) - 5*((a-2)/10)*((a-2)/10) - 6*((a-2)/10) -2)
  5563. // int add=0; // Removed by Dexity
  5564. nullpo_retr (0, sd);
  5565. if (sd->status.base_level < 1)
  5566. return 0;
  5567. // New statpoint table used here - Dexity
  5568. sd->status.status_point = atoi (statp[sd->status.base_level - 1]);
  5569. // End addition
  5570. // Removed by Dexity - old count
  5571. // add += sumsp(sd->status.str);
  5572. // add += sumsp(sd->status.agi);
  5573. // add += sumsp(sd->status.vit);
  5574. // add += sumsp(sd->status.int_);
  5575. // add += sumsp(sd->status.dex);
  5576. // add += sumsp(sd->status.luk);
  5577. // sd->status.status_point+=add;
  5578. clif_updatestatus (sd, SP_STATUSPOINT);
  5579. sd->status.str = 1;
  5580. sd->status.agi = 1;
  5581. sd->status.vit = 1;
  5582. sd->status.int_ = 1;
  5583. sd->status.dex = 1;
  5584. sd->status.luk = 1;
  5585. clif_updatestatus (sd, SP_STR);
  5586. clif_updatestatus (sd, SP_AGI);
  5587. clif_updatestatus (sd, SP_VIT);
  5588. clif_updatestatus (sd, SP_INT);
  5589. clif_updatestatus (sd, SP_DEX);
  5590. clif_updatestatus (sd, SP_LUK);
  5591. clif_updatestatus (sd, SP_USTR); // Updates needed stat points - Valaris
  5592. clif_updatestatus (sd, SP_UAGI);
  5593. clif_updatestatus (sd, SP_UVIT);
  5594. clif_updatestatus (sd, SP_UINT);
  5595. clif_updatestatus (sd, SP_UDEX);
  5596. clif_updatestatus (sd, SP_ULUK); // End Addition
  5597. pc_calcstatus (sd, 0);
  5598. return 0;
  5599. }
  5600. /*==========================================
  5601. * /resetskill
  5602. *------------------------------------------
  5603. */
  5604. int pc_resetskill (struct map_session_data *sd)
  5605. {
  5606. int i;
  5607. nullpo_retr (0, sd);
  5608. sd->status.skill_point += pc_calc_skillpoint (sd);
  5609. for (i = 1; i < MAX_SKILL; i++)
  5610. if (pc_checkskill (sd, i) > 0)
  5611. {
  5612. sd->status.skill[i].lv = 0;
  5613. sd->status.skill[i].flags = 0;
  5614. }
  5615. clif_updatestatus (sd, SP_SKILLPOINT);
  5616. clif_skillinfoblock (sd);
  5617. pc_calcstatus (sd, 0);
  5618. return 0;
  5619. }
  5620. /*==========================================
  5621. * pcにダメージを与える
  5622. *------------------------------------------
  5623. */
  5624. int pc_damage (struct block_list *src, struct map_session_data *sd,
  5625. int damage)
  5626. {
  5627. int i = 0, j = 0;
  5628. struct pc_base_job s_class;
  5629. nullpo_retr (0, sd);
  5630. //転生や養子の場合の元の職業を算出する
  5631. s_class = pc_calc_base_job (sd->status.class);
  5632. // 既に死んでいたら無効
  5633. if (pc_isdead (sd))
  5634. return 0;
  5635. // 座ってたら立ち上がる
  5636. if (pc_issit (sd))
  5637. {
  5638. pc_setstand (sd);
  5639. skill_gangsterparadise (sd, 0);
  5640. }
  5641. if (src)
  5642. {
  5643. if (src->type == BL_PC)
  5644. {
  5645. MAP_LOG_PC (sd, "INJURED-BY PC%d FOR %d",
  5646. ((struct map_session_data *) src)->status.char_id,
  5647. damage);
  5648. }
  5649. else
  5650. {
  5651. MAP_LOG_PC (sd, "INJURED-BY MOB%d FOR %d", src->id, damage);
  5652. }
  5653. }
  5654. else
  5655. MAP_LOG_PC (sd, "INJURED-BY null FOR %d", damage);
  5656. // 歩 いていたら足を止める
  5657. if (sd->sc_data[SC_ENDURE].timer == -1
  5658. && !sd->special_state.infinite_endure)
  5659. pc_stop_walking (sd, 3);
  5660. // 演奏/ダンスの中断
  5661. if (damage > sd->status.max_hp >> 2)
  5662. skill_stop_dancing (&sd->bl, 0);
  5663. sd->status.hp -= damage;
  5664. if (sd->sc_data[SC_TRICKDEAD].timer != -1)
  5665. skill_status_change_end (&sd->bl, SC_TRICKDEAD, -1);
  5666. if (sd->status.option & 2)
  5667. skill_status_change_end (&sd->bl, SC_HIDING, -1);
  5668. if (sd->status.option & 4)
  5669. skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
  5670. if (sd->status.option & 16386)
  5671. skill_status_change_end (&sd->bl, SC_CHASEWALK, -1);
  5672. if (sd->status.hp > 0)
  5673. {
  5674. // まだ生きているならHP更新
  5675. clif_updatestatus (sd, SP_HP);
  5676. if (sd->status.hp < sd->status.max_hp >> 2
  5677. && pc_checkskill (sd, SM_AUTOBERSERK) > 0
  5678. && (sd->sc_data[SC_PROVOKE].timer == -1
  5679. || sd->sc_data[SC_PROVOKE].val2 == 0))
  5680. // オートバーサーク発動
  5681. skill_status_change_start (&sd->bl, SC_PROVOKE, 10, 1, 0, 0, 0,
  5682. 0);
  5683. sd->canlog_tick = gettick ();
  5684. if (sd->status.party_id > 0)
  5685. { // on-the-fly party hp updates [Valaris]
  5686. struct party *p = party_search (sd->status.party_id);
  5687. if (p != NULL)
  5688. clif_party_hp (p, sd);
  5689. } // end addition [Valaris]
  5690. return 0;
  5691. }
  5692. MAP_LOG_PC (sd, "DEAD%s", "");
  5693. // Character is dead!
  5694. sd->status.hp = 0;
  5695. // [Fate] Stop quickregen
  5696. sd->quick_regeneration_hp.amount = 0;
  5697. sd->quick_regeneration_sp.amount = 0;
  5698. skill_update_heal_animation (sd);
  5699. pc_setdead (sd);
  5700. pc_stop_walking (sd, 0);
  5701. skill_castcancel (&sd->bl, 0); // 詠唱の中止
  5702. clif_clearchar_area (&sd->bl, 1);
  5703. skill_unit_out_all (&sd->bl, gettick (), 1);
  5704. if (sd->sc_data[SC_BLADESTOP].timer != -1) //白刃は事前に解除
  5705. skill_status_change_end (&sd->bl, SC_BLADESTOP, -1);
  5706. pc_setglobalreg (sd, "PC_DIE_COUNTER", ++sd->die_counter); //死にカウンター書き込み
  5707. skill_status_change_clear (&sd->bl, 0); // ステータス異常を解除する
  5708. clif_updatestatus (sd, SP_HP);
  5709. pc_calcstatus (sd, 0);
  5710. // [Fate] Reset magic
  5711. sd->cast_tick = gettick ();
  5712. magic_stop_completely (sd);
  5713. for (i = 0; i < 5; i++)
  5714. if (sd->dev.val1[i])
  5715. {
  5716. skill_status_change_end (&map_id2sd (sd->dev.val1[i])->bl,
  5717. SC_DEVOTION, -1);
  5718. sd->dev.val1[i] = sd->dev.val2[i] = 0;
  5719. }
  5720. if (battle_config.death_penalty_type > 0 && sd->status.base_level >= 20)
  5721. { // changed penalty options, added death by player if pk_mode [Valaris]
  5722. if (!map[sd->bl.m].flag.nopenalty && !map[sd->bl.m].flag.gvg)
  5723. {
  5724. if (battle_config.death_penalty_type == 1
  5725. && battle_config.death_penalty_base > 0)
  5726. sd->status.base_exp -=
  5727. (double) pc_nextbaseexp (sd) *
  5728. (double) battle_config.death_penalty_base / 10000;
  5729. if (battle_config.pk_mode && src && src->type == BL_PC)
  5730. sd->status.base_exp -=
  5731. (double) pc_nextbaseexp (sd) *
  5732. (double) battle_config.death_penalty_base / 10000;
  5733. else if (battle_config.death_penalty_type == 2
  5734. && battle_config.death_penalty_base > 0)
  5735. {
  5736. if (pc_nextbaseexp (sd) > 0)
  5737. sd->status.base_exp -=
  5738. (double) sd->status.base_exp *
  5739. (double) battle_config.death_penalty_base / 10000;
  5740. if (battle_config.pk_mode && src && src->type == BL_PC)
  5741. sd->status.base_exp -=
  5742. (double) sd->status.base_exp *
  5743. (double) battle_config.death_penalty_base / 10000;
  5744. }
  5745. if (sd->status.base_exp < 0)
  5746. sd->status.base_exp = 0;
  5747. clif_updatestatus (sd, SP_BASEEXP);
  5748. if (battle_config.death_penalty_type == 1
  5749. && battle_config.death_penalty_job > 0)
  5750. sd->status.job_exp -=
  5751. (double) pc_nextjobexp (sd) *
  5752. (double) battle_config.death_penalty_job / 10000;
  5753. if (battle_config.pk_mode && src && src->type == BL_PC)
  5754. sd->status.job_exp -=
  5755. (double) pc_nextjobexp (sd) *
  5756. (double) battle_config.death_penalty_job / 10000;
  5757. else if (battle_config.death_penalty_type == 2
  5758. && battle_config.death_penalty_job > 0)
  5759. {
  5760. if (pc_nextjobexp (sd) > 0)
  5761. sd->status.job_exp -=
  5762. (double) sd->status.job_exp *
  5763. (double) battle_config.death_penalty_job / 10000;
  5764. if (battle_config.pk_mode && src && src->type == BL_PC)
  5765. sd->status.job_exp -=
  5766. (double) sd->status.job_exp *
  5767. (double) battle_config.death_penalty_job / 10000;
  5768. }
  5769. if (sd->status.job_exp < 0)
  5770. sd->status.job_exp = 0;
  5771. clif_updatestatus (sd, SP_JOBEXP);
  5772. }
  5773. }
  5774. //ナイトメアモードアイテムドロップ
  5775. if (map[sd->bl.m].flag.pvp_nightmaredrop)
  5776. { // Moved this outside so it works when PVP isnt enabled and during pk mode [Ancyker]
  5777. for (j = 0; j < MAX_DROP_PER_MAP; j++)
  5778. {
  5779. int id = map[sd->bl.m].drop_list[j].drop_id;
  5780. int type = map[sd->bl.m].drop_list[j].drop_type;
  5781. int per = map[sd->bl.m].drop_list[j].drop_per;
  5782. if (id == 0)
  5783. continue;
  5784. if (id == -1)
  5785. { //ランダムドロップ
  5786. int eq_num = 0, eq_n[MAX_INVENTORY];
  5787. memset (eq_n, 0, sizeof (eq_n));
  5788. //先ず装備しているアイテム数をカウント
  5789. for (i = 0; i < MAX_INVENTORY; i++)
  5790. {
  5791. if ((type == 1 && !sd->status.inventory[i].equip)
  5792. || (type == 2 && sd->status.inventory[i].equip)
  5793. || type == 3)
  5794. {
  5795. //InventoryIndexを格納
  5796. int k;
  5797. for (k = 0; k < MAX_INVENTORY; k++)
  5798. {
  5799. if (eq_n[k] <= 0)
  5800. {
  5801. eq_n[k] = i;
  5802. break;
  5803. }
  5804. }
  5805. eq_num++;
  5806. }
  5807. }
  5808. if (eq_num > 0)
  5809. {
  5810. int n = eq_n[MRAND (eq_num)]; //該当アイテムの中からランダム
  5811. if (MRAND (10000) < per)
  5812. {
  5813. if (sd->status.inventory[n].equip)
  5814. pc_unequipitem (sd, n, 0);
  5815. pc_dropitem (sd, n, 1);
  5816. }
  5817. }
  5818. }
  5819. else if (id > 0)
  5820. {
  5821. for (i = 0; i < MAX_INVENTORY; i++)
  5822. {
  5823. if (sd->status.inventory[i].nameid == id //ItemIDが一致していて
  5824. && MRAND (10000) < per //ドロップ率判定もOKで
  5825. && ((type == 1 && !sd->status.inventory[i].equip) //タイプ判定もOKならドロップ
  5826. || (type == 2 && sd->status.inventory[i].equip)
  5827. || type == 3))
  5828. {
  5829. if (sd->status.inventory[i].equip)
  5830. pc_unequipitem (sd, i, 0);
  5831. pc_dropitem (sd, i, 1);
  5832. break;
  5833. }
  5834. }
  5835. }
  5836. }
  5837. }
  5838. // pvp
  5839. if (map[sd->bl.m].flag.pvp && !battle_config.pk_mode)
  5840. { // disable certain pvp functions on pk_mode [Valaris]
  5841. //ランキング計算
  5842. if (!map[sd->bl.m].flag.pvp_nocalcrank)
  5843. {
  5844. sd->pvp_point -= 5;
  5845. if (src && src->type == BL_PC)
  5846. ((struct map_session_data *) src)->pvp_point++;
  5847. //} //fixed wrong '{' placement by Lupus
  5848. pc_setdead (sd);
  5849. }
  5850. // 強制送還
  5851. if (sd->pvp_point < 0)
  5852. {
  5853. sd->pvp_point = 0;
  5854. pc_setstand (sd);
  5855. pc_setrestartvalue (sd, 3);
  5856. pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
  5857. sd->status.save_point.y, 0);
  5858. }
  5859. }
  5860. //GvG
  5861. if (map[sd->bl.m].flag.gvg)
  5862. {
  5863. pc_setstand (sd);
  5864. pc_setrestartvalue (sd, 3);
  5865. pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
  5866. sd->status.save_point.y, 0);
  5867. }
  5868. if (src && src->type == BL_PC)
  5869. {
  5870. // [Fate] PK death, trigger scripts
  5871. argrec_t arg[3];
  5872. arg[0].name = "@killerrid";
  5873. arg[0].v.i = src->id;
  5874. arg[1].name = "@victimrid";
  5875. arg[1].v.i = sd->bl.id;
  5876. arg[2].name = "@victimlvl";
  5877. arg[2].v.i = sd->status.base_level;
  5878. npc_event_doall_l ("OnPCKilledEvent", sd->bl.id, 3, arg);
  5879. npc_event_doall_l ("OnPCKillEvent", src->id, 3, arg);
  5880. }
  5881. npc_event_doall_l ("OnPCDieEvent", sd->bl.id, 0, NULL);
  5882. return 0;
  5883. }
  5884. //
  5885. // script関 連
  5886. //
  5887. /*==========================================
  5888. * script用PCステータス読み出し
  5889. *------------------------------------------
  5890. */
  5891. int pc_readparam (struct map_session_data *sd, int type)
  5892. {
  5893. int val = 0;
  5894. struct pc_base_job s_class;
  5895. nullpo_retr (0, sd);
  5896. s_class = pc_calc_base_job (sd->status.class);
  5897. switch (type)
  5898. {
  5899. case SP_SKILLPOINT:
  5900. val = sd->status.skill_point;
  5901. break;
  5902. case SP_STATUSPOINT:
  5903. val = sd->status.status_point;
  5904. break;
  5905. case SP_ZENY:
  5906. val = sd->status.zeny;
  5907. break;
  5908. case SP_BASELEVEL:
  5909. val = sd->status.base_level;
  5910. break;
  5911. case SP_JOBLEVEL:
  5912. val = sd->status.job_level;
  5913. break;
  5914. case SP_CLASS:
  5915. if (val >= 24 && val < 45)
  5916. val += 3978;
  5917. else
  5918. val = sd->status.class;
  5919. break;
  5920. case SP_UPPER:
  5921. val = s_class.upper;
  5922. break;
  5923. case SP_SEX:
  5924. val = sd->sex;
  5925. break;
  5926. case SP_WEIGHT:
  5927. val = sd->weight;
  5928. break;
  5929. case SP_MAXWEIGHT:
  5930. val = sd->max_weight;
  5931. break;
  5932. case SP_BASEEXP:
  5933. val = sd->status.base_exp;
  5934. break;
  5935. case SP_JOBEXP:
  5936. val = sd->status.job_exp;
  5937. break;
  5938. case SP_NEXTBASEEXP:
  5939. val = pc_nextbaseexp (sd);
  5940. break;
  5941. case SP_NEXTJOBEXP:
  5942. val = pc_nextjobexp (sd);
  5943. break;
  5944. case SP_HP:
  5945. val = sd->status.hp;
  5946. break;
  5947. case SP_MAXHP:
  5948. val = sd->status.max_hp;
  5949. break;
  5950. case SP_SP:
  5951. val = sd->status.sp;
  5952. break;
  5953. case SP_MAXSP:
  5954. val = sd->status.max_sp;
  5955. break;
  5956. case SP_STR:
  5957. val = sd->status.str;
  5958. break;
  5959. case SP_AGI:
  5960. val = sd->status.agi;
  5961. break;
  5962. case SP_VIT:
  5963. val = sd->status.vit;
  5964. break;
  5965. case SP_INT:
  5966. val = sd->status.int_;
  5967. break;
  5968. case SP_DEX:
  5969. val = sd->status.dex;
  5970. break;
  5971. case SP_LUK:
  5972. val = sd->status.luk;
  5973. break;
  5974. case SP_FAME:
  5975. val = sd->fame;
  5976. break;
  5977. default:
  5978. break;
  5979. }
  5980. return val;
  5981. }
  5982. /*==========================================
  5983. * script用PCステータス設定
  5984. *------------------------------------------
  5985. */
  5986. int pc_setparam (struct map_session_data *sd, int type, int val)
  5987. {
  5988. int i = 0, up_level = 50;
  5989. struct pc_base_job s_class;
  5990. nullpo_retr (0, sd);
  5991. s_class = pc_calc_base_job (sd->status.class);
  5992. switch (type)
  5993. {
  5994. case SP_BASELEVEL:
  5995. if (val > sd->status.base_level)
  5996. {
  5997. for (i = 1; i <= (val - sd->status.base_level); i++)
  5998. sd->status.status_point +=
  5999. (sd->status.base_level + i + 14) / 4;
  6000. }
  6001. sd->status.base_level = val;
  6002. sd->status.base_exp = 0;
  6003. clif_updatestatus (sd, SP_BASELEVEL);
  6004. clif_updatestatus (sd, SP_NEXTBASEEXP);
  6005. clif_updatestatus (sd, SP_STATUSPOINT);
  6006. clif_updatestatus (sd, SP_BASEEXP);
  6007. pc_calcstatus (sd, 0);
  6008. pc_heal (sd, sd->status.max_hp, sd->status.max_sp);
  6009. break;
  6010. case SP_JOBLEVEL:
  6011. if (sd->status.class <= MAX_PLAYER_CLASS)
  6012. up_level -= 40;
  6013. if ((sd->status.class == 23)
  6014. || (sd->status.class >= 4001 && sd->status.class <= 4022))
  6015. up_level += 20;
  6016. if (val >= sd->status.job_level)
  6017. {
  6018. if (val > up_level)
  6019. val = up_level;
  6020. sd->status.skill_point += (val - sd->status.job_level);
  6021. sd->status.job_level = val;
  6022. sd->status.job_exp = 0;
  6023. clif_updatestatus (sd, SP_JOBLEVEL);
  6024. clif_updatestatus (sd, SP_NEXTJOBEXP);
  6025. clif_updatestatus (sd, SP_JOBEXP);
  6026. clif_updatestatus (sd, SP_SKILLPOINT);
  6027. pc_calcstatus (sd, 0);
  6028. clif_misceffect (&sd->bl, 1);
  6029. }
  6030. else
  6031. {
  6032. sd->status.job_level = val;
  6033. sd->status.job_exp = 0;
  6034. clif_updatestatus (sd, SP_JOBLEVEL);
  6035. clif_updatestatus (sd, SP_NEXTJOBEXP);
  6036. clif_updatestatus (sd, SP_JOBEXP);
  6037. pc_calcstatus (sd, 0);
  6038. }
  6039. clif_updatestatus (sd, type);
  6040. break;
  6041. case SP_SKILLPOINT:
  6042. sd->status.skill_point = val;
  6043. break;
  6044. case SP_STATUSPOINT:
  6045. sd->status.status_point = val;
  6046. break;
  6047. case SP_ZENY:
  6048. sd->status.zeny = val;
  6049. break;
  6050. case SP_BASEEXP:
  6051. if (pc_nextbaseexp (sd) > 0)
  6052. {
  6053. sd->status.base_exp = val;
  6054. if (sd->status.base_exp < 0)
  6055. sd->status.base_exp = 0;
  6056. pc_checkbaselevelup (sd);
  6057. }
  6058. break;
  6059. case SP_JOBEXP:
  6060. if (pc_nextjobexp (sd) > 0)
  6061. {
  6062. sd->status.job_exp = val;
  6063. if (sd->status.job_exp < 0)
  6064. sd->status.job_exp = 0;
  6065. pc_checkjoblevelup (sd);
  6066. }
  6067. break;
  6068. case SP_SEX:
  6069. sd->sex = val;
  6070. break;
  6071. case SP_WEIGHT:
  6072. sd->weight = val;
  6073. break;
  6074. case SP_MAXWEIGHT:
  6075. sd->max_weight = val;
  6076. break;
  6077. case SP_HP:
  6078. sd->status.hp = val;
  6079. break;
  6080. case SP_MAXHP:
  6081. sd->status.max_hp = val;
  6082. break;
  6083. case SP_SP:
  6084. sd->status.sp = val;
  6085. break;
  6086. case SP_MAXSP:
  6087. sd->status.max_sp = val;
  6088. break;
  6089. case SP_STR:
  6090. sd->status.str = val;
  6091. break;
  6092. case SP_AGI:
  6093. sd->status.agi = val;
  6094. break;
  6095. case SP_VIT:
  6096. sd->status.vit = val;
  6097. break;
  6098. case SP_INT:
  6099. sd->status.int_ = val;
  6100. break;
  6101. case SP_DEX:
  6102. sd->status.dex = val;
  6103. break;
  6104. case SP_LUK:
  6105. sd->status.luk = val;
  6106. break;
  6107. case SP_FAME:
  6108. sd->fame = val;
  6109. break;
  6110. default:
  6111. break;
  6112. }
  6113. clif_updatestatus (sd, type);
  6114. return 0;
  6115. }
  6116. /*==========================================
  6117. * HP/SP回復
  6118. *------------------------------------------
  6119. */
  6120. int pc_heal (struct map_session_data *sd, int hp, int sp)
  6121. {
  6122. // if(battle_config.battle_log)
  6123. // printf("heal %d %d\n",hp,sp);
  6124. nullpo_retr (0, sd);
  6125. if (pc_checkoverhp (sd))
  6126. {
  6127. if (hp > 0)
  6128. hp = 0;
  6129. }
  6130. if (pc_checkoversp (sd))
  6131. {
  6132. if (sp > 0)
  6133. sp = 0;
  6134. }
  6135. if (sd->sc_data && sd->sc_data[SC_BERSERK].timer != -1) //バーサーク中は回復させないらしい
  6136. return 0;
  6137. if (hp + sd->status.hp > sd->status.max_hp)
  6138. hp = sd->status.max_hp - sd->status.hp;
  6139. if (sp + sd->status.sp > sd->status.max_sp)
  6140. sp = sd->status.max_sp - sd->status.sp;
  6141. sd->status.hp += hp;
  6142. if (sd->status.hp <= 0)
  6143. {
  6144. sd->status.hp = 0;
  6145. pc_damage (NULL, sd, 1);
  6146. hp = 0;
  6147. }
  6148. sd->status.sp += sp;
  6149. if (sd->status.sp <= 0)
  6150. sd->status.sp = 0;
  6151. if (hp)
  6152. clif_updatestatus (sd, SP_HP);
  6153. if (sp)
  6154. clif_updatestatus (sd, SP_SP);
  6155. if (sd->status.party_id > 0)
  6156. { // on-the-fly party hp updates [Valaris]
  6157. struct party *p = party_search (sd->status.party_id);
  6158. if (p != NULL)
  6159. clif_party_hp (p, sd);
  6160. } // end addition [Valaris]
  6161. return hp + sp;
  6162. }
  6163. /*==========================================
  6164. * HP/SP回復
  6165. *------------------------------------------
  6166. */
  6167. static int pc_itemheal_effect (struct map_session_data *sd, int hp, int sp);
  6168. static int // Compute how quickly we regenerate (less is faster) for that amount
  6169. pc_heal_quick_speed (int amount)
  6170. {
  6171. if (amount >= 100)
  6172. {
  6173. if (amount >= 500)
  6174. return 0;
  6175. if (amount >= 250)
  6176. return 1;
  6177. return 2;
  6178. }
  6179. else
  6180. { // < 100
  6181. if (amount >= 50)
  6182. return 3;
  6183. if (amount >= 20)
  6184. return 4;
  6185. return 5;
  6186. }
  6187. }
  6188. static void
  6189. pc_heal_quick_accumulate (int new_amount,
  6190. struct quick_regeneration *quick_regen, int max)
  6191. {
  6192. if (!quick_regen)
  6193. return;
  6194. int current_amount = quick_regen->amount;
  6195. int current_speed = quick_regen->speed;
  6196. if (current_amount + new_amount == 0)
  6197. return;
  6198. int new_speed = pc_heal_quick_speed (new_amount);
  6199. int average_speed = 1;
  6200. if (current_amount != new_amount)
  6201. average_speed = ((new_speed * new_amount) + (current_speed * current_amount)) / (current_amount + new_amount); // new_amount > 0, current_amount >= 0
  6202. quick_regen->speed = average_speed;
  6203. quick_regen->amount = MIN (current_amount + new_amount, max);
  6204. quick_regen->tickdelay = MIN (quick_regen->speed, quick_regen->tickdelay);
  6205. }
  6206. int pc_itemheal (struct map_session_data *sd, int hp, int sp)
  6207. {
  6208. nullpo_retr (0, sd);
  6209. /* defer healing */
  6210. if (hp > 0)
  6211. {
  6212. pc_heal_quick_accumulate (hp,
  6213. &sd->quick_regeneration_hp,
  6214. sd->status.max_hp - sd->status.hp);
  6215. hp = 0;
  6216. }
  6217. if (sp > 0)
  6218. {
  6219. pc_heal_quick_accumulate (sp,
  6220. &sd->quick_regeneration_sp,
  6221. sd->status.max_sp - sd->status.sp);
  6222. sp = 0;
  6223. }
  6224. /* Hurt right away, if necessary */
  6225. if (hp < 0 || sp < 0)
  6226. pc_itemheal_effect (sd, hp, sp);
  6227. return 0;
  6228. }
  6229. /* pc_itemheal_effect is invoked once every 0.5s whenever the pc
  6230. * has health recovery queued up (cf. pc_natural_heal_sub).
  6231. */
  6232. static int pc_itemheal_effect (struct map_session_data *sd, int hp, int sp)
  6233. {
  6234. int bonus;
  6235. // if(battle_config.battle_log)
  6236. // printf("heal %d %d\n",hp,sp);
  6237. nullpo_retr (0, sd);
  6238. if (sd->sc_data && sd->sc_data[SC_GOSPEL].timer != -1) //バーサーク中は回復させないらしい
  6239. return 0;
  6240. if (sd->state.potionpitcher_flag)
  6241. {
  6242. sd->potion_hp = hp;
  6243. sd->potion_sp = sp;
  6244. return 0;
  6245. }
  6246. if (pc_checkoverhp (sd))
  6247. {
  6248. if (hp > 0)
  6249. hp = 0;
  6250. }
  6251. if (pc_checkoversp (sd))
  6252. {
  6253. if (sp > 0)
  6254. sp = 0;
  6255. }
  6256. if (hp > 0)
  6257. {
  6258. bonus =
  6259. (sd->paramc[2] << 1) + 100 + pc_checkskill (sd, SM_RECOVERY) * 10;
  6260. if (bonus != 100)
  6261. hp = hp * bonus / 100;
  6262. bonus = 100 + pc_checkskill (sd, AM_LEARNINGPOTION) * 5;
  6263. if (bonus != 100)
  6264. hp = hp * bonus / 100;
  6265. }
  6266. if (sp > 0)
  6267. {
  6268. bonus =
  6269. (sd->paramc[3] << 1) + 100 + pc_checkskill (sd,
  6270. MG_SRECOVERY) * 10;
  6271. if (bonus != 100)
  6272. sp = sp * bonus / 100;
  6273. bonus = 100 + pc_checkskill (sd, AM_LEARNINGPOTION) * 5;
  6274. if (bonus != 100)
  6275. sp = sp * bonus / 100;
  6276. }
  6277. if (hp + sd->status.hp > sd->status.max_hp)
  6278. hp = sd->status.max_hp - sd->status.hp;
  6279. if (sp + sd->status.sp > sd->status.max_sp)
  6280. sp = sd->status.max_sp - sd->status.sp;
  6281. sd->status.hp += hp;
  6282. if (sd->status.hp <= 0)
  6283. {
  6284. sd->status.hp = 0;
  6285. pc_damage (NULL, sd, 1);
  6286. hp = 0;
  6287. }
  6288. sd->status.sp += sp;
  6289. if (sd->status.sp <= 0)
  6290. sd->status.sp = 0;
  6291. if (hp)
  6292. clif_updatestatus (sd, SP_HP);
  6293. if (sp)
  6294. clif_updatestatus (sd, SP_SP);
  6295. return 0;
  6296. }
  6297. /*==========================================
  6298. * HP/SP回復
  6299. *------------------------------------------
  6300. */
  6301. int pc_percentheal (struct map_session_data *sd, int hp, int sp)
  6302. {
  6303. nullpo_retr (0, sd);
  6304. if (sd->state.potionpitcher_flag)
  6305. {
  6306. sd->potion_per_hp = hp;
  6307. sd->potion_per_sp = sp;
  6308. return 0;
  6309. }
  6310. if (pc_checkoverhp (sd))
  6311. {
  6312. if (hp > 0)
  6313. hp = 0;
  6314. }
  6315. if (pc_checkoversp (sd))
  6316. {
  6317. if (sp > 0)
  6318. sp = 0;
  6319. }
  6320. if (hp)
  6321. {
  6322. if (hp >= 100)
  6323. {
  6324. sd->status.hp = sd->status.max_hp;
  6325. }
  6326. else if (hp <= -100)
  6327. {
  6328. sd->status.hp = 0;
  6329. pc_damage (NULL, sd, 1);
  6330. }
  6331. else
  6332. {
  6333. sd->status.hp += sd->status.max_hp * hp / 100;
  6334. if (sd->status.hp > sd->status.max_hp)
  6335. sd->status.hp = sd->status.max_hp;
  6336. if (sd->status.hp <= 0)
  6337. {
  6338. sd->status.hp = 0;
  6339. pc_damage (NULL, sd, 1);
  6340. hp = 0;
  6341. }
  6342. }
  6343. }
  6344. if (sp)
  6345. {
  6346. if (sp >= 100)
  6347. {
  6348. sd->status.sp = sd->status.max_sp;
  6349. }
  6350. else if (sp <= -100)
  6351. {
  6352. sd->status.sp = 0;
  6353. }
  6354. else
  6355. {
  6356. sd->status.sp += sd->status.max_sp * sp / 100;
  6357. if (sd->status.sp > sd->status.max_sp)
  6358. sd->status.sp = sd->status.max_sp;
  6359. if (sd->status.sp < 0)
  6360. sd->status.sp = 0;
  6361. }
  6362. }
  6363. if (hp)
  6364. clif_updatestatus (sd, SP_HP);
  6365. if (sp)
  6366. clif_updatestatus (sd, SP_SP);
  6367. return 0;
  6368. }
  6369. /*==========================================
  6370. * 職変更
  6371. * 引数 job 職業 0〜23
  6372. * upper 通常 0, 転生 1, 養子 2, そのまま -1
  6373. *------------------------------------------
  6374. */
  6375. int pc_jobchange (struct map_session_data *sd, int job, int upper)
  6376. {
  6377. nullpo_retr (0, sd);
  6378. int i;
  6379. int b_class = 0;
  6380. //転生や養子の場合の元の職業を算出する
  6381. struct pc_base_job s_class = pc_calc_base_job (sd->status.class);
  6382. if ((job > 23) && (job < 68))
  6383. job += 3977;
  6384. if ((job > 69) && (job < 4000))
  6385. return 1;
  6386. if (upper < 0) //現在転生かどうかを判断する
  6387. upper = s_class.upper;
  6388. if (upper == 0)
  6389. { //通常職ならjobそのまんま
  6390. b_class = job;
  6391. }
  6392. else if (upper == 1)
  6393. {
  6394. if (job == 23)
  6395. { //転生にスパノビは存在しないのでお断り
  6396. return 1;
  6397. }
  6398. else
  6399. {
  6400. b_class = job + 4001;
  6401. }
  6402. }
  6403. else if (upper == 2)
  6404. { //養子に結婚はないけどどうせ次で蹴られるからいいや
  6405. b_class = (job == 23) ? job + 4022 : job + 4023;
  6406. }
  6407. else
  6408. {
  6409. return 1;
  6410. }
  6411. if ((sd->status.sex == 0 && job == 19) || (sd->status.sex == 1 && job == 20) || (sd->status.sex == 0 && job == 4020) || (sd->status.sex == 1 && job == 4021) || job == 22 || sd->status.class == b_class) //♀はバードになれない、♂はダンサーになれない、結婚衣裳もお断り
  6412. return 1;
  6413. sd->status.class = sd->view_class = b_class;
  6414. sd->status.job_level = 1;
  6415. sd->status.job_exp = 0;
  6416. clif_updatestatus (sd, SP_JOBLEVEL);
  6417. clif_updatestatus (sd, SP_JOBEXP);
  6418. clif_updatestatus (sd, SP_NEXTJOBEXP);
  6419. for (i = 0; i < MAX_EQUIP_SIZE; i++)
  6420. {
  6421. if (sd->equip_index[i] >= 0)
  6422. if (!pc_isequip (sd, sd->equip_index[i]))
  6423. pc_unequipitem (sd, sd->equip_index[i], 1); // 装備外し
  6424. }
  6425. clif_changelook (&sd->bl, LOOK_BASE, sd->view_class); // move sprite update to prevent client crashes with incompatible equipment [Valaris]
  6426. if (sd->status.clothes_color > 0)
  6427. clif_changelook (&sd->bl, LOOK_CLOTHES_COLOR,
  6428. sd->status.clothes_color);
  6429. if (battle_config.muting_players && sd->status.manner < 0)
  6430. clif_changestatus (&sd->bl, SP_MANNER, sd->status.manner);
  6431. pc_calcstatus (sd, 0);
  6432. pc_checkallowskill (sd);
  6433. pc_equiplookall (sd);
  6434. clif_equiplist (sd);
  6435. if (pc_isriding (sd))
  6436. { // remove peco status if changing into invalid class [Valaris]
  6437. if (!(pc_checkskill (sd, KN_RIDING)))
  6438. pc_setoption (sd, sd->status.option | -0x0000);
  6439. if (pc_checkskill (sd, KN_RIDING) > 0)
  6440. pc_setriding (sd);
  6441. }
  6442. return 0;
  6443. }
  6444. /*==========================================
  6445. * 見た目変更
  6446. *------------------------------------------
  6447. */
  6448. int pc_equiplookall (struct map_session_data *sd)
  6449. {
  6450. nullpo_retr (0, sd);
  6451. clif_changelook (&sd->bl, LOOK_WEAPON, 0);
  6452. // clif_changelook(&sd->bl,LOOK_SHOES,0);
  6453. clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM, sd->status.head_bottom);
  6454. clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
  6455. clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
  6456. clif_changelook_accessories (&sd->bl, NULL);
  6457. return 0;
  6458. }
  6459. /*==========================================
  6460. * 見た目変更
  6461. *------------------------------------------
  6462. */
  6463. int pc_changelook (struct map_session_data *sd, int type, int val)
  6464. {
  6465. nullpo_retr (0, sd);
  6466. switch (type)
  6467. {
  6468. case LOOK_HAIR:
  6469. sd->status.hair = val;
  6470. break;
  6471. case LOOK_WEAPON:
  6472. sd->status.weapon = val;
  6473. break;
  6474. case LOOK_HEAD_BOTTOM:
  6475. sd->status.head_bottom = val;
  6476. break;
  6477. case LOOK_HEAD_TOP:
  6478. sd->status.head_top = val;
  6479. break;
  6480. case LOOK_HEAD_MID:
  6481. sd->status.head_mid = val;
  6482. break;
  6483. case LOOK_HAIR_COLOR:
  6484. sd->status.hair_color = val;
  6485. break;
  6486. case LOOK_CLOTHES_COLOR:
  6487. sd->status.clothes_color = val;
  6488. break;
  6489. case LOOK_SHIELD:
  6490. sd->status.shield = val;
  6491. break;
  6492. case LOOK_SHOES:
  6493. break;
  6494. default:
  6495. break;
  6496. }
  6497. clif_changelook (&sd->bl, type, val);
  6498. return 0;
  6499. }
  6500. /*==========================================
  6501. * 付属品(鷹,ペコ,カート)設定
  6502. *------------------------------------------
  6503. */
  6504. int pc_setoption (struct map_session_data *sd, int type)
  6505. {
  6506. nullpo_retr (0, sd);
  6507. sd->status.option = type;
  6508. clif_changeoption (&sd->bl);
  6509. pc_calcstatus (sd, 0);
  6510. return 0;
  6511. }
  6512. /*==========================================
  6513. * カート設定
  6514. *------------------------------------------
  6515. */
  6516. int pc_setcart (struct map_session_data *sd, int type)
  6517. {
  6518. int cart[6] = { 0x0000, 0x0008, 0x0080, 0x0100, 0x0200, 0x0400 };
  6519. nullpo_retr (0, sd);
  6520. if (type < 0 || type >= 6)
  6521. return 0;
  6522. if (pc_checkskill (sd, MC_PUSHCART) > 0)
  6523. { // プッシュカートスキル所持
  6524. if (!pc_iscarton (sd))
  6525. { // カートを付けていない
  6526. pc_setoption (sd, cart[type]);
  6527. clif_cart_itemlist (sd);
  6528. clif_cart_equiplist (sd);
  6529. clif_updatestatus (sd, SP_CARTINFO);
  6530. clif_status_change (&sd->bl, 0x0c, 0);
  6531. }
  6532. else
  6533. {
  6534. pc_setoption (sd, cart[type]);
  6535. }
  6536. }
  6537. return 0;
  6538. }
  6539. /*==========================================
  6540. * 鷹設定
  6541. *------------------------------------------
  6542. */
  6543. int pc_setfalcon (struct map_session_data *sd)
  6544. {
  6545. nullpo_retr (0, sd);
  6546. if (pc_checkskill (sd, HT_FALCON) > 0)
  6547. { // ファルコンマスタリースキル所持
  6548. pc_setoption (sd, sd->status.option | 0x0010);
  6549. }
  6550. return 0;
  6551. }
  6552. /*==========================================
  6553. * ペコペコ設定
  6554. *------------------------------------------
  6555. */
  6556. int pc_setriding (struct map_session_data *sd)
  6557. {
  6558. nullpo_retr (0, sd);
  6559. if (sd->disguise > 0)
  6560. { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
  6561. clif_displaymessage (sd->fd,
  6562. "Cannot mount a Peco while in disguise.");
  6563. return 0;
  6564. }
  6565. if ((pc_checkskill (sd, KN_RIDING) > 0))
  6566. { // ライディングスキル所持
  6567. pc_setoption (sd, sd->status.option | 0x0020);
  6568. // if (sd->status.class == 7)
  6569. // sd->status.class = sd->view_class = 13;
  6570. if (sd->status.class == 14)
  6571. sd->status.class = sd->view_class = 21;
  6572. if (sd->status.class == 4008)
  6573. sd->status.class = sd->view_class = 4014;
  6574. if (sd->status.class == 4015)
  6575. sd->status.class = sd->view_class = 4022;
  6576. }
  6577. return 0;
  6578. }
  6579. /*==========================================
  6580. * script用変数の値を読む
  6581. *------------------------------------------
  6582. */
  6583. int pc_readreg (struct map_session_data *sd, int reg)
  6584. {
  6585. int i;
  6586. nullpo_retr (0, sd);
  6587. for (i = 0; i < sd->reg_num; i++)
  6588. if (sd->reg[i].index == reg)
  6589. return sd->reg[i].data;
  6590. return 0;
  6591. }
  6592. /*==========================================
  6593. * script用変数の値を設定
  6594. *------------------------------------------
  6595. */
  6596. int pc_setreg (struct map_session_data *sd, int reg, int val)
  6597. {
  6598. int i;
  6599. nullpo_retr (0, sd);
  6600. for (i = 0; i < sd->reg_num; i++)
  6601. {
  6602. if (sd->reg[i].index == reg)
  6603. {
  6604. sd->reg[i].data = val;
  6605. return 0;
  6606. }
  6607. }
  6608. sd->reg_num++;
  6609. sd->reg = realloc (sd->reg, sizeof (*(sd->reg)) * sd->reg_num);
  6610. if (sd->reg == NULL)
  6611. {
  6612. printf ("out of memory : pc_setreg\n");
  6613. exit (1);
  6614. }
  6615. /* memset(sd->reg + (sd->reg_num - 1) * sizeof(*(sd->reg)), 0,
  6616. sizeof(*(sd->reg)));
  6617. */
  6618. sd->reg[i].index = reg;
  6619. sd->reg[i].data = val;
  6620. return 0;
  6621. }
  6622. /*==========================================
  6623. * script用文字列変数の値を読む
  6624. *------------------------------------------
  6625. */
  6626. char *pc_readregstr (struct map_session_data *sd, int reg)
  6627. {
  6628. int i;
  6629. nullpo_retr (0, sd);
  6630. for (i = 0; i < sd->regstr_num; i++)
  6631. if (sd->regstr[i].index == reg)
  6632. return sd->regstr[i].data;
  6633. return NULL;
  6634. }
  6635. /*==========================================
  6636. * script用文字列変数の値を設定
  6637. *------------------------------------------
  6638. */
  6639. int pc_setregstr (struct map_session_data *sd, int reg, char *str)
  6640. {
  6641. int i;
  6642. nullpo_retr (0, sd);
  6643. nullpo_retr (0, str);
  6644. if (strlen (str) + 1 > sizeof (sd->regstr[0].data))
  6645. {
  6646. printf ("pc_setregstr(): String too long!\n");
  6647. return 0;
  6648. }
  6649. for (i = 0; i < sd->regstr_num; i++)
  6650. if (sd->regstr[i].index == reg)
  6651. {
  6652. strcpy (sd->regstr[i].data, str);
  6653. return 0;
  6654. }
  6655. sd->regstr_num++;
  6656. str = aStrdup (str);
  6657. sd->regstr =
  6658. realloc (sd->regstr, sizeof (sd->regstr[0]) * sd->regstr_num);
  6659. if (sd->regstr == NULL)
  6660. {
  6661. printf ("out of memory : pc_setreg\n");
  6662. exit (1);
  6663. }
  6664. /* memset(sd->reg + (sd->reg_num - 1) * sizeof(*(sd->reg)), 0,
  6665. sizeof(*(sd->reg)));
  6666. */
  6667. sd->regstr[i].index = reg;
  6668. strcpy (sd->regstr[i].data, str);
  6669. aFree (str);
  6670. return 0;
  6671. }
  6672. /*==========================================
  6673. * script用グローバル変数の値を読む
  6674. *------------------------------------------
  6675. */
  6676. int pc_readglobalreg (struct map_session_data *sd, char *reg)
  6677. {
  6678. int i;
  6679. nullpo_retr (0, sd);
  6680. nullpo_retr (0, reg);
  6681. for (i = 0; i < sd->status.global_reg_num; i++)
  6682. {
  6683. if (strcmp (sd->status.global_reg[i].str, reg) == 0)
  6684. return sd->status.global_reg[i].value;
  6685. }
  6686. return 0;
  6687. }
  6688. /*==========================================
  6689. * script用グローバル変数の値を設定
  6690. *------------------------------------------
  6691. */
  6692. int pc_setglobalreg (struct map_session_data *sd, char *reg, int val)
  6693. {
  6694. int i;
  6695. nullpo_retr (0, sd);
  6696. nullpo_retr (0, reg);
  6697. //PC_DIE_COUNTERがスクリプトなどで変更された時の処理
  6698. if (strcmp (reg, "PC_DIE_COUNTER") == 0 && sd->die_counter != val)
  6699. {
  6700. sd->die_counter = val;
  6701. pc_calcstatus (sd, 0);
  6702. }
  6703. if (val == 0)
  6704. {
  6705. for (i = 0; i < sd->status.global_reg_num; i++)
  6706. {
  6707. if (strcmp (sd->status.global_reg[i].str, reg) == 0)
  6708. {
  6709. sd->status.global_reg[i] =
  6710. sd->status.global_reg[sd->status.global_reg_num - 1];
  6711. sd->status.global_reg_num--;
  6712. break;
  6713. }
  6714. }
  6715. return 0;
  6716. }
  6717. for (i = 0; i < sd->status.global_reg_num; i++)
  6718. {
  6719. if (strcmp (sd->status.global_reg[i].str, reg) == 0)
  6720. {
  6721. sd->status.global_reg[i].value = val;
  6722. return 0;
  6723. }
  6724. }
  6725. if (sd->status.global_reg_num < GLOBAL_REG_NUM)
  6726. {
  6727. strcpy (sd->status.global_reg[i].str, reg);
  6728. sd->status.global_reg[i].value = val;
  6729. sd->status.global_reg_num++;
  6730. return 0;
  6731. }
  6732. if (battle_config.error_log)
  6733. printf ("pc_setglobalreg : couldn't set %s (GLOBAL_REG_NUM = %d)\n",
  6734. reg, GLOBAL_REG_NUM);
  6735. return 1;
  6736. }
  6737. /*==========================================
  6738. * script用アカウント変数の値を読む
  6739. *------------------------------------------
  6740. */
  6741. int pc_readaccountreg (struct map_session_data *sd, char *reg)
  6742. {
  6743. int i;
  6744. nullpo_retr (0, sd);
  6745. nullpo_retr (0, reg);
  6746. for (i = 0; i < sd->status.account_reg_num; i++)
  6747. {
  6748. if (strcmp (sd->status.account_reg[i].str, reg) == 0)
  6749. return sd->status.account_reg[i].value;
  6750. }
  6751. return 0;
  6752. }
  6753. /*==========================================
  6754. * script用アカウント変数の値を設定
  6755. *------------------------------------------
  6756. */
  6757. int pc_setaccountreg (struct map_session_data *sd, char *reg, int val)
  6758. {
  6759. int i;
  6760. nullpo_retr (0, sd);
  6761. nullpo_retr (0, reg);
  6762. if (val == 0)
  6763. {
  6764. for (i = 0; i < sd->status.account_reg_num; i++)
  6765. {
  6766. if (strcmp (sd->status.account_reg[i].str, reg) == 0)
  6767. {
  6768. sd->status.account_reg[i] =
  6769. sd->status.account_reg[sd->status.account_reg_num - 1];
  6770. sd->status.account_reg_num--;
  6771. break;
  6772. }
  6773. }
  6774. intif_saveaccountreg (sd);
  6775. return 0;
  6776. }
  6777. for (i = 0; i < sd->status.account_reg_num; i++)
  6778. {
  6779. if (strcmp (sd->status.account_reg[i].str, reg) == 0)
  6780. {
  6781. sd->status.account_reg[i].value = val;
  6782. intif_saveaccountreg (sd);
  6783. return 0;
  6784. }
  6785. }
  6786. if (sd->status.account_reg_num < ACCOUNT_REG_NUM)
  6787. {
  6788. strcpy (sd->status.account_reg[i].str, reg);
  6789. sd->status.account_reg[i].value = val;
  6790. sd->status.account_reg_num++;
  6791. intif_saveaccountreg (sd);
  6792. return 0;
  6793. }
  6794. if (battle_config.error_log)
  6795. printf ("pc_setaccountreg : couldn't set %s (ACCOUNT_REG_NUM = %d)\n",
  6796. reg, ACCOUNT_REG_NUM);
  6797. return 1;
  6798. }
  6799. /*==========================================
  6800. * script用アカウント変数2の値を読む
  6801. *------------------------------------------
  6802. */
  6803. int pc_readaccountreg2 (struct map_session_data *sd, char *reg)
  6804. {
  6805. int i;
  6806. nullpo_retr (0, sd);
  6807. nullpo_retr (0, reg);
  6808. for (i = 0; i < sd->status.account_reg2_num; i++)
  6809. {
  6810. if (strcmp (sd->status.account_reg2[i].str, reg) == 0)
  6811. return sd->status.account_reg2[i].value;
  6812. }
  6813. return 0;
  6814. }
  6815. /*==========================================
  6816. * script用アカウント変数2の値を設定
  6817. *------------------------------------------
  6818. */
  6819. int pc_setaccountreg2 (struct map_session_data *sd, char *reg, int val)
  6820. {
  6821. int i;
  6822. nullpo_retr (1, sd);
  6823. nullpo_retr (1, reg);
  6824. if (val == 0)
  6825. {
  6826. for (i = 0; i < sd->status.account_reg2_num; i++)
  6827. {
  6828. if (strcmp (sd->status.account_reg2[i].str, reg) == 0)
  6829. {
  6830. sd->status.account_reg2[i] =
  6831. sd->status.account_reg2[sd->status.account_reg2_num - 1];
  6832. sd->status.account_reg2_num--;
  6833. break;
  6834. }
  6835. }
  6836. chrif_saveaccountreg2 (sd);
  6837. return 0;
  6838. }
  6839. for (i = 0; i < sd->status.account_reg2_num; i++)
  6840. {
  6841. if (strcmp (sd->status.account_reg2[i].str, reg) == 0)
  6842. {
  6843. sd->status.account_reg2[i].value = val;
  6844. chrif_saveaccountreg2 (sd);
  6845. return 0;
  6846. }
  6847. }
  6848. if (sd->status.account_reg2_num < ACCOUNT_REG2_NUM)
  6849. {
  6850. strcpy (sd->status.account_reg2[i].str, reg);
  6851. sd->status.account_reg2[i].value = val;
  6852. sd->status.account_reg2_num++;
  6853. chrif_saveaccountreg2 (sd);
  6854. return 0;
  6855. }
  6856. if (battle_config.error_log)
  6857. printf
  6858. ("pc_setaccountreg2 : couldn't set %s (ACCOUNT_REG2_NUM = %d)\n",
  6859. reg, ACCOUNT_REG2_NUM);
  6860. return 1;
  6861. }
  6862. /*==========================================
  6863. * 精錬成功率
  6864. *------------------------------------------
  6865. */
  6866. int pc_percentrefinery (struct map_session_data *sd, struct item *item)
  6867. {
  6868. int percent;
  6869. nullpo_retr (0, item);
  6870. //++++ need check itemdb_wlv (item->nameid)?
  6871. percent = percentrefinery[itemdb_wlv (item->nameid)][(int) item->refine];
  6872. percent += pc_checkskill (sd, BS_WEAPONRESEARCH); // 武器研究スキル所持
  6873. // 確率の有効範囲チェック
  6874. if (percent > 100)
  6875. {
  6876. percent = 100;
  6877. }
  6878. else if (percent < 0)
  6879. {
  6880. percent = 0;
  6881. }
  6882. return percent;
  6883. }
  6884. /*==========================================
  6885. * イベントタイマー処理
  6886. *------------------------------------------
  6887. */
  6888. int pc_eventtimer (int tid, unsigned int tick __attribute__ ((unused)), int id, int data)
  6889. {
  6890. struct map_session_data *sd = map_id2sd (id);
  6891. int i;
  6892. if (sd == NULL)
  6893. return 0;
  6894. for (i = 0; i < MAX_EVENTTIMER; i++)
  6895. {
  6896. if (sd->eventtimer[i] == tid)
  6897. {
  6898. sd->eventtimer[i] = -1;
  6899. npc_event (sd, (const char *) data, 0);
  6900. break;
  6901. }
  6902. }
  6903. free ((void *) data);
  6904. if (i == MAX_EVENTTIMER)
  6905. {
  6906. if (battle_config.error_log)
  6907. printf ("pc_eventtimer: no such event timer\n");
  6908. }
  6909. return 0;
  6910. }
  6911. /*==========================================
  6912. * イベントタイマー追加
  6913. *------------------------------------------
  6914. */
  6915. int pc_addeventtimer (struct map_session_data *sd, int tick, const char *name)
  6916. {
  6917. int i;
  6918. nullpo_retr (0, sd);
  6919. for (i = 0; i < MAX_EVENTTIMER; i++)
  6920. if (sd->eventtimer[i] == -1)
  6921. break;
  6922. if (i < MAX_EVENTTIMER)
  6923. {
  6924. char *evname = (char *) aCalloc (24, sizeof (char));
  6925. safestrncpy (evname, name, 24);
  6926. sd->eventtimer[i] = add_timer (gettick () + tick,
  6927. pc_eventtimer, sd->bl.id,
  6928. (int) evname);
  6929. return 1;
  6930. }
  6931. return 0;
  6932. }
  6933. /*==========================================
  6934. * イベントタイマー削除
  6935. *------------------------------------------
  6936. */
  6937. int pc_deleventtimer (struct map_session_data *sd, const char *name)
  6938. {
  6939. int i;
  6940. nullpo_retr (0, sd);
  6941. nullpo_retr (0, name);
  6942. for (i = 0; i < MAX_EVENTTIMER; i++)
  6943. if (sd->eventtimer[i] != -1 && strcmp ((char
  6944. *) (get_timer (sd->eventtimer
  6945. [i])->data),
  6946. name) == 0)
  6947. {
  6948. delete_timer (sd->eventtimer[i], pc_eventtimer);
  6949. sd->eventtimer[i] = -1;
  6950. break;
  6951. }
  6952. return 0;
  6953. }
  6954. /*==========================================
  6955. * イベントタイマーカウント値追加
  6956. *------------------------------------------
  6957. */
  6958. int pc_addeventtimercount (struct map_session_data *sd, const char *name,
  6959. int tick)
  6960. {
  6961. int i;
  6962. nullpo_retr (0, sd);
  6963. nullpo_retr (0, name);
  6964. for (i = 0; i < MAX_EVENTTIMER; i++)
  6965. if (sd->eventtimer[i] != -1 && strcmp ((char
  6966. *) (get_timer (sd->eventtimer
  6967. [i])->data),
  6968. name) == 0)
  6969. {
  6970. addtick_timer (sd->eventtimer[i], tick);
  6971. break;
  6972. }
  6973. return 0;
  6974. }
  6975. /*==========================================
  6976. * イベントタイマー全削除
  6977. *------------------------------------------
  6978. */
  6979. int pc_cleareventtimer (struct map_session_data *sd)
  6980. {
  6981. int i;
  6982. nullpo_retr (0, sd);
  6983. for (i = 0; i < MAX_EVENTTIMER; i++)
  6984. if (sd->eventtimer[i] != -1)
  6985. {
  6986. delete_timer (sd->eventtimer[i], pc_eventtimer);
  6987. sd->eventtimer[i] = -1;
  6988. }
  6989. return 0;
  6990. }
  6991. //
  6992. // 装 備物
  6993. //
  6994. /*==========================================
  6995. * アイテムを装備する
  6996. *------------------------------------------
  6997. */
  6998. static int
  6999. pc_signal_advanced_equipment_change (struct map_session_data *sd, int n)
  7000. {
  7001. nullpo_retr (0, sd);
  7002. if (n < 0 || n >= MAX_INVENTORY)
  7003. return 0;
  7004. if (sd->status.inventory[n].equip & 0x0040)
  7005. clif_changelook (&sd->bl, LOOK_SHOES, 0);
  7006. if (sd->status.inventory[n].equip & 0x0004)
  7007. clif_changelook (&sd->bl, LOOK_GLOVES, 0);
  7008. if (sd->status.inventory[n].equip & 0x0008)
  7009. clif_changelook (&sd->bl, LOOK_CAPE, 0);
  7010. if (sd->status.inventory[n].equip & 0x0010)
  7011. clif_changelook (&sd->bl, LOOK_MISC1, 0);
  7012. if (sd->status.inventory[n].equip & 0x0080)
  7013. clif_changelook (&sd->bl, LOOK_MISC2, 0);
  7014. return 0;
  7015. }
  7016. int pc_equipitem (struct map_session_data *sd, int n, int pos)
  7017. {
  7018. int i, nameid, arrow, view;
  7019. struct item_data *id;
  7020. //転生や養子の場合の元の職業を算出する
  7021. nullpo_retr (0, sd);
  7022. if (n < 0 || n >= MAX_INVENTORY)
  7023. {
  7024. clif_equipitemack (sd, 0, 0, 0);
  7025. return 0;
  7026. }
  7027. nameid = sd->status.inventory[n].nameid;
  7028. id = sd->inventory_data[n];
  7029. pos = pc_equippoint (sd, n);
  7030. if (battle_config.battle_log)
  7031. printf ("equip %d(%d) %x:%x\n", nameid, n, id->equip, pos);
  7032. if (!pc_isequip (sd, n) || !pos || sd->status.inventory[n].broken == 1)
  7033. { // [Valaris]
  7034. clif_equipitemack (sd, n, 0, 0); // fail
  7035. return 0;
  7036. }
  7037. // -- moonsoul (if player is berserk then cannot equip)
  7038. //
  7039. if (sd->sc_data[SC_BERSERK].timer != -1)
  7040. {
  7041. clif_equipitemack (sd, n, 0, 0); // fail
  7042. return 0;
  7043. }
  7044. if (pos == 0x88)
  7045. { // アクセサリ用例外処理
  7046. int epor = 0;
  7047. if (sd->equip_index[0] >= 0)
  7048. epor |= sd->status.inventory[sd->equip_index[0]].equip;
  7049. if (sd->equip_index[1] >= 0)
  7050. epor |= sd->status.inventory[sd->equip_index[1]].equip;
  7051. epor &= 0x88;
  7052. pos = epor == 0x08 ? 0x80 : 0x08;
  7053. }
  7054. // 二刀流処理
  7055. if ((pos == 0x22) // 一応、装備要求箇所が二刀流武器かチェックする
  7056. && (id->equip == 2) // 単 手武器
  7057. && (pc_checkskill (sd, AS_LEFT) > 0 || sd->status.class == 12)) // 左手修錬有
  7058. {
  7059. int tpos = 0;
  7060. if (sd->equip_index[8] >= 0)
  7061. tpos |= sd->status.inventory[sd->equip_index[8]].equip;
  7062. if (sd->equip_index[9] >= 0)
  7063. tpos |= sd->status.inventory[sd->equip_index[9]].equip;
  7064. tpos &= 0x02;
  7065. pos = tpos == 0x02 ? 0x20 : 0x02;
  7066. }
  7067. arrow = pc_search_inventory (sd, pc_checkequip (sd, 9)); // Added by RoVeRT
  7068. for (i = 0; i < MAX_EQUIP_SIZE; i++)
  7069. {
  7070. if (pos & equip_pos[i])
  7071. {
  7072. if (sd->equip_index[i] >= 0) //Slot taken, remove item from there.
  7073. pc_unequipitem (sd, sd->equip_index[i], 1);
  7074. sd->equip_index[i] = n;
  7075. }
  7076. }
  7077. // 弓矢装備
  7078. if (pos == 0x8000)
  7079. {
  7080. clif_arrowequip (sd, n);
  7081. clif_arrow_fail (sd, 3); // 3=矢が装備できました
  7082. }
  7083. else
  7084. {
  7085. /* Don't update re-equipping if we're using a spell */
  7086. if (!(pos == 4 && sd->attack_spell_override))
  7087. clif_equipitemack (sd, n, pos, 1);
  7088. }
  7089. for (i = 0; i < MAX_EQUIP_SIZE; i++)
  7090. {
  7091. if (pos & equip_pos[i])
  7092. sd->equip_index[i] = n;
  7093. }
  7094. sd->status.inventory[n].equip = pos;
  7095. if (sd->inventory_data[n])
  7096. {
  7097. view = sd->inventory_data[n]->look;
  7098. if (view == 0)
  7099. view = sd->inventory_data[n]->nameid;
  7100. }
  7101. else
  7102. {
  7103. view = 0;
  7104. }
  7105. if (sd->status.inventory[n].equip & 0x0002)
  7106. {
  7107. sd->weapontype1 = view;
  7108. pc_calcweapontype (sd);
  7109. pc_set_weapon_look (sd);
  7110. }
  7111. if (sd->status.inventory[n].equip & 0x0020)
  7112. {
  7113. if (sd->inventory_data[n])
  7114. {
  7115. if (sd->inventory_data[n]->type == 4)
  7116. {
  7117. sd->status.shield = 0;
  7118. if (sd->status.inventory[n].equip == 0x0020)
  7119. sd->weapontype2 = view;
  7120. }
  7121. else if (sd->inventory_data[n]->type == 5)
  7122. {
  7123. sd->status.shield = view;
  7124. sd->weapontype2 = 0;
  7125. }
  7126. }
  7127. else
  7128. sd->status.shield = sd->weapontype2 = 0;
  7129. pc_calcweapontype (sd);
  7130. clif_changelook (&sd->bl, LOOK_SHIELD, sd->status.shield);
  7131. }
  7132. if (sd->status.inventory[n].equip & 0x0001)
  7133. {
  7134. sd->status.head_bottom = view;
  7135. clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM, sd->status.head_bottom);
  7136. }
  7137. if (sd->status.inventory[n].equip & 0x0100)
  7138. {
  7139. sd->status.head_top = view;
  7140. clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
  7141. }
  7142. if (sd->status.inventory[n].equip & 0x0200)
  7143. {
  7144. sd->status.head_mid = view;
  7145. clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
  7146. }
  7147. if (sd->status.inventory[n].equip & 0x0400)
  7148. {
  7149. clif_changelook (&sd->bl, LOOK_EVOL_RING1, view);
  7150. }
  7151. if (sd->status.inventory[n].equip & 0x0800)
  7152. {
  7153. clif_changelook (&sd->bl, LOOK_EVOL_RING2, view);
  7154. }
  7155. pc_signal_advanced_equipment_change (sd, n);
  7156. pc_checkallowskill (sd); // 装備品でスキルか解除されるかチェック
  7157. if (itemdb_look (sd->status.inventory[n].nameid) == 11 && arrow)
  7158. { // Added by RoVeRT
  7159. clif_arrowequip (sd, arrow);
  7160. sd->status.inventory[arrow].equip = 32768;
  7161. }
  7162. pc_calcstatus (sd, 0);
  7163. if (sd->special_state.infinite_endure)
  7164. {
  7165. if (sd->sc_data[SC_ENDURE].timer == -1)
  7166. skill_status_change_start (&sd->bl, SC_ENDURE, 10, 1, 0, 0, 0, 0);
  7167. }
  7168. else
  7169. {
  7170. if (sd->sc_data[SC_ENDURE].timer != -1 && sd->sc_data[SC_ENDURE].val2)
  7171. skill_status_change_end (&sd->bl, SC_ENDURE, -1);
  7172. }
  7173. if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1
  7174. && !battle_check_undead (7, sd->def_ele))
  7175. skill_status_change_end (&sd->bl, SC_SIGNUMCRUCIS, -1);
  7176. if (sd->sc_data[SC_DANCING].timer != -1
  7177. && (sd->status.weapon != 13 && sd->status.weapon != 14))
  7178. skill_stop_dancing (&sd->bl, 0);
  7179. return 0;
  7180. }
  7181. /*==========================================
  7182. * 装 備した物を外す
  7183. *------------------------------------------
  7184. */
  7185. int pc_unequipitem (struct map_session_data *sd, int n, int type)
  7186. {
  7187. nullpo_retr (0, sd);
  7188. if (n < 0 || n >= MAX_INVENTORY)
  7189. return 0;
  7190. // -- moonsoul (if player is berserk then cannot unequip)
  7191. //
  7192. if (sd->sc_data[SC_BERSERK].timer != -1)
  7193. {
  7194. clif_unequipitemack (sd, n, 0, 0);
  7195. return 0;
  7196. }
  7197. if (battle_config.battle_log)
  7198. printf ("unequip %d %x:%x\n", n, pc_equippoint (sd, n),
  7199. sd->status.inventory[n].equip);
  7200. if (sd->status.inventory[n].equip)
  7201. {
  7202. int i;
  7203. for (i = 0; i < MAX_EQUIP_SIZE; i++)
  7204. {
  7205. if (sd->status.inventory[n].equip & equip_pos[i])
  7206. sd->equip_index[i] = -1;
  7207. }
  7208. if (sd->status.inventory[n].equip & 0x0002)
  7209. {
  7210. sd->weapontype1 = 0;
  7211. sd->status.weapon = sd->weapontype2;
  7212. pc_calcweapontype (sd);
  7213. pc_set_weapon_look (sd);
  7214. }
  7215. if (sd->status.inventory[n].equip & 0x0020)
  7216. {
  7217. sd->status.shield = sd->weapontype2 = 0;
  7218. pc_calcweapontype (sd);
  7219. clif_changelook (&sd->bl, LOOK_SHIELD, sd->status.shield);
  7220. }
  7221. if (sd->status.inventory[n].equip & 0x0001)
  7222. {
  7223. sd->status.head_bottom = 0;
  7224. clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM,
  7225. sd->status.head_bottom);
  7226. }
  7227. if (sd->status.inventory[n].equip & 0x0100)
  7228. {
  7229. sd->status.head_top = 0;
  7230. clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
  7231. }
  7232. if (sd->status.inventory[n].equip & 0x0200)
  7233. {
  7234. sd->status.head_mid = 0;
  7235. clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
  7236. }
  7237. if (sd->status.inventory[n].equip & 0x0400)
  7238. {
  7239. clif_changelook (&sd->bl, LOOK_EVOL_RING1, 0);
  7240. }
  7241. if (sd->status.inventory[n].equip & 0x0800)
  7242. {
  7243. clif_changelook (&sd->bl, LOOK_EVOL_RING2, 0);
  7244. }
  7245. pc_signal_advanced_equipment_change (sd, n);
  7246. if (sd->sc_data[SC_BROKNWEAPON].timer != -1
  7247. && sd->status.inventory[n].equip & 0x0002
  7248. && sd->status.inventory[i].broken == 1)
  7249. skill_status_change_end (&sd->bl, SC_BROKNWEAPON, -1);
  7250. clif_unequipitemack (sd, n, sd->status.inventory[n].equip, 1);
  7251. sd->status.inventory[n].equip = 0;
  7252. if (!type)
  7253. pc_checkallowskill (sd);
  7254. if (sd->weapontype1 == 0 && sd->weapontype2 == 0)
  7255. skill_encchant_eremental_end (&sd->bl, -1);
  7256. }
  7257. else
  7258. {
  7259. clif_unequipitemack (sd, n, 0, 0);
  7260. }
  7261. if(sd->inventory_data[n] && sd->inventory_data[n]->unequip_script)
  7262. {
  7263. argrec_t arg[2];
  7264. arg[0].name = "@slotId";
  7265. arg[0].v.i = 0;
  7266. arg[1].name = "@itemId";
  7267. arg[1].v.i = sd->inventory_data[n]->nameid;
  7268. run_script_l (sd->inventory_data[n]->unequip_script, 0, sd->bl.id, 0, 2, arg);
  7269. }
  7270. if (!type)
  7271. {
  7272. pc_calcstatus (sd, 0);
  7273. if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1
  7274. && !battle_check_undead (7, sd->def_ele))
  7275. skill_status_change_end (&sd->bl, SC_SIGNUMCRUCIS, -1);
  7276. }
  7277. return 0;
  7278. }
  7279. int pc_unequipinvyitem (struct map_session_data *sd, int n, int type)
  7280. {
  7281. int i;
  7282. nullpo_retr (1, sd);
  7283. for (i = 0; i < MAX_EQUIP_SIZE; i++)
  7284. {
  7285. if (equip_pos[i] > 0 && sd->equip_index[i] == n)
  7286. { //Slot taken, remove item from there.
  7287. pc_unequipitem (sd, sd->equip_index[i], type);
  7288. sd->equip_index[i] = -1;
  7289. }
  7290. }
  7291. return 0;
  7292. }
  7293. /*==========================================
  7294. * アイテムのindex番号を詰めたり
  7295. * 装 備品の装備可能チェックを行なう
  7296. *------------------------------------------
  7297. */
  7298. int pc_checkitem (struct map_session_data *sd)
  7299. {
  7300. int i, j, k, id, calc_flag = 0;
  7301. struct item_data *it = NULL;
  7302. nullpo_retr (0, sd);
  7303. // 所持品空き詰め
  7304. for (i = j = 0; i < MAX_INVENTORY; i++)
  7305. {
  7306. if ((id = sd->status.inventory[i].nameid) == 0)
  7307. continue;
  7308. if (battle_config.item_check && !itemdb_available (id))
  7309. {
  7310. if (battle_config.error_log)
  7311. printf ("illeagal item id %d in %d[%s] inventory.\n", id,
  7312. sd->bl.id, sd->status.name);
  7313. pc_delitem (sd, i, sd->status.inventory[i].amount, 3);
  7314. continue;
  7315. }
  7316. if (i > j)
  7317. {
  7318. memcpy (&sd->status.inventory[j], &sd->status.inventory[i],
  7319. sizeof (struct item));
  7320. sd->inventory_data[j] = sd->inventory_data[i];
  7321. }
  7322. j++;
  7323. }
  7324. if (j < MAX_INVENTORY)
  7325. memset (&sd->status.inventory[j], 0,
  7326. sizeof (struct item) * (MAX_INVENTORY - j));
  7327. for (k = j; k < MAX_INVENTORY; k++)
  7328. sd->inventory_data[k] = NULL;
  7329. // カート内空き詰め
  7330. for (i = j = 0; i < MAX_CART; i++)
  7331. {
  7332. if ((id = sd->status.cart[i].nameid) == 0)
  7333. continue;
  7334. if (battle_config.item_check && !itemdb_available (id))
  7335. {
  7336. if (battle_config.error_log)
  7337. printf ("illeagal item id %d in %d[%s] cart.\n", id,
  7338. sd->bl.id, sd->status.name);
  7339. pc_cart_delitem (sd, i, sd->status.cart[i].amount, 1);
  7340. continue;
  7341. }
  7342. if (i > j)
  7343. {
  7344. memcpy (&sd->status.cart[j], &sd->status.cart[i],
  7345. sizeof (struct item));
  7346. }
  7347. j++;
  7348. }
  7349. if (j < MAX_CART)
  7350. memset (&sd->status.cart[j], 0,
  7351. sizeof (struct item) * (MAX_CART - j));
  7352. // 装 備位置チェック
  7353. for (i = 0; i < MAX_INVENTORY; i++)
  7354. {
  7355. it = sd->inventory_data[i];
  7356. if (sd->status.inventory[i].nameid == 0)
  7357. continue;
  7358. if (sd->status.inventory[i].equip & ~pc_equippoint (sd, i))
  7359. {
  7360. sd->status.inventory[i].equip = 0;
  7361. calc_flag = 1;
  7362. }
  7363. //装備制限チェック
  7364. if (sd->status.inventory[i].equip && map[sd->bl.m].flag.pvp
  7365. && (it->flag.no_equip == 1 || it->flag.no_equip == 3))
  7366. { //PvP制限
  7367. sd->status.inventory[i].equip = 0;
  7368. calc_flag = 1;
  7369. }
  7370. else if (sd->status.inventory[i].equip && map[sd->bl.m].flag.gvg
  7371. && (it->flag.no_equip == 2 || it->flag.no_equip == 3))
  7372. { //GvG制限
  7373. sd->status.inventory[i].equip = 0;
  7374. calc_flag = 1;
  7375. }
  7376. }
  7377. pc_setequipindex (sd);
  7378. if (calc_flag)
  7379. pc_calcstatus (sd, 2);
  7380. return 0;
  7381. }
  7382. int pc_checkoverhp (struct map_session_data *sd)
  7383. {
  7384. nullpo_retr (0, sd);
  7385. if (sd->status.hp == sd->status.max_hp)
  7386. return 1;
  7387. if (sd->status.hp > sd->status.max_hp)
  7388. {
  7389. sd->status.hp = sd->status.max_hp;
  7390. clif_updatestatus (sd, SP_HP);
  7391. return 2;
  7392. }
  7393. return 0;
  7394. }
  7395. int pc_checkoversp (struct map_session_data *sd)
  7396. {
  7397. nullpo_retr (0, sd);
  7398. if (sd->status.sp == sd->status.max_sp)
  7399. return 1;
  7400. if (sd->status.sp > sd->status.max_sp)
  7401. {
  7402. sd->status.sp = sd->status.max_sp;
  7403. clif_updatestatus (sd, SP_SP);
  7404. return 2;
  7405. }
  7406. return 0;
  7407. }
  7408. /*==========================================
  7409. * PVP順位計算用(foreachinarea)
  7410. *------------------------------------------
  7411. */
  7412. int pc_calc_pvprank_sub (struct block_list *bl, va_list ap)
  7413. {
  7414. struct map_session_data *sd1, *sd2 = NULL;
  7415. nullpo_retr (0, bl);
  7416. nullpo_retr (0, ap);
  7417. nullpo_retr (0, sd1 = (struct map_session_data *) bl);
  7418. nullpo_retr (0, sd2 = va_arg (ap, struct map_session_data *));
  7419. if (sd1->pvp_point > sd2->pvp_point)
  7420. sd2->pvp_rank++;
  7421. return 0;
  7422. }
  7423. /*==========================================
  7424. * PVP順位計算
  7425. *------------------------------------------
  7426. */
  7427. int pc_calc_pvprank (struct map_session_data *sd)
  7428. {
  7429. int old;
  7430. struct map_data *m;
  7431. nullpo_retr (0, sd);
  7432. nullpo_retr (0, m = &map[sd->bl.m]);
  7433. old = sd->pvp_rank;
  7434. if (!(m->flag.pvp))
  7435. return 0;
  7436. sd->pvp_rank = 1;
  7437. map_foreachinarea (pc_calc_pvprank_sub, sd->bl.m, 0, 0, m->xs, m->ys,
  7438. BL_PC, sd);
  7439. if (old != sd->pvp_rank || sd->pvp_lastusers != m->users)
  7440. clif_pvpset (sd, sd->pvp_rank, sd->pvp_lastusers = m->users, 0);
  7441. return sd->pvp_rank;
  7442. }
  7443. /*==========================================
  7444. * PVP順位計算(timer)
  7445. *------------------------------------------
  7446. */
  7447. int pc_calc_pvprank_timer (int tid __attribute__ ((unused)), unsigned int tick __attribute__ ((unused)), int id, int data)
  7448. {
  7449. struct map_session_data *sd = NULL;
  7450. if (battle_config.pk_mode) // disable pvp ranking if pk_mode on [Valaris]
  7451. return 0;
  7452. sd = map_id2sd (id);
  7453. if (sd == NULL)
  7454. return 0;
  7455. sd->pvp_timer = -1;
  7456. if (pc_calc_pvprank (sd) > 0)
  7457. sd->pvp_timer = add_timer (gettick () + PVP_CALCRANK_INTERVAL,
  7458. pc_calc_pvprank_timer, id, data);
  7459. return 0;
  7460. }
  7461. /*==========================================
  7462. * sdは結婚しているか(既婚の場合は相方のchar_idを返す)
  7463. *------------------------------------------
  7464. */
  7465. int pc_ismarried (struct map_session_data *sd)
  7466. {
  7467. if (sd == NULL)
  7468. return -1;
  7469. if (sd->status.partner_id > 0)
  7470. return sd->status.partner_id;
  7471. else
  7472. return 0;
  7473. }
  7474. /*==========================================
  7475. * sdがdstsdと結婚(dstsd→sdの結婚処理も同時に行う)
  7476. *------------------------------------------
  7477. */
  7478. int pc_marriage (struct map_session_data *sd, struct map_session_data *dstsd)
  7479. {
  7480. if (sd == NULL || dstsd == NULL || sd->status.partner_id > 0
  7481. || dstsd->status.partner_id > 0)
  7482. return -1;
  7483. sd->status.partner_id = dstsd->status.char_id;
  7484. dstsd->status.partner_id = sd->status.char_id;
  7485. return 0;
  7486. }
  7487. /*==========================================
  7488. * sdが離婚(相手はsd->status.partner_idに依る)(相手も同時に離婚・結婚指輪自動剥奪)
  7489. *------------------------------------------
  7490. */
  7491. int pc_divorce (struct map_session_data *sd)
  7492. {
  7493. struct map_session_data *p_sd = NULL;
  7494. if (sd == NULL || !pc_ismarried (sd))
  7495. return -1;
  7496. // If both are on map server we don't need to bother the char server
  7497. if ((p_sd =
  7498. map_nick2sd (map_charid2nick (sd->status.partner_id))) != NULL)
  7499. {
  7500. if (p_sd->status.partner_id != sd->status.char_id
  7501. || sd->status.partner_id != p_sd->status.char_id)
  7502. {
  7503. printf ("pc_divorce: Illegal partner_id sd=%d p_sd=%d\n",
  7504. sd->status.partner_id, p_sd->status.partner_id);
  7505. return -1;
  7506. }
  7507. p_sd->status.partner_id = 0;
  7508. sd->status.partner_id = 0;
  7509. if (sd->npc_flags.divorce)
  7510. {
  7511. sd->npc_flags.divorce = 0;
  7512. map_scriptcont (sd, sd->npc_id);
  7513. }
  7514. }
  7515. else
  7516. chrif_send_divorce (sd->status.char_id);
  7517. return 0;
  7518. }
  7519. /*==========================================
  7520. * sdの相方のmap_session_dataを返す
  7521. *------------------------------------------
  7522. */
  7523. struct map_session_data *pc_get_partner (struct map_session_data *sd)
  7524. {
  7525. struct map_session_data *p_sd = NULL;
  7526. char *nick;
  7527. if (sd == NULL || !pc_ismarried (sd))
  7528. return NULL;
  7529. nick = map_charid2nick (sd->status.partner_id);
  7530. if (nick == NULL)
  7531. return NULL;
  7532. if ((p_sd = map_nick2sd (nick)) == NULL)
  7533. return NULL;
  7534. return p_sd;
  7535. }
  7536. int pc_set_lang (struct map_session_data *sd, int lang)
  7537. {
  7538. if (sd == NULL)
  7539. return -1;
  7540. sd->status.language = lang;
  7541. return 0;
  7542. }
  7543. //
  7544. // 自然回復物
  7545. //
  7546. /*==========================================
  7547. * SP回復量計算
  7548. *------------------------------------------
  7549. */
  7550. static int natural_heal_tick, natural_heal_prev_tick, natural_heal_diff_tick;
  7551. static int pc_spheal (struct map_session_data *sd)
  7552. {
  7553. int a;
  7554. struct guild_castle *gc = NULL;
  7555. nullpo_retr (0, sd);
  7556. a = natural_heal_diff_tick;
  7557. if (pc_issit (sd))
  7558. a += a;
  7559. if (sd->sc_data[SC_MAGNIFICAT].timer != -1) // マグニフィカート
  7560. a += a * sd->sc_data[SC_MAGNIFICAT].val1;
  7561. gc = guild_mapname2gc (sd->mapname); // Increased guild castle regen [Valaris]
  7562. if (gc)
  7563. {
  7564. struct guild *g;
  7565. g = guild_search (sd->status.guild_id);
  7566. if (g && g->guild_id == gc->guild_id)
  7567. a += a;
  7568. } // end addition [Valaris]
  7569. return a;
  7570. }
  7571. /*==========================================
  7572. * HP回復量計算
  7573. *------------------------------------------
  7574. */
  7575. static int pc_hpheal (struct map_session_data *sd)
  7576. {
  7577. int a;
  7578. struct guild_castle *gc;
  7579. nullpo_retr (0, sd);
  7580. a = natural_heal_diff_tick;
  7581. if (pc_issit (sd))
  7582. a += a;
  7583. if (sd->sc_data[SC_MAGNIFICAT].timer != -1) // Modified by RoVeRT
  7584. a += a * sd->sc_data[SC_MAGNIFICAT].val1;
  7585. gc = guild_mapname2gc (sd->mapname); // Increased guild castle regen [Valaris]
  7586. if (gc)
  7587. {
  7588. struct guild *g;
  7589. g = guild_search (sd->status.guild_id);
  7590. if (g && g->guild_id == gc->guild_id)
  7591. a += a;
  7592. } // end addition [Valaris]
  7593. return a;
  7594. }
  7595. static int pc_natural_heal_hp (struct map_session_data *sd)
  7596. {
  7597. int bhp;
  7598. int inc_num, bonus, hp_flag;
  7599. nullpo_retr (0, sd);
  7600. if (sd->sc_data[SC_TRICKDEAD].timer != -1) // Modified by RoVeRT
  7601. return 0;
  7602. if (pc_checkoverhp (sd))
  7603. {
  7604. sd->hp_sub = sd->inchealhptick = 0;
  7605. return 0;
  7606. }
  7607. bhp = sd->status.hp;
  7608. hp_flag = (pc_checkskill (sd, SM_MOVINGRECOVERY) > 0
  7609. && sd->walktimer != -1);
  7610. if (sd->walktimer == -1)
  7611. {
  7612. inc_num = pc_hpheal (sd);
  7613. if (sd->sc_data[SC_TENSIONRELAX].timer != -1)
  7614. { // テンションリラックス
  7615. sd->hp_sub += 2 * inc_num;
  7616. sd->inchealhptick += 3 * natural_heal_diff_tick;
  7617. }
  7618. else
  7619. {
  7620. sd->hp_sub += inc_num;
  7621. sd->inchealhptick += natural_heal_diff_tick;
  7622. }
  7623. }
  7624. else if (hp_flag)
  7625. {
  7626. inc_num = pc_hpheal (sd);
  7627. sd->hp_sub += inc_num;
  7628. sd->inchealhptick = 0;
  7629. }
  7630. else
  7631. {
  7632. sd->hp_sub = sd->inchealhptick = 0;
  7633. return 0;
  7634. }
  7635. if (sd->hp_sub >= battle_config.natural_healhp_interval)
  7636. {
  7637. bonus = sd->nhealhp;
  7638. if (hp_flag)
  7639. {
  7640. bonus >>= 2;
  7641. if (bonus <= 0)
  7642. bonus = 1;
  7643. }
  7644. while (sd->hp_sub >= battle_config.natural_healhp_interval)
  7645. {
  7646. sd->hp_sub -= battle_config.natural_healhp_interval;
  7647. if (sd->status.hp + bonus <= sd->status.max_hp)
  7648. sd->status.hp += bonus;
  7649. else
  7650. {
  7651. sd->status.hp = sd->status.max_hp;
  7652. sd->hp_sub = sd->inchealhptick = 0;
  7653. }
  7654. }
  7655. }
  7656. if (bhp != sd->status.hp)
  7657. clif_updatestatus (sd, SP_HP);
  7658. if (sd->nshealhp > 0)
  7659. {
  7660. if (sd->inchealhptick >= battle_config.natural_heal_skill_interval
  7661. && sd->status.hp < sd->status.max_hp)
  7662. {
  7663. bonus = sd->nshealhp;
  7664. while (sd->inchealhptick >=
  7665. battle_config.natural_heal_skill_interval)
  7666. {
  7667. sd->inchealhptick -=
  7668. battle_config.natural_heal_skill_interval;
  7669. if (sd->status.hp + bonus <= sd->status.max_hp)
  7670. sd->status.hp += bonus;
  7671. else
  7672. {
  7673. bonus = sd->status.max_hp - sd->status.hp;
  7674. sd->status.hp = sd->status.max_hp;
  7675. sd->hp_sub = sd->inchealhptick = 0;
  7676. }
  7677. clif_heal (sd->fd, SP_HP, bonus);
  7678. }
  7679. }
  7680. }
  7681. else
  7682. sd->inchealhptick = 0;
  7683. return 0;
  7684. /*
  7685. if (sd->sc_data[SC_APPLEIDUN].timer != -1)
  7686. { // Apple of Idun
  7687. if (sd->inchealhptick >= 6000 && sd->status.hp < sd->status.max_hp)
  7688. {
  7689. bonus = skill * 20;
  7690. while (sd->inchealhptick >= 6000)
  7691. {
  7692. sd->inchealhptick -= 6000;
  7693. if (sd->status.hp + bonus <= sd->status.max_hp)
  7694. sd->status.hp += bonus;
  7695. else
  7696. {
  7697. bonus = sd->status.max_hp - sd->status.hp;
  7698. sd->status.hp = sd->status.max_hp;
  7699. sd->hp_sub = sd->inchealhptick = 0;
  7700. }
  7701. clif_heal (sd->fd, SP_HP, bonus);
  7702. }
  7703. }
  7704. }
  7705. else
  7706. sd->inchealhptick = 0;
  7707. return 0;
  7708. */
  7709. }
  7710. static int pc_natural_heal_sp (struct map_session_data *sd)
  7711. {
  7712. int bsp;
  7713. int inc_num, bonus;
  7714. nullpo_retr (0, sd);
  7715. if (sd->sc_data[SC_TRICKDEAD].timer != -1) // Modified by RoVeRT
  7716. return 0;
  7717. if (pc_checkoversp (sd))
  7718. {
  7719. sd->sp_sub = sd->inchealsptick = 0;
  7720. return 0;
  7721. }
  7722. bsp = sd->status.sp;
  7723. inc_num = pc_spheal (sd);
  7724. if (sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1)
  7725. sd->sp_sub += inc_num;
  7726. if (sd->walktimer == -1)
  7727. sd->inchealsptick += natural_heal_diff_tick;
  7728. else
  7729. sd->inchealsptick = 0;
  7730. if (sd->sp_sub >= battle_config.natural_healsp_interval)
  7731. {
  7732. bonus = sd->nhealsp;;
  7733. while (sd->sp_sub >= battle_config.natural_healsp_interval)
  7734. {
  7735. sd->sp_sub -= battle_config.natural_healsp_interval;
  7736. if (sd->status.sp + bonus <= sd->status.max_sp)
  7737. sd->status.sp += bonus;
  7738. else
  7739. {
  7740. sd->status.sp = sd->status.max_sp;
  7741. sd->sp_sub = sd->inchealsptick = 0;
  7742. }
  7743. }
  7744. }
  7745. if (bsp != sd->status.sp)
  7746. clif_updatestatus (sd, SP_SP);
  7747. if (sd->nshealsp > 0)
  7748. {
  7749. if (sd->inchealsptick >= battle_config.natural_heal_skill_interval
  7750. && sd->status.sp < sd->status.max_sp)
  7751. {
  7752. struct pc_base_job s_class = pc_calc_base_job (sd->status.class);
  7753. if (sd->doridori_counter && s_class.job == 23)
  7754. bonus = sd->nshealsp * 2;
  7755. else
  7756. bonus = sd->nshealsp;
  7757. sd->doridori_counter = 0;
  7758. while (sd->inchealsptick >=
  7759. battle_config.natural_heal_skill_interval)
  7760. {
  7761. sd->inchealsptick -=
  7762. battle_config.natural_heal_skill_interval;
  7763. if (sd->status.sp + bonus <= sd->status.max_sp)
  7764. sd->status.sp += bonus;
  7765. else
  7766. {
  7767. bonus = sd->status.max_sp - sd->status.sp;
  7768. sd->status.sp = sd->status.max_sp;
  7769. sd->sp_sub = sd->inchealsptick = 0;
  7770. }
  7771. clif_heal (sd->fd, SP_SP, bonus);
  7772. }
  7773. }
  7774. }
  7775. else
  7776. sd->inchealsptick = 0;
  7777. return 0;
  7778. }
  7779. static int pc_spirit_heal_hp (struct map_session_data *sd, int level __attribute__ ((unused)))
  7780. {
  7781. nullpo_retr (0, sd);
  7782. int interval = battle_config.natural_heal_skill_interval;;
  7783. struct status_change *sc_data = battle_get_sc_data (&sd->bl);
  7784. nullpo_retr (0, sc_data);
  7785. if (pc_checkoverhp (sd))
  7786. {
  7787. sd->inchealspirithptick = 0;
  7788. return 0;
  7789. }
  7790. sd->inchealspirithptick += natural_heal_diff_tick;
  7791. if (sd->max_weight && sd->weight * 100 / sd->max_weight >=
  7792. battle_config.natural_heal_weight_rate
  7793. && sc_data[SC_FLYING_BACKPACK].timer == -1)
  7794. interval += interval;
  7795. if (sd->inchealspirithptick >= interval)
  7796. {
  7797. int bonus_hp;
  7798. bonus_hp = sd->nsshealhp;
  7799. while (sd->inchealspirithptick >= interval)
  7800. {
  7801. if (pc_issit (sd))
  7802. {
  7803. sd->inchealspirithptick -= interval;
  7804. if (sd->status.hp < sd->status.max_hp)
  7805. {
  7806. if (sd->status.hp + bonus_hp <= sd->status.max_hp)
  7807. sd->status.hp += bonus_hp;
  7808. else
  7809. {
  7810. bonus_hp = sd->status.max_hp - sd->status.hp;
  7811. sd->status.hp = sd->status.max_hp;
  7812. }
  7813. clif_heal (sd->fd, SP_HP, bonus_hp);
  7814. sd->inchealspirithptick = 0;
  7815. }
  7816. }
  7817. else
  7818. {
  7819. sd->inchealspirithptick -= natural_heal_diff_tick;
  7820. break;
  7821. }
  7822. }
  7823. }
  7824. return 0;
  7825. }
  7826. static int pc_spirit_heal_sp (struct map_session_data *sd, int level __attribute__ ((unused)))
  7827. {
  7828. int interval = battle_config.natural_heal_skill_interval;
  7829. nullpo_retr (0, sd);
  7830. if (pc_checkoversp (sd))
  7831. {
  7832. sd->inchealspiritsptick = 0;
  7833. return 0;
  7834. }
  7835. sd->inchealspiritsptick += natural_heal_diff_tick;
  7836. if (sd->max_weight && sd->weight * 100 / sd->max_weight >=
  7837. battle_config.natural_heal_weight_rate)
  7838. interval += interval;
  7839. if (sd->inchealspiritsptick >= interval)
  7840. {
  7841. int bonus_sp;
  7842. bonus_sp = sd->nsshealsp;
  7843. while (sd->inchealspiritsptick >= interval)
  7844. {
  7845. if (pc_issit (sd))
  7846. {
  7847. sd->inchealspiritsptick -= interval;
  7848. if (sd->status.sp < sd->status.max_sp)
  7849. {
  7850. if (sd->status.sp + bonus_sp <= sd->status.max_sp)
  7851. sd->status.sp += bonus_sp;
  7852. else
  7853. {
  7854. bonus_sp = sd->status.max_sp - sd->status.sp;
  7855. sd->status.sp = sd->status.max_sp;
  7856. }
  7857. clif_heal (sd->fd, SP_SP, bonus_sp);
  7858. sd->inchealspiritsptick = 0;
  7859. }
  7860. }
  7861. else
  7862. {
  7863. sd->inchealspiritsptick -= natural_heal_diff_tick;
  7864. break;
  7865. }
  7866. }
  7867. }
  7868. return 0;
  7869. }
  7870. /*==========================================
  7871. * HP/SP 自然回復 各クライアント
  7872. *------------------------------------------
  7873. */
  7874. static int pc_itemheal_effect (struct map_session_data *sd, int hp, int sp);
  7875. static int
  7876. pc_quickregenerate_effect (struct quick_regeneration *quick_regen,
  7877. int heal_speed)
  7878. {
  7879. nullpo_retr (0, quick_regen);
  7880. if (!(quick_regen->tickdelay--))
  7881. {
  7882. int bonus =
  7883. MIN (heal_speed * battle_config.itemheal_regeneration_factor,
  7884. quick_regen->amount);
  7885. quick_regen->amount -= bonus;
  7886. quick_regen->tickdelay = quick_regen->speed;
  7887. return bonus;
  7888. }
  7889. return 0;
  7890. }
  7891. static int pc_natural_heal_sub (struct map_session_data *sd, va_list ap __attribute__ ((unused)))
  7892. {
  7893. int skill;
  7894. nullpo_retr (0, sd);
  7895. if (sd->heal_xp > 0)
  7896. {
  7897. if (sd->heal_xp < 64)
  7898. --sd->heal_xp; // [Fate] Slowly reduce XP that healers can get for healing this char
  7899. else
  7900. sd->heal_xp -= (sd->heal_xp >> 6);
  7901. }
  7902. // Hijack this callback: Adjust spellpower bonus
  7903. if (sd->spellpower_bonus_target < sd->spellpower_bonus_current)
  7904. {
  7905. sd->spellpower_bonus_current = sd->spellpower_bonus_target;
  7906. pc_calcstatus (sd, 0);
  7907. }
  7908. else if (sd->spellpower_bonus_target > sd->spellpower_bonus_current)
  7909. {
  7910. sd->spellpower_bonus_current +=
  7911. 1 +
  7912. ((sd->spellpower_bonus_target -
  7913. sd->spellpower_bonus_current) >> 5);
  7914. pc_calcstatus (sd, 0);
  7915. }
  7916. if (sd->sc_data[SC_HALT_REGENERATE].timer != -1)
  7917. return 0;
  7918. if (sd->quick_regeneration_hp.amount || sd->quick_regeneration_sp.amount)
  7919. {
  7920. int hp_bonus = pc_quickregenerate_effect (&sd->quick_regeneration_hp,
  7921. (sd->sc_data[SC_POISON].timer == -1 || sd->sc_data[SC_SLOWPOISON].timer != -1) ? sd->nhealhp : 1);
  7922. // [fate] slow down when poisoned
  7923. int sp_bonus = pc_quickregenerate_effect (&sd->quick_regeneration_sp,
  7924. sd->nhealsp);
  7925. pc_itemheal_effect (sd, hp_bonus, sp_bonus);
  7926. }
  7927. skill_update_heal_animation (sd); // if needed.
  7928. // -- moonsoul (if conditions below altered to disallow natural healing if under berserk status)
  7929. if ((sd->sc_data[SC_FLYING_BACKPACK].timer != -1
  7930. || battle_config.natural_heal_weight_rate > 100
  7931. || (sd->max_weight && sd->weight * 100 / sd->max_weight <
  7932. battle_config.natural_heal_weight_rate)) && !pc_isdead (sd)
  7933. && !pc_ishiding (sd) && sd->sc_data[SC_POISON].timer == -1)
  7934. {
  7935. pc_natural_heal_hp (sd);
  7936. if (sd->sc_data && sd->sc_data[SC_EXTREMITYFIST].timer == -1 && //阿修羅状態ではSPが回復しない
  7937. sd->sc_data[SC_DANCING].timer == -1 && //ダンス状態ではSPが回復しない
  7938. sd->sc_data[SC_BERSERK].timer == -1 //バーサーク状態ではSPが回復しない
  7939. )
  7940. pc_natural_heal_sp (sd);
  7941. }
  7942. else
  7943. {
  7944. sd->hp_sub = sd->inchealhptick = 0;
  7945. sd->sp_sub = sd->inchealsptick = 0;
  7946. }
  7947. if ((skill = pc_checkskill (sd, MO_SPIRITSRECOVERY)) > 0
  7948. && !pc_ishiding (sd) && sd->sc_data[SC_POISON].timer == -1
  7949. && sd->sc_data[SC_BERSERK].timer == -1)
  7950. {
  7951. pc_spirit_heal_hp (sd, skill);
  7952. pc_spirit_heal_sp (sd, skill);
  7953. }
  7954. else
  7955. {
  7956. sd->inchealspirithptick = 0;
  7957. sd->inchealspiritsptick = 0;
  7958. }
  7959. return 0;
  7960. }
  7961. /*==========================================
  7962. * HP/SP自然回復 (interval timer関数)
  7963. *------------------------------------------
  7964. */
  7965. int pc_natural_heal (int tid __attribute__ ((unused)), unsigned int tick, int id __attribute__ ((unused)), int data __attribute__ ((unused)))
  7966. {
  7967. natural_heal_tick = tick;
  7968. natural_heal_diff_tick =
  7969. DIFF_TICK (natural_heal_tick, natural_heal_prev_tick);
  7970. clif_foreachclient (pc_natural_heal_sub);
  7971. natural_heal_prev_tick = tick;
  7972. return 0;
  7973. }
  7974. /*==========================================
  7975. * セーブポイントの保存
  7976. *------------------------------------------
  7977. */
  7978. int pc_setsavepoint (struct map_session_data *sd, char *mapname, int x, int y)
  7979. {
  7980. nullpo_retr (0, sd);
  7981. nullpo_retr (0, mapname);
  7982. safestrncpy (sd->status.save_point.map, mapname, 24);
  7983. sd->status.save_point.x = x;
  7984. sd->status.save_point.y = y;
  7985. return 0;
  7986. }
  7987. /*==========================================
  7988. * 自動セーブ 各クライアント
  7989. *------------------------------------------
  7990. */
  7991. static int last_save_fd, save_flag;
  7992. static int pc_autosave_sub (struct map_session_data *sd, va_list ap __attribute__ ((unused)))
  7993. {
  7994. nullpo_retr (0, sd);
  7995. if (save_flag == 0 && sd->fd > last_save_fd)
  7996. {
  7997. struct guild_castle *gc = NULL;
  7998. int i;
  7999. pc_makesavestatus (sd);
  8000. chrif_save (sd);
  8001. for (i = 0; i < MAX_GUILDCASTLE; i++)
  8002. {
  8003. gc = guild_castle_search (i);
  8004. if (!gc)
  8005. continue;
  8006. if (gc->visibleG0 == 1)
  8007. guild_castledatasave (gc->castle_id, 18, gc->Ghp0);
  8008. if (gc->visibleG1 == 1)
  8009. guild_castledatasave (gc->castle_id, 19, gc->Ghp1);
  8010. if (gc->visibleG2 == 1)
  8011. guild_castledatasave (gc->castle_id, 20, gc->Ghp2);
  8012. if (gc->visibleG3 == 1)
  8013. guild_castledatasave (gc->castle_id, 21, gc->Ghp3);
  8014. if (gc->visibleG4 == 1)
  8015. guild_castledatasave (gc->castle_id, 22, gc->Ghp4);
  8016. if (gc->visibleG5 == 1)
  8017. guild_castledatasave (gc->castle_id, 23, gc->Ghp5);
  8018. if (gc->visibleG6 == 1)
  8019. guild_castledatasave (gc->castle_id, 24, gc->Ghp6);
  8020. if (gc->visibleG7 == 1)
  8021. guild_castledatasave (gc->castle_id, 25, gc->Ghp7);
  8022. }
  8023. save_flag = 1;
  8024. last_save_fd = sd->fd;
  8025. }
  8026. return 0;
  8027. }
  8028. /*==========================================
  8029. * 自動セーブ (timer関数)
  8030. *------------------------------------------
  8031. */
  8032. int pc_autosave (int tid __attribute__ ((unused)), unsigned int tick __attribute__ ((unused)), int id __attribute__ ((unused)), int data __attribute__ ((unused)))
  8033. {
  8034. int interval;
  8035. save_flag = 0;
  8036. clif_foreachclient (pc_autosave_sub);
  8037. if (save_flag == 0)
  8038. last_save_fd = 0;
  8039. int tmp = clif_countusers () + 1;
  8040. if (tmp)
  8041. interval = autosave_interval / tmp;
  8042. else
  8043. interval = 1;
  8044. if (interval <= 0)
  8045. interval = 1;
  8046. add_timer (gettick () + interval, pc_autosave, 0, 0);
  8047. return 0;
  8048. }
  8049. int pc_read_gm_account (int fd)
  8050. {
  8051. int i = 0;
  8052. free (gm_account);
  8053. GM_num = 0;
  8054. gm_account =
  8055. calloc (sizeof (struct gm_account) * ((RFIFOW (fd, 2) - 4) / 5), 1);
  8056. if (!gm_account)
  8057. {
  8058. printf("out of memory pc_read_gm_account\n");
  8059. exit(1);
  8060. }
  8061. for (i = 4; i < RFIFOW (fd, 2); i = i + 5)
  8062. {
  8063. gm_account[GM_num].account_id = RFIFOL (fd, i);
  8064. gm_account[GM_num].level = (int) RFIFOB (fd, i + 4);
  8065. //printf("GM account: %d -> level %d\n", gm_account[GM_num].account_id, gm_account[GM_num].level);
  8066. GM_num++;
  8067. }
  8068. return GM_num;
  8069. }
  8070. /*==========================================
  8071. * timer to do the day
  8072. *------------------------------------------
  8073. */
  8074. int map_day_timer (int tid __attribute__ ((unused)), unsigned int tick __attribute__ ((unused)), int id __attribute__ ((unused)), int data __attribute__ ((unused)))
  8075. { // by [yor]
  8076. struct map_session_data *pl_sd = NULL;
  8077. char tmpstr[1024];
  8078. if (battle_config.day_duration > 0)
  8079. { // if we want a day
  8080. if (night_flag != 0)
  8081. {
  8082. int i;
  8083. strcpy (tmpstr, msg_txt (502)); // The day has arrived!
  8084. night_flag = 0; // 0=day, 1=night [Yor]
  8085. for (i = 0; i < fd_max; i++)
  8086. {
  8087. if (session[i] && (pl_sd = session[i]->session_data)
  8088. && pl_sd->state.auth)
  8089. {
  8090. pl_sd->opt2 &= ~STATE_BLIND;
  8091. clif_changeoption (&pl_sd->bl);
  8092. clif_wis_message (pl_sd->fd, wisp_server_name, tmpstr,
  8093. strlen (tmpstr) + 1);
  8094. }
  8095. }
  8096. }
  8097. }
  8098. return 0;
  8099. }
  8100. /*==========================================
  8101. * timer to do the night
  8102. *------------------------------------------
  8103. */
  8104. int map_night_timer (int tid __attribute__ ((unused)), unsigned int tick __attribute__ ((unused)), int id __attribute__ ((unused)), int data __attribute__ ((unused)))
  8105. { // by [yor]
  8106. struct map_session_data *pl_sd = NULL;
  8107. char tmpstr[1024];
  8108. if (battle_config.night_duration > 0)
  8109. { // if we want a night
  8110. if (night_flag == 0)
  8111. {
  8112. int i;
  8113. strcpy (tmpstr, msg_txt (503)); // The night has fallen...
  8114. night_flag = 1; // 0=day, 1=night [Yor]
  8115. for (i = 0; i < fd_max; i++)
  8116. {
  8117. if (session[i] && (pl_sd = session[i]->session_data)
  8118. && pl_sd->state.auth)
  8119. {
  8120. pl_sd->opt2 |= STATE_BLIND;
  8121. clif_changeoption (&pl_sd->bl);
  8122. clif_wis_message (pl_sd->fd, wisp_server_name, tmpstr,
  8123. strlen (tmpstr) + 1);
  8124. }
  8125. }
  8126. }
  8127. }
  8128. return 0;
  8129. }
  8130. void pc_setstand (struct map_session_data *sd)
  8131. {
  8132. nullpo_retv (sd);
  8133. if (sd->sc_data && sd->sc_data[SC_TENSIONRELAX].timer != -1)
  8134. skill_status_change_end (&sd->bl, SC_TENSIONRELAX, -1);
  8135. sd->state.dead_sit = 0;
  8136. }
  8137. //
  8138. // 初期化物
  8139. //
  8140. /*==========================================
  8141. * 設定ファイル読み込む
  8142. * exp.txt 必要経験値
  8143. * job_db1.txt 重量,hp,sp,攻撃速度
  8144. * job_db2.txt job能力値ボーナス
  8145. * skill_tree.txt 各職毎のスキルツリー
  8146. * attr_fix.txt 属性修正テーブル
  8147. * size_fix.txt サイズ補正テーブル
  8148. * refine_db.txt 精錬データテーブル
  8149. *------------------------------------------
  8150. */
  8151. int pc_readdb (void)
  8152. {
  8153. int i, j, k;
  8154. FILE *fp;
  8155. char line[2024], *p;
  8156. // 必要経験値読み込み
  8157. fp = fopen_ ("db/exp.txt", "r");
  8158. if (fp == NULL)
  8159. {
  8160. printf ("can't read db/exp.txt\n");
  8161. return 1;
  8162. }
  8163. i = 0;
  8164. while (fgets (line, sizeof (line) - 1, fp))
  8165. {
  8166. int bn, b1, b2, b3, b4, b5, b6, jn, j1, j2, j3, j4, j5, j6;
  8167. if (line[0] == '/' && line[1] == '/')
  8168. continue;
  8169. if (sscanf
  8170. (line, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &bn, &b1, &b2,
  8171. &b3, &b4, &b5, &b6, &jn, &j1, &j2, &j3, &j4, &j5, &j6) != 14)
  8172. continue;
  8173. exp_table[0][i] = bn;
  8174. exp_table[1][i] = b1;
  8175. exp_table[2][i] = b2;
  8176. exp_table[3][i] = b3;
  8177. exp_table[4][i] = b4;
  8178. exp_table[5][i] = b5;
  8179. exp_table[6][i] = b6;
  8180. exp_table[7][i] = jn;
  8181. exp_table[8][i] = j1;
  8182. exp_table[9][i] = j2;
  8183. exp_table[10][i] = j3;
  8184. exp_table[11][i] = j4;
  8185. exp_table[12][i] = j5;
  8186. exp_table[13][i] = j6;
  8187. i++;
  8188. if (i >= battle_config.maximum_level)
  8189. break;
  8190. }
  8191. fclose_ (fp);
  8192. printf ("read db/exp.txt done\n");
  8193. // JOB補正数値1
  8194. fp = fopen_ ("db/job_db1.txt", "r");
  8195. if (fp == NULL)
  8196. {
  8197. printf ("can't read db/job_db1.txt\n");
  8198. return 1;
  8199. }
  8200. i = 0;
  8201. while (fgets (line, sizeof (line) - 1, fp))
  8202. {
  8203. char *split[50];
  8204. if (line[0] == '/' && line[1] == '/')
  8205. continue;
  8206. for (j = 0, p = line; j < 21 && p; j++)
  8207. {
  8208. split[j] = p;
  8209. p = strchr (p, ',');
  8210. if (p)
  8211. *p++ = 0;
  8212. }
  8213. if (j < 21)
  8214. continue;
  8215. max_weight_base[i] = atoi (split[0]);
  8216. hp_coefficient[i] = atoi (split[1]);
  8217. hp_coefficient2[i] = atoi (split[2]);
  8218. sp_coefficient[i] = atoi (split[3]);
  8219. for (j = 0; j < 17; j++)
  8220. aspd_base[i][j] = atoi (split[j + 4]);
  8221. i++;
  8222. // -- moonsoul (below two lines added to accommodate high numbered new class ids)
  8223. if (i == 24)
  8224. i = 4001;
  8225. if (i == MAX_PC_CLASS)
  8226. break;
  8227. }
  8228. fclose_ (fp);
  8229. printf ("read db/job_db1.txt done\n");
  8230. // JOBボーナス
  8231. fp = fopen_ ("db/job_db2.txt", "r");
  8232. if (fp == NULL)
  8233. {
  8234. printf ("can't read db/job_db2.txt\n");
  8235. return 1;
  8236. }
  8237. i = 0;
  8238. while (fgets (line, sizeof (line) - 1, fp))
  8239. {
  8240. if (line[0] == '/' && line[1] == '/')
  8241. continue;
  8242. for (j = 0, p = line; j < MAX_LEVEL && p; j++)
  8243. {
  8244. if (sscanf (p, "%d", &k) == 0)
  8245. break;
  8246. job_bonus[0][i][j] = k;
  8247. job_bonus[2][i][j] = k; //養子職のボーナスは分からないので仮
  8248. p = strchr (p, ',');
  8249. if (p)
  8250. p++;
  8251. }
  8252. i++;
  8253. // -- moonsoul (below two lines added to accommodate high numbered new class ids)
  8254. if (i == 24)
  8255. i = 4001;
  8256. if (i == MAX_PC_CLASS)
  8257. break;
  8258. }
  8259. fclose_ (fp);
  8260. printf ("read db/job_db2.txt done\n");
  8261. // JOBボーナス2 転生職用
  8262. fp = fopen_ ("db/job_db2-2.txt", "r");
  8263. if (fp == NULL)
  8264. {
  8265. printf ("can't read db/job_db2-2.txt\n");
  8266. return 1;
  8267. }
  8268. i = 0;
  8269. while (fgets (line, sizeof (line) - 1, fp))
  8270. {
  8271. if (line[0] == '/' && line[1] == '/')
  8272. continue;
  8273. for (j = 0, p = line; j < MAX_LEVEL && p; j++)
  8274. {
  8275. if (sscanf (p, "%d", &k) == 0)
  8276. break;
  8277. job_bonus[1][i][j] = k;
  8278. p = strchr (p, ',');
  8279. if (p)
  8280. p++;
  8281. }
  8282. i++;
  8283. if (i == MAX_PC_CLASS)
  8284. break;
  8285. }
  8286. fclose_ (fp);
  8287. printf ("read db/job_db2-2.txt done\n");
  8288. // スキルツリー
  8289. memset (skill_tree, 0, sizeof (skill_tree));
  8290. fp = fopen_ ("db/skill_tree.txt", "r");
  8291. if (fp == NULL)
  8292. {
  8293. printf ("can't read db/skill_tree.txt\n");
  8294. return 1;
  8295. }
  8296. while (fgets (line, sizeof (line) - 1, fp))
  8297. {
  8298. char *split[50];
  8299. if (line[0] == '/' && line[1] == '/')
  8300. continue;
  8301. for (j = 0, p = line; j < 13 && p; j++)
  8302. {
  8303. split[j] = p;
  8304. p = strchr (p, ',');
  8305. if (p)
  8306. *p++ = 0;
  8307. }
  8308. if (j < 13)
  8309. continue;
  8310. i = atoi (split[0]);
  8311. for (j = 0; skill_tree[0][i][j].id; j++);
  8312. skill_tree[0][i][j].id = atoi (split[1]);
  8313. skill_tree[0][i][j].max = atoi (split[2]);
  8314. skill_tree[2][i][j].id = atoi (split[1]); //養子職は良く分からないので暫定
  8315. skill_tree[2][i][j].max = atoi (split[2]); //養子職は良く分からないので暫定
  8316. for (k = 0; k < 5; k++)
  8317. {
  8318. skill_tree[0][i][j].need[k].id = atoi (split[k * 2 + 3]);
  8319. skill_tree[0][i][j].need[k].lv = atoi (split[k * 2 + 4]);
  8320. skill_tree[2][i][j].need[k].id = atoi (split[k * 2 + 3]); //養子職は良く分からないので暫定
  8321. skill_tree[2][i][j].need[k].lv = atoi (split[k * 2 + 4]); //養子職は良く分からないので暫定
  8322. }
  8323. }
  8324. fclose_ (fp);
  8325. printf ("read db/skill_tree.txt done\n");
  8326. // 属性修正テーブル
  8327. for (i = 0; i < 4; i++)
  8328. for (j = 0; j < 10; j++)
  8329. for (k = 0; k < 10; k++)
  8330. attr_fix_table[i][j][k] = 100;
  8331. fp = fopen_ ("db/attr_fix.txt", "r");
  8332. if (fp == NULL)
  8333. {
  8334. printf ("can't read db/attr_fix.txt\n");
  8335. return 1;
  8336. }
  8337. while (fgets (line, sizeof (line) - 1, fp))
  8338. {
  8339. char *split[10];
  8340. int lv, n;
  8341. if (line[0] == '/' && line[1] == '/')
  8342. continue;
  8343. for (j = 0, p = line; j < 3 && p; j++)
  8344. {
  8345. split[j] = p;
  8346. p = strchr (p, ',');
  8347. if (p)
  8348. *p++ = 0;
  8349. }
  8350. lv = atoi (split[0]);
  8351. if (lv < 1 || lv >= 4 + 1)
  8352. continue;
  8353. n = atoi (split[1]);
  8354. if (n > 10)
  8355. continue;
  8356. // printf("%d %d\n",lv,n);
  8357. for (i = 0; i < n;)
  8358. {
  8359. if (!fgets (line, sizeof (line) - 1, fp))
  8360. break;
  8361. if (line[0] == '/' && line[1] == '/')
  8362. continue;
  8363. for (j = 0, p = line; j < n && p; j++)
  8364. {
  8365. while (*p == 32 && *p > 0)
  8366. p++;
  8367. attr_fix_table[lv - 1][i][j] = atoi (p);
  8368. if (battle_config.attr_recover == 0
  8369. && attr_fix_table[lv - 1][i][j] < 0)
  8370. attr_fix_table[lv - 1][i][j] = 0;
  8371. p = strchr (p, ',');
  8372. if (p)
  8373. *p++ = 0;
  8374. }
  8375. i++;
  8376. }
  8377. }
  8378. fclose_ (fp);
  8379. printf ("read db/attr_fix.txt done\n");
  8380. // サイズ補正テーブル
  8381. for (i = 0; i < 3; i++)
  8382. for (j = 0; j < 20; j++)
  8383. atkmods[i][j] = 100;
  8384. fp = fopen_ ("db/size_fix.txt", "r");
  8385. if (fp == NULL)
  8386. {
  8387. printf ("can't read db/size_fix.txt\n");
  8388. return 1;
  8389. }
  8390. i = 0;
  8391. while (fgets (line, sizeof (line) - 1, fp))
  8392. {
  8393. char *split[20];
  8394. if (line[0] == '/' && line[1] == '/')
  8395. continue;
  8396. if (atoi (line) <= 0)
  8397. continue;
  8398. memset (split, 0, sizeof (split));
  8399. for (j = 0, p = line; j < 20 && p; j++)
  8400. {
  8401. split[j] = p;
  8402. p = strchr (p, ',');
  8403. if (p)
  8404. *p++ = 0;
  8405. }
  8406. for (j = 0; j < 20 && split[j]; j++)
  8407. atkmods[i][j] = atoi (split[j]);
  8408. i++;
  8409. }
  8410. fclose_ (fp);
  8411. printf ("read db/size_fix.txt done\n");
  8412. // 精錬データテーブル
  8413. for (i = 0; i < 5; i++)
  8414. {
  8415. for (j = 0; j < 10; j++)
  8416. percentrefinery[i][j] = 100;
  8417. refinebonus[i][0] = 0;
  8418. refinebonus[i][1] = 0;
  8419. refinebonus[i][2] = 10;
  8420. }
  8421. fp = fopen_ ("db/refine_db.txt", "r");
  8422. if (fp == NULL)
  8423. {
  8424. printf ("can't read db/refine_db.txt\n");
  8425. return 1;
  8426. }
  8427. i = 0;
  8428. while (fgets (line, sizeof (line) - 1, fp))
  8429. {
  8430. char *split[16];
  8431. if (line[0] == '/' && line[1] == '/')
  8432. continue;
  8433. if (atoi (line) <= 0)
  8434. continue;
  8435. memset (split, 0, sizeof (split));
  8436. for (j = 0, p = line; j < 16 && p; j++)
  8437. {
  8438. split[j] = p;
  8439. p = strchr (p, ',');
  8440. if (p)
  8441. *p++ = 0;
  8442. }
  8443. refinebonus[i][0] = atoi (split[0]); // 精錬ボーナス
  8444. refinebonus[i][1] = atoi (split[1]); // 過剰精錬ボーナス
  8445. refinebonus[i][2] = atoi (split[2]); // 安全精錬限界
  8446. for (j = 0; j < 10 && split[j]; j++)
  8447. percentrefinery[i][j] = atoi (split[j + 3]);
  8448. i++;
  8449. }
  8450. fclose_ (fp); //Lupus. close this file!!!
  8451. printf ("read db/refine_db.txt done\n");
  8452. return 0;
  8453. }
  8454. static int pc_calc_sigma (void)
  8455. {
  8456. int i, j, k;
  8457. for (i = 0; i < MAX_PC_CLASS; i++)
  8458. {
  8459. memset (hp_sigma_val[i], 0, sizeof (hp_sigma_val[i]));
  8460. for (k = 0, j = 2; j <= MAX_LEVEL; j++)
  8461. {
  8462. k += hp_coefficient[i] * j + 50;
  8463. k -= k % 100;
  8464. hp_sigma_val[i][j - 1] = k;
  8465. }
  8466. }
  8467. return 0;
  8468. }
  8469. static void pc_statpointdb (void)
  8470. {
  8471. char *buf_stat;
  8472. int i = 0, j = 0, k = 0, l = 0, end = 0;
  8473. FILE *stp;
  8474. stp = fopen_ ("db/statpoint.txt", "r");
  8475. if (stp == NULL)
  8476. {
  8477. printf ("can't read db/statpoint.txt\n");
  8478. return;
  8479. }
  8480. fseek (stp, 0, SEEK_END);
  8481. end = ftell (stp);
  8482. rewind (stp);
  8483. buf_stat = (char *) malloc (end + 1);
  8484. l = fread (buf_stat, 1, end, stp);
  8485. fclose_ (stp);
  8486. printf ("read db/statpoint.txt done (size=%d)\n", l);
  8487. for (i = 0; i < 255; i++)
  8488. {
  8489. j = 0;
  8490. while (*(buf_stat + k) != '\n')
  8491. {
  8492. statp[i][j] = *(buf_stat + k);
  8493. j++;
  8494. k++;
  8495. }
  8496. statp[i][j + 1] = '\0';
  8497. k++;
  8498. }
  8499. free (buf_stat);
  8500. }
  8501. /*==========================================
  8502. * pc関 係初期化
  8503. *------------------------------------------
  8504. */
  8505. int do_init_pc (void)
  8506. {
  8507. pc_readdb ();
  8508. pc_statpointdb ();
  8509. pc_calc_sigma ();
  8510. // gm_account_db = numdb_init();
  8511. add_timer_func_list (pc_walk, "pc_walk");
  8512. add_timer_func_list (pc_attack_timer, "pc_attack_timer");
  8513. add_timer_func_list (pc_natural_heal, "pc_natural_heal");
  8514. add_timer_func_list (pc_invincible_timer, "pc_invincible_timer");
  8515. add_timer_func_list (pc_eventtimer, "pc_eventtimer");
  8516. add_timer_func_list (pc_calc_pvprank_timer, "pc_calc_pvprank_timer");
  8517. add_timer_func_list (pc_autosave, "pc_autosave");
  8518. add_timer_func_list (pc_spiritball_timer, "pc_spiritball_timer");
  8519. add_timer_interval ((natural_heal_prev_tick =
  8520. gettick () + NATURAL_HEAL_INTERVAL), pc_natural_heal,
  8521. 0, 0, NATURAL_HEAL_INTERVAL);
  8522. add_timer (gettick () + autosave_interval, pc_autosave, 0, 0);
  8523. // add night/day timer (by [yor])
  8524. add_timer_func_list (map_day_timer, "map_day_timer"); // by [yor]
  8525. add_timer_func_list (map_night_timer, "map_night_timer"); // by [yor]
  8526. {
  8527. int day_duration = battle_config.day_duration;
  8528. int night_duration = battle_config.night_duration;
  8529. if (day_duration < 60000)
  8530. day_duration = 60000;
  8531. if (night_duration < 60000)
  8532. night_duration = 60000;
  8533. if (battle_config.night_at_start == 0)
  8534. {
  8535. night_flag = 0; // 0=day, 1=night [Yor]
  8536. day_timer_tid =
  8537. add_timer_interval (gettick () + day_duration +
  8538. night_duration, map_day_timer, 0, 0,
  8539. day_duration + night_duration);
  8540. night_timer_tid =
  8541. add_timer_interval (gettick () + day_duration,
  8542. map_night_timer, 0, 0,
  8543. day_duration + night_duration);
  8544. }
  8545. else
  8546. {
  8547. night_flag = 1; // 0=day, 1=night [Yor]
  8548. day_timer_tid =
  8549. add_timer_interval (gettick () + night_duration,
  8550. map_day_timer, 0, 0,
  8551. day_duration + night_duration);
  8552. night_timer_tid =
  8553. add_timer_interval (gettick () + day_duration +
  8554. night_duration, map_night_timer, 0, 0,
  8555. day_duration + night_duration);
  8556. }
  8557. }
  8558. return 0;
  8559. }
  8560. void pc_cleanup (struct map_session_data *sd)
  8561. {
  8562. magic_stop_completely (sd);
  8563. }
  8564. void pc_invisibility (struct map_session_data *sd, int enabled)
  8565. {
  8566. if (enabled && !(sd->status.option & OPTION_INVISIBILITY))
  8567. {
  8568. clif_clearchar_area (&sd->bl, 3);
  8569. sd->status.option |= OPTION_INVISIBILITY;
  8570. clif_status_change (&sd->bl, CLIF_OPTION_SC_INVISIBILITY, 1);
  8571. }
  8572. else if (!enabled)
  8573. {
  8574. sd->status.option &= ~OPTION_INVISIBILITY;
  8575. clif_status_change (&sd->bl, CLIF_OPTION_SC_INVISIBILITY, 0);
  8576. pc_setpos (sd, map[sd->bl.m].name, sd->bl.x, sd->bl.y, 3);
  8577. }
  8578. }
  8579. int pc_logout (struct map_session_data *sd) // [fate] Player logs out
  8580. {
  8581. unsigned int tick = gettick ();
  8582. if (!sd)
  8583. return 0;
  8584. if (sd->sc_data[SC_POISON].timer != -1)
  8585. sd->status.hp = 1; // Logging out while poisoned -> bad
  8586. /*
  8587. * Trying to rapidly sign out/in or switch characters to avoid a spell's
  8588. * cast time is also bad. [remoitnane]
  8589. */
  8590. if (sd->cast_tick > tick)
  8591. {
  8592. if (pc_setglobalreg (sd, "MAGIC_CAST_TICK", sd->cast_tick - tick))
  8593. sd->status.sp = 1;
  8594. }
  8595. else
  8596. pc_setglobalreg (sd, "MAGIC_CAST_TICK", 0);
  8597. MAP_LOG_STATS (sd, "LOGOUT") return 0;
  8598. }