diff options
Diffstat (limited to 'src/map/pc.cpp')
-rw-r--r-- | src/map/pc.cpp | 299 |
1 files changed, 205 insertions, 94 deletions
diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 9e76ecf..12af48f 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -127,71 +127,90 @@ int sp_coefficient_0 = 100; static //const earray<interval_t, ItemLook, ItemLook::COUNT> aspd_base_0 //= {{ -650_ms, // 0 NONE -700_ms, // 1 BLADE or some other common weapons -750_ms, // 2 -610_ms, // 3 SETZER_AND_SCYTHE -2000_ms, // 4 -2000_ms, // 5 -800_ms, // 6 Falchion -2000_ms, // 7 -700_ms, // 8 -700_ms, // 9 -650_ms, //10 STAFF / Sandcutter -900_ms, //11 BOW -2000_ms, //12 -2000_ms, //13 -2000_ms, //14 -2000_ms, //15 -2000_ms, //16 + 550_ms, // 0 { "Fist", W_FIST }, + 600_ms, // 1 { "Dagger", W_DAGGER }, + 650_ms, // 2 { "Sword", W_1HSWORD }, + 700_ms, // 3 { "TwoHandSword", W_2HSWORD }, + 650_ms, // 4 { "Spear", W_1HSPEAR }, + 700_ms, // 5 { "TwoHandSpear", W_2HSPEAR }, + 700_ms, // 6 { "Axe", W_1HAXE }, + 750_ms, // 7 { "TwoHandAxe", W_2HAXE }, + 700_ms, // 8 { "Mace", W_MACE }, + 750_ms, // 9 { "TwoHandMace", W_2HMACE }, + 700_ms, // 10 { "Rod", W_STAFF }, + 800_ms, // 11 { "Bow", W_BOW }, + 575_ms, // 12 { "Knuckle", W_KNUCKLE }, + 800_ms, // 13 { "Instrument", W_MUSICAL }, + 675_ms, // 14 { "Whip", W_WHIP }, + 700_ms, // 15 { "Book", W_BOOK }, + 600_ms, // 16 { "Katar", W_KATAR }, + 600_ms, // 17 { "Revolver", W_REVOLVER }, + 800_ms, // 18 { "Rifle", W_RIFLE }, + 500_ms, // 19 { "GatlingGun", W_GATLING }, + 1000_ms, // 20 { "Shotgun", W_SHOTGUN }, + 2000_ms, // 21 { "GrenadeLauncher", W_GRENADE }, + 650_ms, // 22 { "FuumaShuriken", W_HUUMA }, + 750_ms, // 23 { "TwoHandRod", W_2HSTAFF }, }}; static const int exp_table_0[MAX_LEVEL] = { - // 1 .. 9 + // 1 .. 10 9, 16, 25, 36, 77, 112, 153, 200, 253, - // 10 .. 19 + // 11 .. 20 320, 385, 490, 585, 700, 830, 970, 1120, 1260, 1420, - // 20 .. 29 + // 21 .. 30 1620, 1860, 1990, 2240, 2504, 2950, 3426, 3934, 4474, 6889, - // 30 .. 39 + // 31 .. 40 7995, 9174, 10425, 11748, 13967, 15775, 17678, 19677, 21773, 30543, - // 40 .. 49 + // 41 .. 50 34212, 38065, 42102, 46323, 53026, 58419, 64041, 69892, 75973, 102468, - // 50 .. 59 + // 51 .. 60 115254, 128692, 142784, 157528, 178184, 196300, 215198, 234879, 255341, 330188, - // 60 .. 69 + // 61 .. 70 365914, 403224, 442116, 482590, 536948, 585191, 635278, 687211, 740988, 925400, - // 70 .. 79 + // 71 .. 80 1473746, 1594058, 1718928, 1848355, 1982340, 2230113, 2386162, 2547417, 2713878, 3206160, - // 80 .. 89 + // 81 .. 90 3681024, 4022472, 4377024, 4744680, 5125440, 5767272, 6204000, 6655464, 7121664, 7602600, - // 90 .. 99 + // 91 .. 100 9738720, 11649960, 13643520, 18339300, 23836800, 35658000, 48687000, 58135000, 99999999, 103000000, - // 100 .. 109 + // 101 .. 110 107000000, 112000000, 116000000, 121000000, 125000000, 130000000, 134000000, 139000000, 145000000, 152200000, - // 110 .. 119 + // 111 .. 120 160840000, 171200000, 191930000, 202290000, 214720000, 229640000, 247550000, 283370000, 301280000, 322770000, - // 120 .. 129 + // 121 .. 130 348560000, 379500000, 417450000, 459195000, 505114500, 555625950, 622301064, 696977191, 780614454, 880533104, - // 130 .. 135 - 993241342, 1120376234, 1263784392, 1425548794, 1608019039, - 2147483647, 0 + // 131 .. 140 + 993241342, 1120376234, 1263784392, 1425548794, 1588019039, + 1680000000, 1780000000, 1890000000, 2010000000, 2140000000, + // 141 + 0 }; +// The old table contained a bug, actually max level was 136 and not 135 but to reach level 136 you must hit exactly the value 2147483647 +// else and overflow occurs and you lose all the progress of that level and start with level 135 at 0% again. +// I made a buffer that is great enough now I guess its 7483647 while looking through all gm logs I saw the highest values ever where 300%. +// A Xakelbael killed on 300% exp one time tabbed gives around 6 mil so I have a little buffer on top of that as well, it won't make it for +// 400% exp but since this will most likely never happen and the chance that one will make his lvl up with Xakelbael one time tabbed +// is extremely rare as well. + // 130 .. 135 + //993241342, 1120376234, 1263784392, 1425548794, 1608019039, + //2147483647, 0 + // is this *actually* used anywhere? static const @@ -694,7 +713,7 @@ int pc_setequipindex(dumb_ptr<map_session_data> sd) } OMATCH_CASE_NONE () { - sd->weapontype1 = ItemLook::NONE; + sd->weapontype1 = ItemLook::W_FIST; } } OMATCH_END (); @@ -786,13 +805,13 @@ void pc_set_attack_info(dumb_ptr<map_session_data> sd, interval_t speed, int ran if (speed == interval_t::zero()) { - pc_calcstatus(sd, 1); + pc_calcstatus(sd, (int)CalcStatusKind::INITIAL_CALC); clif_updatestatus(sd, SP::ASPD); clif_updatestatus(sd, SP::ATTACKRANGE); } else { - pc_calcstatus(sd, 9); + pc_calcstatus(sd, ((int)CalcStatusKind::INITIAL_CALC + (int)CalcStatusKind::MAGIC_OVERRIDE)); clif_updatestatus(sd, SP::ASPD); clif_updatestatus(sd, SP::ATTACKRANGE); } @@ -831,7 +850,7 @@ int pc_authok(AccountId id, int login_id2, ClientVersion client_version, sd->state.connect_new = 1; sd->bl_prev = sd->bl_next = nullptr; - sd->weapontype1 = ItemLook::NONE; + sd->weapontype1 = ItemLook::W_FIST; sd->speed = DEFAULT_WALK_SPEED; sd->state.dead_sit = 0; sd->dir = DIR::S; @@ -929,7 +948,7 @@ int pc_authok(AccountId id, int login_id2, ClientVersion client_version, sd->die_counter = pc_readglobalreg(sd, stringish<VarName>("PC_DIE_COUNTER"_s)); // ステータス初期計算など | Status initial calculation, etc. - pc_calcstatus(sd, 1); + pc_calcstatus(sd, (int)CalcStatusKind::INITIAL_CALC); if (pc_isGM(sd)) { @@ -962,7 +981,7 @@ int pc_authok(AccountId id, int login_id2, ClientVersion client_version, sd->packet_flood_reset_due = tick_t(); sd->packet_flood_in = 0; - pc_calcstatus(sd, 1); + pc_calcstatus(sd, (int)CalcStatusKind::INITIAL_CALC); if(sd->bl_m->mask > 0) clif_send_mask(sd, sd->bl_m->mask); @@ -1087,10 +1106,11 @@ void pc_set_weapon_look(dumb_ptr<map_session_data> sd) * Actively changed parameters should be send on their own * * First is a bitmask - * &1 = ? - * &2 = ? - * &4 = ? - * &8 = magic override + * &0 = Status Recalculation | ステータス再計算 + * &1 = Status initial calculation, etc.| ステータス初期計算など + * &2 = Recalculate item bonus (used in pc_checkitem but not handled in this function atm, so if function is called with first = 2 its basically first = 0 only) + * &4 = Status Recalculation but don't use any clif_updatestatus to send status to client (used by map_quit) + * &8 = magic override (used in pc_set_attack_info) *------------------------------------------ */ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) @@ -1115,11 +1135,11 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) b_weight = sd->weight; b_max_weight = sd->max_weight; earray<int, ATTR, ATTR::COUNT> b_paramb = sd->paramb; - earray<int, ATTR, ATTR::COUNT> b_parame = sd->paramc; + earray<int, ATTR, ATTR::COUNT> b_parame = sd->parame; earray<SkillValue, SkillID, MAX_SKILL> b_skill = sd->status.skill; b_hit = sd->hit; b_flee = sd->flee; - interval_t b_aspd = sd->aspd; + interval_t b_aspd = sd->aspd, b_base_weapon_delay_adjust = interval_t::zero(); b_watk = sd->watk; b_def = sd->def; b_watk2 = sd->watk2; @@ -1137,7 +1157,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->max_weight = max_weight_base_0 + sd->status.attrs[ATTR::STR] * 300; - if (first & 1) + if (first & (int)CalcStatusKind::INITIAL_CALC) { sd->weight = 0; for (IOff0 i : IOff0::iter()) @@ -1161,7 +1181,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->flee = 0; sd->flee2 = 0; sd->critical = 0; - sd->aspd = interval_t::zero(); + sd->aspd = sd->base_weapon_delay_adjust = interval_t::zero(); sd->watk = 0; sd->def = 0; sd->mdef = 0; @@ -1174,6 +1194,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->matk1 = 0; sd->matk2 = 0; sd->speed = DEFAULT_WALK_SPEED; + sd->speed_cap = interval_t::zero(); sd->hprate = 100; sd->sprate = 100; sd->dsprate = 100; @@ -1192,11 +1213,11 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->double_rate = 0; sd->atk_rate = sd->matk_rate = 100; sd->arrow_cri = 0; - sd->perfect_hit = 0; + sd->perfect_hit = sd->deadly_strike = 0; sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100; sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100; sd->speed_add_rate = sd->aspd_add_rate = 100; - sd->double_add_rate = sd->perfect_hit_add = 0; + sd->double_add_rate = sd->perfect_hit_add_rate = sd->deadly_strike_add_rate = 0; sd->hp_drain_rate = sd->hp_drain_per = sd->sp_drain_rate = sd->sp_drain_per = 0; @@ -1324,10 +1345,11 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (sd->attackrange < 1) sd->attackrange = 1; - if (sd->status.weapon == ItemLook::BOW) + if (sd->status.weapon == ItemLook::W_BOW) sd->attackrange += sd->arrow_range; sd->double_rate += sd->double_add_rate; - sd->perfect_hit += sd->perfect_hit_add; + sd->perfect_hit += sd->perfect_hit_add_rate; + sd->deadly_strike += sd->deadly_strike_add_rate; if (sd->speed_add_rate != 100) sd->speed_rate += sd->speed_add_rate - 100; if (sd->aspd_add_rate != 100) @@ -1341,7 +1363,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) for (ATTR attr : ATTRs) sd->paramc[attr] = std::max(0, sd->status.attrs[attr] + sd->paramb[attr] + sd->parame[attr]); - if (sd->status.weapon == ItemLook::BOW) + if (sd->status.weapon == ItemLook::W_BOW) { str = sd->paramc[ATTR::DEX]; dex = sd->paramc[ATTR::STR]; @@ -1356,6 +1378,13 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->base_atk += str + dstr * dstr + dex / 5 + sd->paramc[ATTR::LUK] / 5; sd->matk1 += sd->paramc[ATTR::INT] + (sd->paramc[ATTR::INT] / 5) * (sd->paramc[ATTR::INT] / 5); sd->matk2 += sd->paramc[ATTR::INT] + (sd->paramc[ATTR::INT] / 7) * (sd->paramc[ATTR::INT] / 7); + + if (sd->sc_data[StatusChange::SC_MATKPOT].timer) + { + sd->matk1 += sd->sc_data[StatusChange::SC_MATKPOT].val1; + sd->matk2 += sd->sc_data[StatusChange::SC_MATKPOT].val1; + } + if (sd->matk1 < sd->matk2) { int temp = sd->matk2; @@ -1435,9 +1464,12 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) //二刀流 ASPD 修正 | Two-cut ASPD correction { - sd->aspd += aspd_base_0[sd->status.weapon] + b_base_weapon_delay_adjust = aspd_base_0[sd->status.weapon] + sd->base_weapon_delay_adjust; + if (b_base_weapon_delay_adjust.count() < 0) + b_base_weapon_delay_adjust = interval_t::zero(); + sd->aspd += b_base_weapon_delay_adjust - (sd->paramc[ATTR::AGI] * 4 + sd->paramc[ATTR::DEX]) - * aspd_base_0[sd->status.weapon] / 1000; + * b_base_weapon_delay_adjust / 1000; } aspd_rate = sd->aspd_rate; @@ -1507,11 +1539,6 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (sd->sc_data[StatusChange::SC_ATKPOT].timer) sd->watk += sd->sc_data[StatusChange::SC_ATKPOT].val1; - if (sd->sc_data[StatusChange::SC_MATKPOT].timer) - { - sd->matk1 += sd->sc_data[StatusChange::SC_MATKPOT].val1; - sd->matk2 += sd->sc_data[StatusChange::SC_MATKPOT].val1; - } if (sd->sc_data[StatusChange::SC_SPEEDPOTION0].timer) aspd_rate -= sd->sc_data[StatusChange::SC_SPEEDPOTION0].val1; @@ -1528,17 +1555,20 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (sd->speed_rate != 100) sd->speed = sd->speed * sd->speed_rate / 100; sd->speed = std::max(sd->speed, 1_ms); + if (sd->speed_cap < interval_t::zero()) + sd->speed_cap = interval_t::zero(); + if (sd->speed < sd->speed_cap) + sd->speed = sd->speed_cap; + if (aspd_rate != 100) + sd->aspd = sd->aspd * aspd_rate / 100; /* Magic speed */ - if (sd->attack_spell_override || first & 8) + if (sd->attack_spell_override || first & (int)CalcStatusKind::MAGIC_OVERRIDE) sd->aspd = sd->attack_spell_delay; - if (aspd_rate != 100) - sd->aspd = sd->aspd * aspd_rate / 100; - - /* Red Threshold Calculation (TODO) */ + /* Red Threshold Calculation */ if (sd->aspd < 300_ms) { - sd->aspd = 300_ms + ((sd->aspd - 300_ms) * 20 / 20); + sd->aspd = 300_ms + ((sd->aspd - 300_ms) * 19 / 20); } sd->aspd = std::max(sd->aspd, battle_config.max_aspd); @@ -1551,14 +1581,14 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (sd->status.sp > sd->status.max_sp) sd->status.sp = sd->status.max_sp; - if (first & 4) + if (first & (int)CalcStatusKind::NORMAL_RECALC_NO_CLIENT_UPDATE) return 0; - if (first & 3) + if (first & ((int)CalcStatusKind::INITIAL_CALC + (int)CalcStatusKind::ITEM_BONUS_RECALC)) // never executed atm { clif_updatestatus(sd, SP::SPEED); clif_updatestatus(sd, SP::MAXHP); clif_updatestatus(sd, SP::MAXSP); - if (first & 1) + if (first & (int)CalcStatusKind::INITIAL_CALC) // its always 1 here if first is 3 so this if is not needed normally { clif_updatestatus(sd, SP::HP); clif_updatestatus(sd, SP::SP); @@ -1792,7 +1822,7 @@ int pc_bonus(dumb_ptr<map_session_data> sd, SP type, int val) break; case SP::PERFECT_HIT_ADD_RATE: if (!sd->state.lr_flag_is_arrow_2) - sd->perfect_hit_add += val; + sd->perfect_hit_add_rate += val; break; case SP::CRITICAL_RATE: if (!sd->state.lr_flag_is_arrow_2) @@ -1829,6 +1859,41 @@ int pc_bonus(dumb_ptr<map_session_data> sd, SP type, int val) case SP::DEAF: sd->special_state.deaf = 1; break; + case SP::SPEED_CAP: + if (!sd->state.lr_flag_is_arrow_2) + // highest value (slowest speed) is taken others are ignored + if (sd->speed_cap < interval_t(val)) + sd->speed_cap = interval_t(val); + break; + case SP::ALL_STATS: + sd->parame[ATTR::STR] += val; + sd->parame[ATTR::AGI] += val; + sd->parame[ATTR::VIT] += val; + sd->parame[ATTR::INT] += val; + sd->parame[ATTR::DEX] += val; + sd->parame[ATTR::LUK] += val; + break; + case SP::AGI_VIT: + sd->parame[ATTR::AGI] += val; + sd->parame[ATTR::VIT] += val; + break; + case SP::AGI_DEX_STR: + sd->parame[ATTR::AGI] += val; + sd->parame[ATTR::DEX] += val; + sd->parame[ATTR::STR] += val; + break; + case SP::DEADLY_STRIKE_RATE: + if (!sd->state.lr_flag_is_arrow_2 && sd->deadly_strike < val) + sd->deadly_strike = val; + break; + case SP::DEADLY_STRIKE_ADD_RATE: + if (!sd->state.lr_flag_is_arrow_2) + sd->deadly_strike_add_rate += val; + break; + case SP::BASE_WEAPON_DELAY_ADJUST: + if (!sd->state.lr_flag_is_arrow_2) + sd->base_weapon_delay_adjust += interval_t(val); + break; default: if (battle_config.error_log) PRINTF("pc_bonus: unknown type %d %d !\n"_fmt, @@ -1840,6 +1905,7 @@ int pc_bonus(dumb_ptr<map_session_data> sd, SP type, int val) /*========================================== * ソスソス ソスソスソスiソスノゑソスソスソスソス\ソスヘ難ソスソスフボソス[ソスiソスXソスン抵ソス + * sos sos sos sos sos i sos no sos sos sos sos\ *------------------------------------------ */ int pc_bonus2(dumb_ptr<map_session_data> sd, SP type, int type2, int val) @@ -1889,7 +1955,7 @@ int pc_skill(dumb_ptr<map_session_data> sd, SkillID id, int level, int flag) if (!flag && (sd->status.skill[id].lv || level == 0)) { sd->status.skill[id].lv = level; - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); clif_skillinfoblock(sd); } else if (sd->status.skill[id].lv < level) @@ -2341,6 +2407,13 @@ int pc_useitem(dumb_ptr<map_session_data> sd, IOff0 n) clif_useitemack(sd, n, amount - 1, 1); pc_delitem(sd, n, 1, 1); + // activity + if (sd) + if (sd->activity.items_used == 2147483647) + sd->activity.items_used = 1; + else + sd->activity.items_used++; + run_script(ScriptPointer(script, 0), sd->bl_id, BlockId()); } OMATCH_END (); @@ -2664,6 +2737,13 @@ int pc_walktoxy_sub(dumb_ptr<map_session_data> sd) } clif_movechar(sd); + // activity + if (sd) + if (sd->activity.tiles_walked == 2147483647) + sd->activity.tiles_walked = 1; + else + sd->activity.tiles_walked++; + return 0; } @@ -2841,14 +2921,14 @@ void pc_attack_timer(TimerData *, tick_t tick, BlockId id) sd->attack_spell_override = BlockId(); pc_set_weapon_icon(sd, 0, StatusChange::ZERO, ItemNameId()); pc_set_attack_info(sd, interval_t::zero(), 0); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); } } else { dist = distance(sd->bl_x, sd->bl_y, bl->bl_x, bl->bl_y); range = sd->attackrange; - if (sd->status.weapon != ItemLook::BOW) + if (sd->status.weapon != ItemLook::W_BOW) range++; if (dist > range) { //届 かないので移動 | Move because it does not arrive @@ -2977,7 +3057,7 @@ int pc_checkbaselevelup(dumb_ptr<map_session_data> sd) clif_updatestatus(sd, SP::STATUSPOINT); clif_updatestatus(sd, SP::BASELEVEL); clif_updatestatus(sd, SP::NEXTBASEEXP); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); pc_heal(sd, sd->status.max_hp, sd->status.max_sp, true); clif_misceffect(sd, 0); @@ -3036,7 +3116,7 @@ int pc_checkjoblevelup(dumb_ptr<map_session_data> sd) { // [Fate] Bah, this is is painful. // But the alternative is quite error-prone, and eAthena has far worse performance issues... sd->status.job_exp = next - 1; - pc_calcstatus(sd,0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); return 0; } @@ -3045,7 +3125,7 @@ int pc_checkjoblevelup(dumb_ptr<map_session_data> sd) clif_updatestatus(sd, SP::NEXTJOBEXP); sd->status.skill_point++; clif_updatestatus(sd, SP::SKILLPOINT); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); MAP_LOG_PC(sd, "SKILLPOINTS-UP %d"_fmt, sd->status.skill_point); @@ -3282,7 +3362,7 @@ int pc_statusup(dumb_ptr<map_session_data> sd, SP type) } clif_updatestatus(sd, SP::STATUSPOINT); clif_updatestatus(sd, type); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); clif_statusupack(sd, type, 1, val); MAP_LOG_STATS(sd, "STATUP"_fmt); @@ -3311,7 +3391,7 @@ int pc_statusup2(dumb_ptr<map_session_data> sd, SP type, int val) sd->status.attrs[attr] = val; clif_updatestatus(sd, sp_to_usp(type)); clif_updatestatus(sd, type); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); clif_statusupack(sd, type, 1, val); MAP_LOG_STATS(sd, "STATUP2"_fmt); @@ -3334,7 +3414,7 @@ int pc_skillup(dumb_ptr<map_session_data> sd, SkillID skill_num) sd->status.skill_point -= sd->status.skill[skill_num].lv; sd->status.skill[skill_num].lv++; - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); clif_skillup(sd, skill_num); clif_updatestatus(sd, SP::SKILLPOINT); clif_skillinfoblock(sd); @@ -3366,7 +3446,7 @@ int pc_resetstate(dumb_ptr<map_session_data> sd) for (ATTR attr : ATTRs) clif_updatestatus(sd, attr_to_usp(attr)); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); return 0; } @@ -3392,7 +3472,7 @@ int pc_resetskill(dumb_ptr<map_session_data> sd) clif_updatestatus(sd, SP::SKILLPOINT); clif_skillinfoblock(sd); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); return 0; } @@ -3485,7 +3565,7 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, pc_set_weapon_icon(sd, 0, StatusChange::ZERO, ItemNameId()); pc_set_attack_info(sd, interval_t::zero(), 0); } - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); if (battle_config.death_penalty_type > 0 && sd->status.base_level >= 20) { @@ -3785,6 +3865,21 @@ int pc_readparam(dumb_ptr<block_list> bl, SP type) case SP::MUTE_GUILD: val = sd ? sd->mute.guild : 0; break; + case SP::KILLS: + val = sd->activity.kills; + break; + case SP::CASTS: + val = sd->activity.casts; + break; + case SP::ITEMS_USED: + val = sd->activity.items_used; + break; + case SP::TILES_WALKED: + val = sd->activity.tiles_walked; + break; + case SP::ATTACKS: + val = sd->activity.attacks; + break; case SP::AUTOMOD: val = sd ? static_cast<int>(sd->automod) : 0; break; @@ -3835,7 +3930,7 @@ int pc_setparam(dumb_ptr<block_list> bl, SP type, int val) clif_updatestatus(sd, SP::NEXTBASEEXP); clif_updatestatus(sd, SP::STATUSPOINT); clif_updatestatus(sd, SP::BASEEXP); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); pc_heal(sd, sd->status.max_hp, sd->status.max_sp, true); break; case SP::JOBLEVEL: @@ -3853,7 +3948,7 @@ int pc_setparam(dumb_ptr<block_list> bl, SP type, int val) clif_updatestatus(sd, SP::JOBLEVEL); clif_updatestatus(sd, SP::NEXTJOBEXP); clif_updatestatus(sd, SP::JOBEXP); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); break; case SP::CLASS: // TODO: mob class change @@ -3933,7 +4028,7 @@ int pc_setparam(dumb_ptr<block_list> bl, SP type, int val) && !pc_isequip(sd, j)) pc_unequipitem(sd, j, CalcStatus::LATER); } - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); chrif_save(sd); clif_fixpcpos(sd); } @@ -4034,6 +4129,22 @@ int pc_setparam(dumb_ptr<block_list> bl, SP type, int val) nullpo_retz(sd); sd->mute.guild = (val == 1); break; + // atm only setting of casts is needed since magic is handled in serverdata but I let the others here as well for whatever reason + case SP::KILLS: + sd->activity.kills = val; + break; + case SP::CASTS: + sd->activity.casts = val; + break; + case SP::ITEMS_USED: + sd->activity.items_used = val; + break; + case SP::TILES_WALKED: + sd->activity.tiles_walked = val; + break; + case SP::ATTACKS: + sd->activity.attacks = val; + break; case SP::AUTOMOD: nullpo_retz(sd); sd->automod = static_cast<AutoMod>(val); @@ -4413,7 +4524,7 @@ int pc_setglobalreg(dumb_ptr<map_session_data> sd, VarName reg, int val) if (reg == stringish<VarName>("PC_DIE_COUNTER"_s) && sd->die_counter != val) { sd->die_counter = val; - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); } Option<P<struct quest_data>> quest_data_ = questdb_searchname(var); OMATCH_BEGIN_SOME(quest_data, quest_data_) @@ -4780,11 +4891,11 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, IOff0 n, EPOS) sd->status.inventory[n].equip = pos; ItemNameId view_i; - ItemLook view_l = ItemLook::NONE; + ItemLook view_l = ItemLook::W_FIST; // TODO: This is ugly. OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[n]) { - bool look_not_weapon = sdidn->look == ItemLook::NONE; + bool look_not_weapon = sdidn->look == ItemLook::W_FIST; bool equip_is_weapon = bool(sd->status.inventory[n].equip & EPOS::WEAPON); assert (look_not_weapon != equip_is_weapon); @@ -4844,7 +4955,7 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, IOff0 n, EPOS) } pc_signal_advanced_equipment_change(sd, n); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); return 0; } @@ -4873,9 +4984,9 @@ int pc_unequipitem(dumb_ptr<map_session_data> sd, IOff0 n, CalcStatus type) } if (bool(sd->status.inventory[n].equip & EPOS::WEAPON)) { - sd->weapontype1 = ItemLook::NONE; + sd->weapontype1 = ItemLook::W_FIST; // when reading the diff, think twice about this - sd->status.weapon = ItemLook::NONE; + sd->status.weapon = ItemLook::W_FIST; pc_calcweapontype(sd); pc_set_weapon_look(sd); } @@ -4911,7 +5022,7 @@ int pc_unequipitem(dumb_ptr<map_session_data> sd, IOff0 n, CalcStatus type) } if (type == CalcStatus::NOW) { - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); } return 0; @@ -4984,7 +5095,7 @@ int pc_checkitem(dumb_ptr<map_session_data> sd) pc_setequipindex(sd); if (calc_flag) - pc_calcstatus(sd, 2); + pc_calcstatus(sd, (int)CalcStatusKind::ITEM_BONUS_RECALC); return 0; } @@ -5369,7 +5480,7 @@ void pc_natural_heal_sub(dumb_ptr<map_session_data> sd) if (sd->spellpower_bonus_target < sd->spellpower_bonus_current) { sd->spellpower_bonus_current = sd->spellpower_bonus_target; - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); } else if (sd->spellpower_bonus_target > sd->spellpower_bonus_current) { @@ -5377,7 +5488,7 @@ void pc_natural_heal_sub(dumb_ptr<map_session_data> sd) 1 + ((sd->spellpower_bonus_target - sd->spellpower_bonus_current) >> 5); - pc_calcstatus(sd, 0); + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); } if (sd->sc_data[StatusChange::SC_HALT_REGENERATE].timer) |