📄 pc.c
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "timer.h"
#include "db.h"
#include "map.h"
#include "chrif.h"
#include "clif.h"
#include "intif.h"
#include "pc.h"
#include "npc.h"
#include "mob.h"
#include "pet.h"
#include "itemdb.h"
#include "script.h"
#include "battle.h"
#include "skill.h"
#include "party.h"
#include "guild.h"
#include "chat.h"
#include "trade.h"
#include "storage.h"
#include "vending.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
#define PVP_CALCRANK_INTERVAL 1000 // PVP弴埵寁嶼偺娫妘
static int max_weight_base[MAX_PC_CLASS];
static int hp_coefficient[MAX_PC_CLASS];
static int hp_coefficient2[MAX_PC_CLASS];
static int hp_sigma_val[MAX_PC_CLASS][MAX_LEVEL];
static int sp_coefficient[MAX_PC_CLASS];
static int aspd_base[MAX_PC_CLASS][20];
static char job_bonus[MAX_PC_CLASS][MAX_LEVEL];
static int exp_table[8][MAX_LEVEL];
static struct {
int id;
int max;
struct {
short id,lv;
} need[6];
} skill_tree[MAX_PC_CLASS][100];
static int atkmods[3][20]; // 晲婍ATK僒僀僘廋惓(size_fix.txt)
static int refinebonus[5][3]; // 惛楤儃乕僫僗僥乕僽儖(refine_db.txt)
static int percentrefinery[5][10]; // 惛楤惉岟棪(refine_db.txt)
static int dirx[8]={0,-1,-1,-1,0,1,1,1};
static int diry[8]={1,1,0,-1,-1,-1,0,1};
static unsigned int equip_pos[11]={0x0080,0x0008,0x0040,0x0004,0x0001,0x0200,0x0100,0x0010,0x0020,0x0002,0x8000};
static char GM_account_filename[1024] = "conf/GM_account.txt";
static struct dbt *gm_account_db;
void pc_set_gm_account_fname(char *str)
{
strcpy(GM_account_filename,str);
}
int pc_isGM(struct map_session_data *sd)
{
struct gm_account *p;
p = numdb_search(gm_account_db,sd->status.account_id);
if( p == NULL)
return 0;
return p->level;
}
int pc_getrefinebonus(int lv,int type)
{
if(lv >= 0 && lv < 5 && type >= 0 && type < 3)
return refinebonus[lv][type];
return 0;
}
static int distance(int x0,int y0,int x1,int y1)
{
int dx,dy;
dx=abs(x0-x1);
dy=abs(y0-y1);
return dx>dy ? dx : dy;
}
static int pc_invincible_timer(int tid,unsigned int tick,int id,int data)
{
struct map_session_data *sd;
sd=(struct map_session_data *)map_id2sd(id);
if(sd==NULL || sd->bl.type!=BL_PC)
return 1;
if(sd->invincible_timer != tid){
if(battle_config.error_log)
printf("invincible_timer %d != %d\n",sd->invincible_timer,tid);
return 0;
}
sd->invincible_timer=-1;
return 0;
}
int pc_setinvincibletimer(struct map_session_data *sd,int val)
{
if(sd->invincible_timer != -1)
delete_timer(sd->invincible_timer,pc_invincible_timer);
sd->invincible_timer = add_timer(gettick()+val,pc_invincible_timer,sd->bl.id,0);
return 0;
}
int pc_delinvincibletimer(struct map_session_data *sd)
{
if(sd->invincible_timer != -1) {
delete_timer(sd->invincible_timer,pc_invincible_timer);
sd->invincible_timer = -1;
}
return 0;
}
static int pc_spiritball_timer(int tid,unsigned int tick,int id,int data)
{
struct map_session_data *sd;
int i;
sd=(struct map_session_data *)map_id2sd(id);
if(sd==NULL || sd->bl.type!=BL_PC)
return 1;
if(sd->spirit_timer[0] != tid){
if(battle_config.error_log)
printf("spirit_timer %d != %d\n",sd->spirit_timer[0],tid);
return 0;
}
sd->spirit_timer[0]=-1;
for(i=1;i<sd->spiritball;i++) {
sd->spirit_timer[i-1] = sd->spirit_timer[i];
sd->spirit_timer[i] = -1;
}
sd->spiritball--;
if(sd->spiritball < 0)
sd->spiritball = 0;
clif_spiritball(sd);
return 0;
}
int pc_addspiritball(struct map_session_data *sd,int interval,int max)
{
int i;
if(max > MAX_SKILL_LEVEL)
max = MAX_SKILL_LEVEL;
if(sd->spiritball < 0)
sd->spiritball = 0;
if(sd->spiritball >= max) {
if(sd->spirit_timer[0] != -1) {
delete_timer(sd->spirit_timer[0],pc_spiritball_timer);
sd->spirit_timer[0] = -1;
}
for(i=1;i<max;i++) {
sd->spirit_timer[i-1] = sd->spirit_timer[i];
sd->spirit_timer[i] = -1;
}
}
else
sd->spiritball++;
sd->spirit_timer[sd->spiritball-1] = add_timer(gettick()+interval,pc_spiritball_timer,sd->bl.id,0);
clif_spiritball(sd);
return 0;
}
int pc_delspiritball(struct map_session_data *sd,int count,int type)
{
int i;
if(sd->spiritball <= 0) {
sd->spiritball = 0;
return 0;
}
if(count > sd->spiritball)
count = sd->spiritball;
sd->spiritball -= count;
if(count > MAX_SKILL_LEVEL)
count = MAX_SKILL_LEVEL;
for(i=0;i<count;i++) {
if(sd->spirit_timer[i] != -1) {
delete_timer(sd->spirit_timer[i],pc_spiritball_timer);
sd->spirit_timer[i] = -1;
}
}
for(i=count;i<MAX_SKILL_LEVEL;i++) {
sd->spirit_timer[i-count] = sd->spirit_timer[i];
sd->spirit_timer[i] = -1;
}
if(!type)
clif_spiritball(sd);
return 0;
}
int pc_setrestartvalue(struct map_session_data *sd,int type)
{
//-----------------------
// 巰朣偟偨
if(sd->special_state.restart_full_recover) { // 僆僔儕僗僇乕僪
sd->status.hp=sd->status.max_hp;
sd->status.sp=sd->status.max_sp;
}
else {
if(sd->status.class == 0 && battle_config.restart_hp_rate < 50) { // 僲乕價僗
sd->status.hp=(sd->status.max_hp)/2;
}
else {
if(battle_config.restart_hp_rate <= 0)
sd->status.hp = 1;
else {
sd->status.hp = sd->status.max_hp * battle_config.restart_hp_rate /100;
if(sd->status.hp <= 0)
sd->status.hp = 1;
}
}
if(battle_config.restart_sp_rate > 0) {
int sp = sd->status.max_sp * battle_config.restart_sp_rate /100;
if(sd->status.sp < sp)
sd->status.sp = sp;
}
}
if(type&1)
clif_updatestatus(sd,SP_HP);
if(type&1)
clif_updatestatus(sd,SP_SP);
if(type&2) {
if(!(battle_config.death_penalty_type&1) ) {
if(sd->status.class > 0 && !map[sd->bl.m].flag.nopenalty && !map[sd->bl.m].flag.gvg){
if(battle_config.death_penalty_type&2 && battle_config.death_penalty_base > 0)
sd->status.base_exp -= (int)((double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000.);
else if(battle_config.death_penalty_base > 0) {
if(pc_nextbaseexp(sd) > 0)
sd->status.base_exp -= (int)((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000.);
}
if(sd->status.base_exp < 0)
sd->status.base_exp = 0;
if(type&1)
clif_updatestatus(sd,SP_BASEEXP);
if(battle_config.death_penalty_type&2 && battle_config.death_penalty_job > 0)
sd->status.job_exp -= (int)((double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000.);
else if(battle_config.death_penalty_job > 0) {
if(pc_nextjobexp(sd) > 0)
sd->status.job_exp -= (int)((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000.);
}
if(sd->status.job_exp < 0)
sd->status.job_exp = 0;
if(type&1)
clif_updatestatus(sd,SP_JOBEXP);
}
}
if(battle_config.zeny_penalty > 0&&!map[sd->bl.m].flag.nozenypenalty) {
int zeny = (int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.);
if(zeny < 1) zeny = 1;
sd->status.zeny -= zeny;
if(sd->status.zeny < 0) sd->status.zeny = 0;
if(type&1)
clif_updatestatus(sd,SP_ZENY);
}
}
return 0;
}
/*==========================================
* 帺暘傪儘僢僋偟偰偄傞MOB偺悢傪悢偊傞(foreachclient)
*------------------------------------------
*/
static int pc_counttargeted_sub(struct block_list *bl,va_list ap)
{
int id,*c;
struct block_list *src;
id=va_arg(ap,int);
c=va_arg(ap,int *);
src=va_arg(ap,struct block_list *);
if(id == bl->id || (src && id == src->id)) return 0;
if(bl->type == BL_PC) {
if(((struct map_session_data *)bl)->attacktarget == id && ((struct map_session_data *)bl)->attacktimer != -1)
(*c)++;
}
else if(bl->type == BL_MOB) {
if(((struct mob_data *)bl)->target_id == id && ((struct mob_data *)bl)->timer != -1 && ((struct mob_data *)bl)->state.state == MS_ATTACK)
(*c)++;
}
return 0;
}
int pc_counttargeted(struct map_session_data *sd,struct block_list *src)
{
int c=0;
map_foreachinarea(pc_counttargeted_sub, sd->bl.m,
sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,
sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,0,sd->bl.id,&c,src);
return c;
}
/*==========================================
* 儘乕僇儖僾儘僩僞僀僾愰尵 (昁梫側暔偺傒)
*------------------------------------------
*/
static int pc_walktoxy_sub(struct map_session_data *);
/*==========================================
* save偵昁梫側僗僥乕僞僗廋惓傪峴側偆
*------------------------------------------
*/
int pc_makesavestatus(struct map_session_data *sd)
{
int i;
// 暈偺怓偼怓乆暰奞偑懡偄偺偱曐懚懳徾偵偼偟側偄
if(!battle_config.save_clothcolor)
sd->status.clothes_color=0;
// 巰朣忬懺偩偭偨偺偱hp傪1丄埵抲傪僙乕僽応強偵曄峏
if(pc_isdead(sd)){
pc_setrestartvalue(sd,0);
memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
} else {
memcpy(sd->status.last_point.map,sd->mapname,24);
sd->status.last_point.x = sd->bl.x;
sd->status.last_point.y = sd->bl.y;
}
// 僙乕僽嬛巭儅僢僾偩偭偨偺偱巜掕埵抲偵堏摦
if(map[sd->bl.m].flag.nosave){
struct map_data *m=&map[sd->bl.m];
if(strcmp(m->save.map,"SavePoint")==0)
memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
else
memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point));
}
//僋儘乕儞僗僉儖偱妎偊偨僗僉儖偼徚偡
for(i=0;i<MAX_SKILL;i++){
if(sd->status.skill[i].flag == 13){
sd->status.skill[i].id=0;
sd->status.skill[i].lv=0;
sd->status.skill[i].flag=0;
}
}
return 0;
}
/*==========================================
* 愙懕帪偺弶婜壔
*------------------------------------------
*/
int pc_setnewpc(struct map_session_data *sd,int account_id,int char_id,int login_id1,int client_tick,int sex,int fd)
{
sd->bl.id = account_id;
sd->char_id = char_id;
sd->login_id1 = login_id1;
sd->client_tick = client_tick;
sd->sex = sex;
sd->state.auth = 0;
sd->bl.type = BL_PC;
sd->canact_tick = sd->canmove_tick = gettick();
sd->state.waitingdisconnect=0;
return 0;
}
int pc_equippoint(struct map_session_data *sd,int n)
{
int ep = 0;
if(sd && sd->inventory_data[n]) {
ep = sd->inventory_data[n]->equip;
if(sd->inventory_data[n]->look == 1 || sd->inventory_data[n]->look == 2 || sd->inventory_data[n]->look == 6) {
if(ep == 2 && (pc_checkskill(sd,AS_LEFT) > 0 || sd->status.class == 12) )
return 34;
}
}
return ep;
}
int pc_setinventorydata(struct map_session_data *sd)
{
int i,id;
for(i=0;i<MAX_INVENTORY;i++) {
id = sd->status.inventory[i].nameid;
sd->inventory_data[i] = itemdb_search(id);
}
return 0;
}
int pc_calcweapontype(struct map_session_data *sd)
{
if(sd->weapontype1 != 0 && sd->weapontype2 == 0)
sd->status.weapon = sd->weapontype1;
if(sd->weapontype1 == 0 && sd->weapontype2 != 0)// 嵍庤晲婍 Only
sd->status.weapon = sd->weapontype2;
else if(sd->weapontype1 == 1 && sd->weapontype2 == 1)// 憃抁寱
sd->status.weapon = 0x11;
else if(sd->weapontype1 == 2 && sd->weapontype2 == 2)// 憃扨庤寱
sd->status.weapon = 0x12;
else if(sd->weapontype1 == 6 && sd->weapontype2 == 6)// 憃扨庤晙
sd->status.weapon = 0x13;
else if( (sd->weapontype1 == 1 && sd->weapontype2 == 2) ||
(sd->weapontype1 == 2 && sd->weapontype2 == 1) ) // 抁寱 - 扨庤寱
sd->status.weapon = 0x14;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -