From 3ef2cb492970da40f82df9643c4cfc570bc3aa62 Mon Sep 17 00:00:00 2001 From: Fate Date: Sat, 26 Sep 2009 18:08:42 +0000 Subject: Initial support for skill pools (available via at commands and untested scripting commands.) These changes also affect the format of the skill_db.txt file. --- doc/mapserver-logging | 67 ++++++++++++++++++++ src/char/char.c | 23 ++----- src/common/mmo.h | 2 +- src/map/atcommand.c | 130 +++++++++++++++++++++++++++++++++++++-- src/map/battle.c | 48 ++++++++++++--- src/map/battle.h | 1 + src/map/chrif.c | 17 +----- src/map/clif.c | 14 ++--- src/map/magic-stmt.c | 27 +++++++-- src/map/magic.c | 8 +-- src/map/map.c | 11 +--- src/map/map.h | 8 +++ src/map/npc.c | 4 -- src/map/pc.c | 72 +++++++++------------- src/map/script.c | 7 +-- src/map/skill-pools.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/map/skill.c | 7 +++ src/map/skill.h | 31 +++++++--- 18 files changed, 505 insertions(+), 137 deletions(-) create mode 100644 doc/mapserver-logging create mode 100644 src/map/skill-pools.c diff --git a/doc/mapserver-logging b/doc/mapserver-logging new file mode 100644 index 0000000..e7088eb --- /dev/null +++ b/doc/mapserver-logging @@ -0,0 +1,67 @@ +Log format: + +LOGLINE ::= int'.'int + +MESSAGE ::= 'log-start' + | 'log-start v2' + | 'log-start v3' + | + | + +COORD ::= int':'int','int + +PC ::= 'PC'int + +MOB ::= 'MOB'int + +TARGET ::= | + +SPELLRESULT ::= 'SUCCESS' | 'FAILURE' + +STATPLACE ::= 'LOGIN' | 'STATUP' | 'STATUP2' | 'STATRESET' + +XPPLACE ::= 'LOGIN' | 'LEVELUP' + +XPREASON ::= 'SCRIPTXP' 'HEALXP' 'KILLXP' + +ZEROTARGET ::= 'null' | + +MOB-MESSAGE ::= 'DEAD' + +PC-MESSAGE ::= 'WPNDMG' int 'FOR' int WPN int # "WPNDMG MOB01 type FOR damage WPN weapon-item" + | 'WPNINJURY' int 'FOR' int + | 'SPELLHEAL-INSTA' FOR int + | 'SPELLDMG' FOR int BY spell-id + | 'CAST' spell-id + | 'STAT' int int int int int int # str agi vit int dex luk + | 'XP' int int ZENY int '+' int # level xp zeny bank-zeny + | 'MAGIC' int int int int int int 'EXP' int int 'LOGIN' # magic life war transmute nature ether magic-xp healer-xp + | 'SKILL-ACTIVATE' int int int # skillid skilllvl skillpower + | 'SKILL-UP' int int int # skillid skilllvl skillpower + | 'SKILL-DEACTIVATE' int + | 'MAGIC-ABSORB-DMG' int + | 'GAINXP' int + | 'PICKUP' int int # item-id count + | 'INJURED-BY' 'FOR' int + | 'DEAD' + | 'LOGOUT' + | 'TRADECOMMIT' 'WITH' int 'GIVE' int 'GET' int # pc-id give-zeny get-zeny + | 'TRADECANCEL' + | 'TRADEOK' + + + +NOTES: +------ +1. Any PICKUP between TRADECOMMIT and TRADEOK is part of the trade. +2. TRADECOMMIT is issued for both participants in a trade. +3. INJURED-BY seems to only duplicate information we already have. + + +Illegal items + +645, 668, 659, 731, 734, 744, 745, 755, 756, 757, 747, 748, 721, 722 + +Restricted access + +725, 726, 647, 646 \ No newline at end of file diff --git a/src/char/char.c b/src/char/char.c index fbf512e..98321ec 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -269,8 +269,8 @@ int mmo_char_tostr(char *str, struct mmo_charstatus *p) { *(str_p++) = '\t'; for(i = 0; i < MAX_SKILL; i++) - if (p->skill[i].id && p->skill[i].flag != 1) { - str_p += sprintf(str_p, "%d,%d ", p->skill[i].id, (p->skill[i].flag == 0) ? p->skill[i].lv : p->skill[i].flag-2); + if (p->skill[i].id) { + str_p += sprintf(str_p, "%d,%d ", p->skill[i].id, p->skill[i].lv | (p->skill[i].flags << 16)); } *(str_p++) = '\t'; @@ -506,7 +506,8 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p) { if (sscanf(str + next, "%d,%d%n", &tmp_int[0], &tmp_int[1], &len) != 2) return -6; p->skill[tmp_int[0]].id = tmp_int[0]; - p->skill[tmp_int[0]].lv = tmp_int[1]; + p->skill[tmp_int[0]].lv = tmp_int[1] & 0xffff; + p->skill[tmp_int[0]].flags = ((tmp_int[1] >> 16) & 0xffff); next += len; if (str[next] == ' ') next++; @@ -1660,22 +1661,6 @@ int parse_tologin(int fd) { } else if (jobclass == 4042 || jobclass == 4043) { char_dat[i].class = (sex) ? 4042 : 4043; } - // remove specifical skills of classes 19, 4020 and 4042 - for(j = 315; j <= 322; j++) { - if (char_dat[i].skill[j].id > 0 && !char_dat[i].skill[j].flag) { - char_dat[i].skill_point += char_dat[i].skill[j].lv; - char_dat[i].skill[j].id = 0; - char_dat[i].skill[j].lv = 0; - } - } - // remove specifical skills of classes 20, 4021 and 4043 - for(j = 323; j <= 330; j++) { - if (char_dat[i].skill[j].id > 0 && !char_dat[i].skill[j].flag) { - char_dat[i].skill_point += char_dat[i].skill[j].lv; - char_dat[i].skill[j].id = 0; - char_dat[i].skill[j].lv = 0; - } - } } // to avoid any problem with equipment and invalid sex, equipment is unequiped. for (j = 0; j < MAX_INVENTORY; j++) { diff --git a/src/common/mmo.h b/src/common/mmo.h index e958f81..1ba3ee4 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -83,7 +83,7 @@ struct point{ }; struct skill { - unsigned short id,lv,flag; + unsigned short id,lv,flags; }; struct global_reg { diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 23f1aa8..510026b 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -204,6 +204,10 @@ ATCOMMAND_FUNC(visible); // [Fate] ATCOMMAND_FUNC(list_nearby); // [Fate] ATCOMMAND_FUNC(iterate_forward_over_players); // [Fate] ATCOMMAND_FUNC(iterate_backwards_over_players); // [Fate] +ATCOMMAND_FUNC(skillpool_info); // [Fate] +ATCOMMAND_FUNC(skillpool_focus); // [Fate] +ATCOMMAND_FUNC(skillpool_unfocus); // [Fate] +ATCOMMAND_FUNC(skill_learn); // [Fate] ATCOMMAND_FUNC(wgm); /*========================================== @@ -393,6 +397,10 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_Visible, "@visible", 60, atcommand_visible }, // [Fate] { AtCommand_IterateForward, "@hugo", 60, atcommand_iterate_forward_over_players }, // [Fate] { AtCommand_IterateBackward, "@linus", 60, atcommand_iterate_backwards_over_players }, // [Fate] + { AtCommand_IterateBackward, "@sp-info", 40, atcommand_skillpool_info }, // [Fate] + { AtCommand_IterateBackward, "@sp-focus", 80, atcommand_skillpool_focus }, // [Fate] + { AtCommand_IterateBackward, "@sp-unfocus", 80, atcommand_skillpool_unfocus }, // [Fate] + { AtCommand_IterateBackward, "@skill-learn", 80, atcommand_skill_learn }, // [Fate] { AtCommand_Wgm, "@wgm", 0, atcommand_wgm }, // add new commands before this line @@ -4088,7 +4096,7 @@ int atcommand_lostskill( if (skill_get_inf2(skill_id) & 0x01) { if (pc_checkskill(sd, skill_id) > 0) { sd->status.skill[skill_id].lv = 0; - sd->status.skill[skill_id].flag = 0; + sd->status.skill[skill_id].flags = 0; clif_skillinfoblock(sd); clif_displaymessage(fd, msg_table[71]); // You have forgotten the skill. } else { @@ -4131,7 +4139,7 @@ int atcommand_charlostskill( if ((pl_sd = map_nick2sd(character)) != NULL) { if (pc_checkskill(pl_sd, skill_id) > 0) { pl_sd->status.skill[skill_id].lv = 0; - pl_sd->status.skill[skill_id].flag = 0; + pl_sd->status.skill[skill_id].flags = 0; clif_skillinfoblock(pl_sd); clif_displaymessage(fd, msg_table[202]); // This player has forgotten the skill. } else { @@ -7002,7 +7010,7 @@ atcommand_magic_info(const int fd, struct map_session_data* sd, memset(character, '\0', sizeof(character)); - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) { + if (!message || !*message || sscanf(message, "%99s", character) < 1) { clif_displaymessage(fd, "Usage: @magicinfo "); return -1; } @@ -7031,7 +7039,6 @@ set_skill(struct map_session_data* sd, int i, int level) { sd->status.skill[i].id = level? i : 0; sd->status.skill[i].lv = level; - sd->status.skill[i].flag = 0; } int @@ -7194,3 +7201,118 @@ int atcommand_wgm( return 0; } + +int atcommand_skillpool_info( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char character[100]; + struct map_session_data *pl_sd; + + if (!message || !*message || sscanf(message, "%99s", character) < 1) { + clif_displaymessage(fd, "Usage: @sp-info "); + return -1; + } + + if ((pl_sd = map_nick2sd(character)) != NULL) { + char buf[200]; + int pool_skills[MAX_SKILL_POOL]; + int pool_skills_nr = skill_pool(pl_sd, pool_skills); + int i; + + sprintf(buf, "Active skills %d out of %d for %s:", pool_skills_nr, skill_pool_max(pl_sd), character); + clif_displaymessage(fd, buf); + for (i = 0; i < pool_skills_nr; ++i) { + sprintf(buf, " - %s [%d]: power %d", skill_name(pool_skills[i]), pool_skills[i], skill_power(pl_sd, pool_skills[i])); + clif_displaymessage(fd, buf); + } + + sprintf(buf, "Learned skills out of %d for %s:", skill_pool_skills_size, character); + clif_displaymessage(fd, buf); + + for (i = 0; i < skill_pool_skills_size; ++i) { + char *name = skill_name(skill_pool_skills[i]); + int lvl = pl_sd->status.skill[skill_pool_skills[i]].lv; + + if (lvl) { + sprintf(buf, " - %s [%d]: lvl %d", name, skill_pool_skills[i], lvl); + clif_displaymessage(fd, buf); + } + } + + } else + clif_displaymessage(fd, "Character not found."); + + + return 0; +} + +int atcommand_skillpool_focus( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char character[100]; + int skill; + struct map_session_data *pl_sd; + + if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill, character) < 1) { + clif_displaymessage(fd, "Usage: @sp-focus "); + return -1; + } + + if ((pl_sd = map_nick2sd(character)) != NULL) { + if (skill_pool_activate(pl_sd, skill)) + clif_displaymessage(fd, "Activation failed."); + else + clif_displaymessage(fd, "Activation successful."); + } else + clif_displaymessage(fd, "Character not found."); + + return 0; +} + +int atcommand_skillpool_unfocus( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char character[100]; + int skill; + struct map_session_data *pl_sd; + + if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill, character) < 1) { + clif_displaymessage(fd, "Usage: @sp-unfocus "); + return -1; + } + + if ((pl_sd = map_nick2sd(character)) != NULL) { + if (skill_pool_deactivate(pl_sd, skill)) + clif_displaymessage(fd, "Deactivation failed."); + else + clif_displaymessage(fd, "Deactivation successful."); + } else + clif_displaymessage(fd, "Character not found."); + + return 0; +} + +int atcommand_skill_learn( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char character[100]; + int skill, level; + struct map_session_data *pl_sd; + + if (!message || !*message || sscanf(message, "%d %d %99[^\n]", &skill, &level, character) < 1) { + clif_displaymessage(fd, "Usage: @skill-learn "); + return -1; + } + + if ((pl_sd = map_nick2sd(character)) != NULL) { + set_skill(pl_sd, skill, level); + clif_skillinfoblock(pl_sd); + } else + clif_displaymessage(fd, "Character not found."); + + return 0; +} diff --git a/src/map/battle.c b/src/map/battle.c index 507defd..9b5f699 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -381,6 +381,10 @@ int battle_get_flee(struct block_list *bl) flee += flee*(sc_data[SC_WINDWALK].val2)/100; if(sc_data[SC_SPIDERWEB].timer!=-1 && bl->type != BL_PC) //スパイダーウェブ flee -= flee*50/100; + + if (battle_is_unarmed(bl)) + flee += (skill_power_bl(bl, TMW_BRAWLING) >> 3); // +25 for 200 + flee += skill_power_bl(bl, TMW_SPEED) >> 3; } if(flee < 1) flee = 1; return flee; @@ -412,6 +416,9 @@ int battle_get_hit(struct block_list *bl) hit += 3*(sc_data[SC_TRUESIGHT].val1); if(sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC) //コンセントレーション hit += (hit*(10*(sc_data[SC_CONCENTRATION].val1)))/100; + + if (battle_is_unarmed(bl)) + hit += (skill_power_bl(bl, TMW_BRAWLING) >> 4); // +12 for 200 } if(hit < 1) hit = 1; return hit; @@ -439,6 +446,10 @@ int battle_get_flee2(struct block_list *bl) if(sc_data[SC_WHISTLE].timer!=-1 && bl->type != BL_PC) flee2 += (sc_data[SC_WHISTLE].val1+sc_data[SC_WHISTLE].val2 +(sc_data[SC_WHISTLE].val3&0xffff))*10; + + if (battle_is_unarmed(bl)) + flee2 += (skill_power_bl(bl, TMW_BRAWLING) >> 3); // +25 for 200 + flee2 += skill_power_bl(bl, TMW_SPEED) >> 3; } if(flee2 < 1) flee2 = 1; return flee2; @@ -582,6 +593,7 @@ int battle_get_atk2(struct block_list *bl) if(sc_data[SC_CONCENTRATION].timer!=-1) //コンセントレーション atk2 += atk2*(5*sc_data[SC_CONCENTRATION].val1)/100; } + if(atk2 < 0) atk2 = 0; return atk2; } @@ -595,8 +607,8 @@ int battle_get_atk2(struct block_list *bl) int battle_get_atk_2(struct block_list *bl) { nullpo_retr(0, bl); - if(bl->type==BL_PC && (struct map_session_data *)bl) - return ((struct map_session_data*)bl)->watk_2; + if(bl->type==BL_PC) + return ((struct map_session_data*)bl)->watk_2; else return 0; } @@ -2228,6 +2240,23 @@ static struct Damage battle_calc_mob_weapon_attack( wd.dmg_lv=dmg_lv; return wd; } + + +int +battle_is_unarmed(struct block_list *bl) +{ + if (!bl) + return 0; + if (bl->type == BL_PC) { + struct map_session_data *sd = (struct map_session_data *) bl; + + return (sd->equip_index[EQUIP_SHIELD] == -1 + && sd->equip_index[EQUIP_WEAPON] == -1); + } else + return 0; +} + + /* * ========================================================================= * PCの武器による攻撃 @@ -2325,6 +2354,7 @@ static struct Damage battle_calc_pc_weapon_attack( } } hitrate=battle_get_hit(src) - flee + 80; //命中率計算 + battle_is_unarmed(src); { // [Fate] Reduce hit chance by distance int dx = abs(src->x - target->x); int dy = abs(src->y - target->y); @@ -3890,13 +3920,17 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, // significantly increase injuries for hasted characters if (wd.damage > 0 && (t_sc_data[SC_HASTE].timer != -1)) { - wd.damage = (wd.damage * (16 + t_sc_data[SC_HASTE].val1)) >> 4; + wd.damage = (wd.damage * (16 + t_sc_data[SC_HASTE].val1)) >> 4; } - if (t_sc_data[SC_PHYS_SHIELD].timer != -1 && target->type == BL_PC) { - wd.damage -= t_sc_data[SC_PHYS_SHIELD].val1; - if (wd.damage < 0) - wd.damage = 0; + if (wd.damage > 0 + && t_sc_data[SC_PHYS_SHIELD].timer != -1 && target->type == BL_PC) { + int reduction = t_sc_data[SC_PHYS_SHIELD].val1; + if (reduction > wd.damage) + reduction = wd.damage; + + wd.damage -= reduction; + MAP_LOG_PC(((struct map_session_data *)target), "MAGIC-ABSORB-DMG %d", reduction); } if((damage = wd.damage + wd.damage2) > 0 && src != target) { diff --git a/src/map/battle.h b/src/map/battle.h index 6ff45d0..6b4860d 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -63,6 +63,7 @@ int battle_weapon_attack( struct block_list *bl,struct block_list *target, // 各種パラメータを得る int battle_counttargeted(struct block_list *bl,struct block_list *src,int target_lv); +int battle_is_unarmed(struct block_list *bl); int battle_get_class(struct block_list *bl); int battle_get_dir(struct block_list *bl); int battle_get_lv(struct block_list *bl); diff --git a/src/map/chrif.c b/src/map/chrif.c index 4318d1a..3152866 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -595,22 +595,7 @@ int chrif_changedsex(int fd) // reset skill of some job if (s_class.job == 19 || s_class.job == 4020 || s_class.job == 4042 || s_class.job == 20 || s_class.job == 4021 || s_class.job == 4043) { - // remove specifical skills of classes 19, 4020 and 4042 - for(i = 315; i <= 322; i++) { - if (sd->status.skill[i].id > 0 && !sd->status.skill[i].flag) { - sd->status.skill_point += sd->status.skill[i].lv; - sd->status.skill[i].id = 0; - sd->status.skill[i].lv = 0; - } - } - // remove specifical skills of classes 20, 4021 and 4043 - for(i = 323; i <= 330; i++) { - if (sd->status.skill[i].id > 0 && !sd->status.skill[i].flag) { - sd->status.skill_point += sd->status.skill[i].lv; - sd->status.skill[i].id = 0; - sd->status.skill[i].lv = 0; - } - } + clif_updatestatus(sd, SP_SKILLPOINT); // change job if necessary if (s_class.job == 20 || s_class.job == 4021 || s_class.job == 4043) diff --git a/src/map/clif.c b/src/map/clif.c index 083a246..086c14b 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -3741,10 +3741,7 @@ int clif_skillinfo(struct map_session_data *sd,int skillid,int type,int range) } else WFIFOW(fd,12)= range; memset(WFIFOP(fd,14),0,24); - if(skill_get_inf2(id)&0x01) - WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_get_max(id) && sd->status.skill[skillid].flag ==0 )? 1:0; - else - WFIFOB(fd,38) = 0; + WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_get_max_raise(id))? 1:0; WFIFOSET(fd,packet_len_table[0x147]); return 0; @@ -3768,7 +3765,7 @@ int clif_skillinfoblock(struct map_session_data *sd) && (sd->tmw_version >= 1)){ // [Fate] Version 1 and later don't crash because of bad skill IDs anymore WFIFOW(fd,len ) = id; WFIFOW(fd,len+2) = skill_get_inf(id); - WFIFOW(fd,len+4) = skill_db[i].poolflags | (sd->status.skill[i].flag & (SKILL_POOL_ACTIVATED)); + WFIFOW(fd,len+4) = skill_db[i].poolflags | (sd->status.skill[i].flags & (SKILL_POOL_ACTIVATED)); WFIFOW(fd,len+6) = sd->status.skill[i].lv; WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv); range = skill_get_range(id,sd->status.skill[i].lv); @@ -3776,10 +3773,7 @@ int clif_skillinfoblock(struct map_session_data *sd) range = battle_get_range(&sd->bl) - (range + 1); WFIFOW(fd,len+10)= range; memset(WFIFOP(fd,len+12),0,24); - if(skill_get_inf2(id)&0x01) - WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_get_max(id) && sd->status.skill[i].flag ==0 )? 1:0; - else - WFIFOB(fd,len+36) = 0; + WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_get_max_raise(id))? 1:0; len+=37; c++; } @@ -3809,7 +3803,7 @@ int clif_skillup(struct map_session_data *sd,int skill_num) if(range < 0) range = battle_get_range(&sd->bl) - (range + 1); WFIFOW(fd,8) = range; - WFIFOB(fd,10) = (sd->status.skill[skill_num].lv < skill_get_max(sd->status.skill[skill_num].id)) ? 1 : 0; + WFIFOB(fd,10) = (sd->status.skill[skill_num].lv < skill_get_max_raise(sd->status.skill[skill_num].id)) ? 1 : 0; WFIFOSET(fd,packet_len_table[0x10e]); return 0; diff --git a/src/map/magic-stmt.c b/src/map/magic-stmt.c index 55e6133..65e0202 100644 --- a/src/map/magic-stmt.c +++ b/src/map/magic-stmt.c @@ -292,9 +292,8 @@ op_instaheal(env_t *env, int args_nr, val_t *args) if (caster->type == BL_PC && subject->type == BL_PC) { character_t *caster_pc = (character_t *) caster; character_t *subject_pc = (character_t *) subject; - MAP_LOG("PC%d %d:%d,%d SPELLHEAL-INSTA PC%d FOR %d", - caster_pc->status.char_id, caster->m, caster->x, caster->y, - subject_pc->status.char_id, ARGINT(1)); + MAP_LOG_PC(caster_pc, "SPELLHEAL-INSTA PC%d FOR %d", + subject_pc->status.char_id, ARGINT(1)); } battle_heal(caster, subject, ARGINT(1), ARGINT(2), 0); @@ -677,6 +676,22 @@ op_spawn(env_t *env, int args_nr, val_t *args) } +static char * +get_invocation_name(env_t *env) +{ + invocation_t *invocation; + + if (VAR(VAR_INVOCATION).ty != TY_INVOCATION) + return "?"; + invocation = (invocation_t *)map_id2bl(VAR(VAR_INVOCATION).v.v_int); + + if (invocation) + return invocation->spell->name; + else + return "??"; +} + + static int op_injure(env_t *env, int args_nr, val_t *args) { @@ -711,9 +726,9 @@ op_injure(env_t *env, int args_nr, val_t *args) if (target->type == BL_MOB) { struct mob_data *mob = (struct mob_data *) target; - MAP_LOG("PC%d %d:%d,%d SPELLDMG MOB%d %d FOR %d", - caster_pc->status.char_id, caster->m, caster->x, caster->y, - mob->bl.id, mob->class, damage_caused); + MAP_LOG_PC(caster_pc, "SPELLDMG MOB%d %d FOR %d BY %s", + mob->bl.id, mob->class, damage_caused, + get_invocation_name(env)); } } battle_damage(caster, target, damage_caused, mp_damage); diff --git a/src/map/magic.c b/src/map/magic.c index 7567691..f70d9a6 100644 --- a/src/map/magic.c +++ b/src/map/magic.c @@ -95,11 +95,9 @@ magic_message(character_t *caster, if (caster->status.option & OPTION_HIDE) return 0; // No spellcasting while hidden - MAP_LOG("PC%d %d:%d,%d CAST %s %s", - caster->status.char_id, caster->bl.m, caster->bl.x, caster->bl.y, - spell->name, - effects? "SUCCESS" : "FAILURE"); - + MAP_LOG_PC(caster, "CAST %s %s", + spell->name, + effects? "SUCCESS" : "FAILURE"); if (effects) { invocation_t *invocation = spell_instantiate(effects, env); diff --git a/src/map/map.c b/src/map/map.c index abb750f..f5d6d33 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -965,8 +965,6 @@ void map_addnickdb(struct map_session_data *sd) { *------------------------------------------ */ int map_quit(struct map_session_data *sd) { - int i; - nullpo_retr(0, sd); if(sd->chatID) // チャットから出る @@ -1012,13 +1010,6 @@ int map_quit(struct map_session_data *sd) { pc_setrestartvalue(sd,2); pc_makesavestatus(sd); //クローンスキルで覚えたスキルは消す - for(i=0;istatus.skill[i].flag == 13){ - sd->status.skill[i].id=0; - sd->status.skill[i].lv=0; - sd->status.skill[i].flag=0; - } - } //The storage closing routines will save the char if needed. [Skotlex] if (!sd->state.storage_flag) @@ -1704,7 +1695,7 @@ map_set_logfile(char *filename) map_start_logfile(tv.tv_sec); atexit(map_close_logfile); - MAP_LOG("log-start v2"); + MAP_LOG("log-start v3"); } diff --git a/src/map/map.h b/src/map/map.h index 5e77d89..30c03f4 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -630,6 +630,11 @@ enum { LOOK_MISC2 }; +enum { + EQUIP_SHIELD = 8, + EQUIP_WEAPON = 9 +}; + #define LOOK_LAST LOOK_MISC2 struct chat_data { @@ -692,6 +697,9 @@ extern FILE *map_logfile; void map_write_log(char *format, ...); #define MAP_LOG(format, args...) {if (map_logfile) map_write_log(format, ##args);} +#define MAP_LOG_PC(sd, fmt, args...) MAP_LOG("PC%d %d:%d,%d " fmt, sd->status.char_id, sd->bl.m, sd->bl.x, sd->bl.y, ## args) + + // 床アイテム関連 int map_clearflooritem_timer(int,unsigned int,int,int); #define map_clearflooritem(id) map_clearflooritem_timer(0,0,id,1) diff --git a/src/map/npc.c b/src/map/npc.c index 10d64db..1a0462f 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -996,8 +996,6 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list) pc_gainexp(sd,0,z); }*/ if (battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_DISCOUNT)) > 0) { - if (sd->status.skill[MC_DISCOUNT].flag != 0) - skill = sd->status.skill[MC_DISCOUNT].flag - 2; if (skill > 0) { z = (log(z * (double)skill) * (double)battle_config.shop_exp/100.); if (z < 1) @@ -1053,8 +1051,6 @@ int npc_selllist(struct map_session_data *sd,int n,unsigned short *item_list) pc_gainexp(sd,0,z); }*/ if (battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_OVERCHARGE)) > 0) { - if (sd->status.skill[MC_OVERCHARGE].flag != 0) - skill = sd->status.skill[MC_OVERCHARGE].flag - 2; if (skill > 0) { z = (log(z * (double)skill) * (double)battle_config.shop_exp/100.); if (z < 1) diff --git a/src/map/pc.c b/src/map/pc.c index 51165ea..5976137 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -38,8 +38,6 @@ #define STATE_BLIND 0x10 -#define MAP_LOG_PC(sd, fmt, args...) MAP_LOG("PC%d %d:%d,%d " fmt, sd->status.char_id, sd->bl.m, sd->bl.x, sd->bl.y, ## args) - #define MAP_LOG_STATS(sd, suffix) \ MAP_LOG_PC(sd, "STAT %d %d %d %d %d %d " suffix, \ sd->status.str, sd->status.agi, sd->status.vit, sd->status.int_, sd->status.dex, sd->status.luk) @@ -853,6 +851,7 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, short tmw_versio strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(501), gmtime(&connect_until_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S." clif_wis_message(sd->fd, wisp_server_name, tmpstr, strlen(tmpstr)+1); } + pc_calcstatus(sd,1); return 0; } @@ -875,23 +874,17 @@ int pc_authfail(int id) { static int pc_calc_skillpoint(struct map_session_data* sd) { - int i,skill,skill_point=0; + int i, skill_points = 0; nullpo_retr(0, sd); - for(i=1;i 0) { - if(skill_get_inf2(i)&0x01) { - if(!sd->status.skill[i].flag) - skill_point += skill; - else if(sd->status.skill[i].flag > 2 && sd->status.skill[i].flag != 13) { - skill_point += (sd->status.skill[i].flag - 2); - } - } - } - } + for (i = 0; i < skill_pool_skills_size; i++) { + int lv = sd->status.skill[skill_pool_skills[i]].lv; + if (lv) + skill_points += ((lv * (lv + 1)) >> 1) - 1; + } - return skill_point; + return skill_points; } /*========================================== @@ -1381,6 +1374,13 @@ int pc_calcstatus(struct map_session_data* sd,int first) } } + if (battle_is_unarmed(&sd->bl)) { + sd->watk += skill_power(sd, TMW_BRAWLING) / 3; // +66 for 200 + sd->watk2 += skill_power(sd, TMW_BRAWLING) >> 3; // +25 for 200 + sd->watk_ += skill_power(sd, TMW_BRAWLING) / 3; // +66 for 200 + sd->watk_2 += skill_power(sd, TMW_BRAWLING) >> 3; // +25 for 200 + } + if(sd->equip_index[10] >= 0){ // ソスソス index = sd->equip_index[10]; if(sd->inventory_data[index]){ //ソスワゑソスソスソスソスソスソスソスソスソスソスソストゑソスソスネゑソス @@ -1471,6 +1471,10 @@ int pc_calcstatus(struct map_session_data* sd,int first) sd->paramb[5]+= 5; } } + sd->speed -= skill_power(sd, TMW_SPEED) >> 3; + sd->aspd_rate -= skill_power(sd, TMW_SPEED) / 10; + if (sd->aspd_rate < 20) + sd->aspd_rate = 20; //1ソスxソスソスソスソスソスナなゑソスJob70ソスXソスpソスmソスrソスソス+10 if(s_class.job == 23 && sd->die_counter == 0 && sd->status.job_level >= 70){ @@ -2654,12 +2658,7 @@ int pc_skill(struct map_session_data *sd,int id,int level,int flag) clif_skillinfoblock(sd); } else if(sd->status.skill[id].lv < level){ // ソスoソスソスソスソスソスソスソス驍ェlvソスソスソスソスソスソスソスソスソスネゑソス - if(sd->status.skill[id].id==id) - sd->status.skill[id].flag=sd->status.skill[id].lv+2; // lvソスソスソスLソスソス - else { - sd->status.skill[id].id=id; - sd->status.skill[id].flag=1; // cardソスXソスLソスソスソスニゑソスソスソス - } + sd->status.skill[id].id=id; sd->status.skill[id].lv=level; } @@ -4358,6 +4357,7 @@ int pc_checkbaselevelup(struct map_session_data *sd) //ソスソスソスxソスソスソスAソスbソスvソスソスソスソスソスフでパソス[ソスeソスBソス[ソスソスソスソスソスソスソスXソスVソスソスソスソス //(ソスソスヘ囲チソスFソスbソスN) party_send_movemap(sd); + MAP_LOG_XP(sd, "LEVELUP") return 1; } @@ -4766,6 +4766,8 @@ int pc_skillup(struct map_session_data *sd,int skill_num) clif_skillup(sd,skill_num); clif_updatestatus(sd,SP_SKILLPOINT); clif_skillinfoblock(sd); + MAP_LOG_PC(sd, "SKILLUP %d %d %d", + skill_num, sd->status.skill[skill_num].lv, skill_power(sd, skill_num)); } return 0; @@ -4788,13 +4790,8 @@ int pc_allskillup(struct map_session_data *sd) c = s_class.job; s = (s_class.upper==1) ? 1 : 0 ; //ソス]ソスソスソスネ外ソスヘ通擾ソスソスフスソスLソスソスソスH - for(i=0;istatus.skill[i].id=0; - if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){ // cardソスXソスLソスソスソスネゑソスソスA - sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2; // ソス{ソスソスソスソスlvソスソス - sd->status.skill[i].flag=0; // flagソスソス0ソスノゑソスソストゑソスソスソス - } - } if (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill){ // ソスSソストのスソスLソスソス @@ -4963,23 +4960,14 @@ int pc_resetskill(struct map_session_data* sd) nullpo_retr(0, sd); - for(i=1;istatus.skill_point += pc_calc_skillpoint(sd); + + for(i=1;i 0) { - if(skill_get_inf2(i)&0x01) { - if(!sd->status.skill[i].flag) - sd->status.skill_point += skill; - else if(sd->status.skill[i].flag > 2 && sd->status.skill[i].flag != 13) { - sd->status.skill_point += (sd->status.skill[i].flag - 2); - } - sd->status.skill[i].lv = 0; - } - else if(battle_config.quest_skill_reset) - sd->status.skill[i].lv = 0; - sd->status.skill[i].flag = 0; - } - else sd->status.skill[i].lv = 0; - } + sd->status.skill[i].flags = 0; + } + clif_updatestatus(sd,SP_SKILLPOINT); clif_skillinfoblock(sd); pc_calcstatus(sd,0); diff --git a/src/map/script.c b/src/map/script.c index 87336a2..60ea879 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -3205,7 +3205,6 @@ int buildin_setskill(struct script_state *st) sd->status.skill[id].id = level? id : 0; sd->status.skill[id].lv = level; - sd->status.skill[id].flag = 0; clif_skillinfoblock(sd); return 0; } @@ -5524,7 +5523,7 @@ int buildin_getskilllist(struct script_state *st) if(sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0){ pc_setreg(sd,add_str("@skilllist_id")+(j<<24),sd->status.skill[i].id); pc_setreg(sd,add_str("@skilllist_lv")+(j<<24),sd->status.skill[i].lv); - pc_setreg(sd,add_str("@skilllist_flag")+(j<<24),sd->status.skill[i].flag); + pc_setreg(sd,add_str("@skilllist_flag")+(j<<24),sd->status.skill[i].flags); j++; } } @@ -5551,7 +5550,7 @@ buildin_get_activated_pool_skills(struct script_state *st) if (sd->status.skill[skill_id].id == skill_id) { pc_setreg(sd,add_str("@skilllist_id")+(count<<24),sd->status.skill[skill_id].id); pc_setreg(sd,add_str("@skilllist_lv")+(count<<24),sd->status.skill[skill_id].lv); - pc_setreg(sd,add_str("@skilllist_flag")+(count<<24),sd->status.skill[skill_id].flag); + pc_setreg(sd,add_str("@skilllist_flag")+(count<<24),sd->status.skill[skill_id].flags); pc_setregstr(sd, add_str("@skilllist_name$")+(count<<24), skill_name(skill_id)); ++count; } @@ -5579,7 +5578,7 @@ buildin_get_pool_skills(struct script_state *st) if (sd->status.skill[skill_id].id == skill_id) { pc_setreg(sd,add_str("@skilllist_id")+(count<<24),sd->status.skill[skill_id].id); pc_setreg(sd,add_str("@skilllist_lv")+(count<<24),sd->status.skill[skill_id].lv); - pc_setreg(sd,add_str("@skilllist_flag")+(count<<24),sd->status.skill[skill_id].flag); + pc_setreg(sd,add_str("@skilllist_flag")+(count<<24),sd->status.skill[skill_id].flags); pc_setregstr(sd, add_str("@skilllist_name$")+(count<<24), skill_name(skill_id)); ++count; } diff --git a/src/map/skill-pools.c b/src/map/skill-pools.c new file mode 100644 index 0000000..de7f04b --- /dev/null +++ b/src/map/skill-pools.c @@ -0,0 +1,165 @@ +#include +#include +#include +#include + +#include "timer.h" +#include "nullpo.h" +#include "malloc.h" +#include "magic.h" + +#include "battle.h" +#include "clif.h" +#include "intif.h" +#include "itemdb.h" +#include "map.h" +#include "mob.h" +#include "party.h" +#include "pc.h" +#include "script.h" +#include "skill.h" +#include "../common/socket.h" + +#ifdef MEMWATCH +#include "memwatch.h" +#endif + +int skill_pool_skills[MAX_POOL_SKILLS]; +int skill_pool_skills_size = 0; + +extern void +skill_pool_register(int id) +{ + if (skill_pool_skills_size + 1 >= MAX_POOL_SKILLS) { + fprintf(stderr, "Too many pool skills! Increase MAX_POOL_SKILLS and recompile."); + return; + } + + skill_pool_skills[skill_pool_skills_size++] = id; +} + + +char * +skill_name(int skill) +{ + if (skill > 0 && skill < MAX_SKILL_DB) + return skill_names[skill].desc; + else + return NULL; +} + +int +skill_pool(struct map_session_data *sd, int *skills) +{ + int i, count = 0; + + for (i = 0; count < MAX_SKILL_POOL && i < skill_pool_skills_size; i++) { + int skill_id = skill_pool_skills[i]; + if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED) { + if (skills) + skills[count] = skill_id; + ++count; + } + } + + return count; +} + +void +skill_pool_empty(struct map_session_data *sd) +{ + int i; + + for (i = 0; i < skill_pool_skills_size; i++) { + int skill_id = skill_pool_skills[i]; + sd->status.skill[skill_id].flags = 0; + } +} + +int skill_pool_size(struct map_session_data *sd) +{ + return skill_pool(sd, NULL); +} + +int +skill_pool_max(struct map_session_data *sd) +{ + return sd->status.skill[TMW_SKILLPOOL].lv; +} + + +int +skill_pool_activate(struct map_session_data *sd, int skill_id) +{ + if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED) + return 0; // Already there + else if (sd->status.skill[skill_id].id == skill_id // knows the skill + && (skill_pool_size(sd) < skill_pool_max(sd))) { + sd->status.skill[skill_id].flags |= SKILL_POOL_ACTIVATED; + MAP_LOG_PC(sd, "SKILL-ACTIVATE %d %d %d", skill_id, sd->status.skill[skill_id].lv, skill_power(sd, skill_id)); + return 0; + } + pc_calcstatus(sd, 0); + + return 1; // failed +} + +int +skill_pool_is_activated(struct map_session_data *sd, int skill_id) +{ + return sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED; +} + +int +skill_pool_deactivate(struct map_session_data *sd, int skill_id) +{ + if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED) { + sd->status.skill[skill_id].flags &= ~SKILL_POOL_ACTIVATED; + MAP_LOG_PC(sd, "SKILL-DEACTIVATE %d", skill_id); + pc_calcstatus(sd, 0); + return 0; + } + + return 1; +} + + +int +skill_stat(int skill_id) +{ + return skill_db[skill_id].stat; +} + +int +skill_power(struct map_session_data *sd, int skill_id) +{ + int stat = skill_stat(skill_id); + int stat_value, skill_value; + int result; + + if (stat == 0 + || !skill_pool_is_activated(sd, skill_id)) + return 0; + + stat_value = battle_get_stat(stat, &(sd->bl)); + skill_value = sd->status.skill[skill_id].lv; + + if ((skill_value * 10) - 1 > stat_value) + skill_value += (stat_value / 10); + else + skill_value *= 2; + + result = (skill_value * stat_value) / 10; + + return result; +} + + +int +skill_power_bl(struct block_list *bl, int skill) +{ + if (bl->type == BL_PC) + return skill_power((struct map_session_data *) bl, skill); + else + return 0; +} diff --git a/src/map/skill.c b/src/map/skill.c index 9e7d1d3..6cff936 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -722,11 +722,16 @@ static int rdamage; /* スキルデータベース */ struct skill_db skill_db[MAX_SKILL_DB]; +#define UNARMED_PLAYER_DAMAGE_MIN(bl) (skill_power_bl((bl), TMW_BRAWLING) >> 4) // +50 for 200 +#define UNARMED_PLAYER_DAMAGE_MAX(bl) (skill_power_bl((bl), TMW_BRAWLING)) // +200 for 200 + + int skill_get_hit( int id ){ return skill_db[id].hit; } int skill_get_inf( int id ){ return skill_db[id].inf; } int skill_get_pl( int id ){ return skill_db[id].pl; } int skill_get_nk( int id ){ return skill_db[id].nk; } int skill_get_max( int id ){ return skill_db[id].max; } +int skill_get_max_raise( int id ){ return skill_db[id].max_raise; } int skill_get_range( int id , int lv ){ return (lv <= 0) ? 0:skill_db[id].range[lv-1]; } int skill_get_hp( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].hp[lv-1]; } int skill_get_sp( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].sp[lv-1]; } @@ -10008,6 +10013,8 @@ int skill_readdb(void) char *s = skill_names[i].desc; while ((s = strchr(s, '_'))) *s = ' '; + if ((s = strchr(skill_names[i].desc, '\t')) || (s = strchr (skill_names[i].desc, ' ')) || (s = strchr (skill_names[i].desc, '\n'))) + *s = '\000'; } } fclose_(fp); diff --git a/src/map/skill.h b/src/map/skill.h index faff9a9..0f7b369 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -50,6 +50,7 @@ int skill_get_inf( int id ); int skill_get_pl( int id ); int skill_get_nk( int id ); int skill_get_max( int id ); +int skill_get_max_raise( int id ); int skill_get_range( int id , int lv ); int skill_get_hp( int id ,int lv ); int skill_get_mhp( int id ,int lv ); @@ -373,7 +374,7 @@ enum { MC_VENDING, MC_MAMMONITE, - AC_OWL, + AC_OWL = 45, AC_VULTURE, AC_CONCENTRATION, AC_DOUBLE, @@ -383,7 +384,7 @@ enum { TF_MISS, TF_STEAL, TF_HIDING, - TF_POISON, // 52 + TF_POISON, TF_DETOXIFY, ALL_RESURRECTION, @@ -691,12 +692,19 @@ enum { TMW_SKILLPOOL = 339, // skill pool size TMW_MAGIC = 340, - TMW_MAGIC_LIFE, - TMW_MAGIC_WAR, - TMW_MAGIC_TRANSMUTE, - TMW_MAGIC_NATURE, - TMW_MAGIC_ETHER, - TMW_MAGIC_END, + TMW_MAGIC_LIFE = 341, + TMW_MAGIC_WAR = 342, + TMW_MAGIC_TRANSMUTE = 343, + TMW_MAGIC_NATURE = 344, + TMW_MAGIC_ETHER = 345, + TMW_MAGIC_DARK = 346, + TMW_MAGIC_LIGHT = 347, + + TMW_BRAWLING = 350, + TMW_LUCKY_COUNTER = 351, + TMW_SPEED = 352, + TMW_RESIST_POISON = 353, + TMW_ASTRAL_SOUL = 354, LK_AURABLADE = 355, LK_PARRYING, @@ -832,17 +840,22 @@ enum { // Max. # of skills that may be classified as pool skills in db/skill_db.txt #define MAX_POOL_SKILLS 128 +extern int skill_pool_skills[MAX_POOL_SKILLS]; // All pool skills +extern int skill_pool_skills_size; // Number of entries in skill_pool_skills + int skill_pool(struct map_session_data *sd, int *skills); // Yields all active skills in the skill pool; no more than MAX_SKILL_POOL. Return is number of skills. int skill_pool_size(struct map_session_data *sd); int skill_pool_max(struct map_session_data *sd); // Max. number of pool skills void skill_pool_empty(struct map_session_data *sd); // Deactivate all pool skills int skill_pool_activate(struct map_session_data *sd, int skill); // Skill into skill pool. Return is zero iff okay. -int skill_pool_is_activated(struct map_session_data *sd, int skill); // Skill into skill pool. Return is nonzero when activated. +int skill_pool_is_activated(struct map_session_data *sd, int skill); // Skill into skill pool. Return is zero when activated. int skill_pool_deactivate(struct map_session_data *sd, int skill); // Skill out of skill pool. Return is zero iff okay. char *skill_name(int skill); // Yield configurable skill name int skill_stat(int skill); // Yields the stat associated with a skill. Returns zero if none, or SP_STR, SP_VIT, ... otherwise int skill_power(struct map_session_data *sd, int skill); // Yields the power of a skill. This is zero if the skill is unknown or if it's a pool skill that is outside of the skill pool, // otherwise a value from 0 to 255 (with 200 being the `normal maximum') +int skill_power_bl(struct block_list *bl, int skill); // Yields the power of a skill. This is zero if the skill is unknown or if it's a pool skill that is outside of the skill pool, + // otherwise a value from 0 to 255 (with 200 being the `normal maximum') #endif -- cgit v1.2.3-60-g2f50