diff options
-rw-r--r-- | src/map/atcommand.cpp | 89 | ||||
-rw-r--r-- | src/map/magic-stmt.cpp | 4 | ||||
-rw-r--r-- | src/map/map.hpp | 3 | ||||
-rw-r--r-- | src/map/npc-parse.cpp | 5 | ||||
-rw-r--r-- | src/map/npc.cpp | 21 | ||||
-rw-r--r-- | src/map/npc.hpp | 2 | ||||
-rw-r--r-- | src/map/pc.cpp | 43 | ||||
-rw-r--r-- | src/map/pc.hpp | 2 | ||||
-rw-r--r-- | src/map/script-fun.cpp | 183 | ||||
-rw-r--r-- | src/map/tmw.cpp | 4 | ||||
-rwxr-xr-x | tools/config.py | 2 |
11 files changed, 217 insertions, 141 deletions
diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index cd51b70..f226706 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -4030,81 +4030,40 @@ ATCE atcommand_character_storage_list(Session *s, dumb_ptr<map_session_data> sd, } static -ATCE atcommand_killer(Session *s, dumb_ptr<map_session_data> sd, +ATCE atcommand_pvp(Session *s, dumb_ptr<map_session_data> sd, ZString) { - sd->special_state.killer = !sd->special_state.killer; - - if (sd->special_state.killer) - clif_displaymessage(s, "You be a killa..."_s); - else - clif_displaymessage(s, "You gonna be own3d..."_s); - - return ATCE::OKAY; -} - -static -ATCE atcommand_charkiller(Session *s, dumb_ptr<map_session_data>, - ZString message) -{ - CharName character; - - if (!asplit(message, &character)) - return ATCE::USAGE; - - dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); - if (pl_sd == nullptr) - return ATCE::EXIST; - - pl_sd->special_state.killer = !pl_sd->special_state.killer; + int chan = sd->state.pvpchannel; + if (sd->pvp_timer || (chan > 1)) + return ATCE::OKAY; - if (pl_sd->special_state.killer) - { - clif_displaymessage(s, "The player is now a killer"_s); - clif_displaymessage(pl_sd->sess, "You are now a killer"_s); - } - else - { - clif_displaymessage(s, "The player is no longer a killer"_s); - clif_displaymessage(pl_sd->sess, "You are no longer a killer"_s); + if (chan < 1) { + sd->state.pvpchannel = 1; + clif_displaymessage(s, "##3PvP : ##BOn"_s); + } else { + sd->state.pvpchannel = 0; + clif_displaymessage(s, "##3PvP : ##BOff"_s); } + pc_setpvptimer(sd, battle_config.player_pvp_time); return ATCE::OKAY; } static -ATCE atcommand_killable(Session *s, dumb_ptr<map_session_data> sd, - ZString) -{ - sd->special_state.killable = !sd->special_state.killable; - - if (sd->special_state.killable) - clif_displaymessage(s, "You gonna be own3d..."_s); - else - clif_displaymessage(s, "You be a killa..."_s); - - return ATCE::OKAY; -} - -static -ATCE atcommand_charkillable(Session *s, dumb_ptr<map_session_data>, +ATCE atcommand_charpvp(Session *, dumb_ptr<map_session_data>, ZString message) { CharName character; + int channel; - if (!asplit(message, &character)) + if (!extract(message, record<' '>(&character, &channel))) return ATCE::USAGE; dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); if (pl_sd == nullptr) return ATCE::EXIST; - pl_sd->special_state.killable = !pl_sd->special_state.killable; - - if (pl_sd->special_state.killable) - clif_displaymessage(s, "The player is now killable"_s); - else - clif_displaymessage(s, "The player is no longer killable"_s); + pl_sd->state.pvpchannel = channel; return ATCE::OKAY; } @@ -5236,21 +5195,15 @@ Map<XString, AtCommandInfo> atcommand_info = {"addwarp"_s, {"<mapname> <x> <y>"_s, 80, atcommand_addwarp, "Create a new permanent warp"_s}}, - {"killer"_s, {""_s, - 60, atcommand_killer, - "Toggle whether you are a killer"_s}}, - {"charkiller"_s, {"<charname>"_s, - 60, atcommand_charkiller, - "Toggle whether a player is a killer"_s}}, + {"pvp"_s, {""_s, + 0, atcommand_pvp, + "Toggle your pvp flag"_s}}, {"npcmove"_s, {"<x> <y> <npc-name>"_s, 80, atcommand_npcmove, "Force an NPC to move on the map"_s}}, - {"killable"_s, {""_s, - 60, atcommand_killable, - "Toggle whether you are killable"_s}}, - {"charkillable"_s, {"<charname>"_s, - 60, atcommand_charkillable, - "Toggle whether a player is killable"_s}}, + {"charpvp"_s, {"<charname> <channel>"_s, + 40, atcommand_charpvp, + "Set the pvp channel of another player"_s}}, {"chareffect"_s, {"<type> <target>"_s, 40, atcommand_chareffect, "Apply effect type with arg 0 to a player"_s}}, diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp index c69dafa..fdeac3a 100644 --- a/src/map/magic-stmt.cpp +++ b/src/map/magic-stmt.cpp @@ -773,8 +773,8 @@ int op_injure(dumb_ptr<env_t> env, Slice<val_t> args) if (target->bl_type == BL::PC && !target->bl_m->flag.get(MapFlag::PVP) - && !target->is_player()->special_state.killable - && (caster->bl_type != BL::PC || !caster->is_player()->special_state.killer)) + && (caster->bl_type != BL::PC) + && ((caster->is_player()->state.pvpchannel > 1) && (target->is_player()->state.pvpchannel != caster->is_player()->state.pvpchannel))) return 0; /* Cannot damage other players outside of pvp */ if (target != caster) diff --git a/src/map/map.hpp b/src/map/map.hpp index 3dd03e7..f57dcee 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -142,11 +142,10 @@ struct map_session_data : block_list, SessionData unsigned shroud_disappears_on_pickup:1; unsigned shroud_disappears_on_talk:1; unsigned seen_motd:1; + unsigned pvpchannel; } state; struct { - unsigned killer:1; - unsigned killable:1; unsigned unbreakable_weapon:1; unsigned unbreakable_armor:1; unsigned deaf:1; diff --git a/src/map/npc-parse.cpp b/src/map/npc-parse.cpp index bdb212c..443a1e7 100644 --- a/src/map/npc-parse.cpp +++ b/src/map/npc-parse.cpp @@ -154,10 +154,7 @@ bool npc_load_warp(ast::npc::Warp& warp) nd->flag = 0; nd->name = warp.name.data; - if (!battle_config.warp_point_debug) - nd->npc_class = WARP_CLASS; - else - nd->npc_class = WARP_DEBUG_CLASS; + nd->npc_class = WARP_CLASS; nd->speed = 200_ms; nd->option = Opt0::ZERO; nd->opt1 = Opt1::ZERO; diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 3320039..56c33cc 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -482,27 +482,6 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, return 0; } -static -void npc_command_sub(NpcEvent key, struct event_data *ev, NpcName npcname, XString command) -{ - if (ev->nd->name == npcname - && key.label.startswith("OnCommand"_s)) - { - XString temp = key.label.xslice_t(9); - - if (command == temp) - run_script(ScriptPointer(borrow(*ev->nd->scr.script), ev->pos), BlockId(), ev->nd->bl_id); - } -} - -int npc_command(dumb_ptr<map_session_data>, NpcName npcname, XString command) -{ - for (auto& pair : ev_db) - npc_command_sub(pair.first, &pair.second, npcname, command); - - return 0; -} - /*========================================== * 接触型のNPC処理 *------------------------------------------ diff --git a/src/map/npc.hpp b/src/map/npc.hpp index c856a8c..b587f5f 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -41,12 +41,10 @@ constexpr BlockId START_NPC_NUM = wrap<BlockId>(110000000); // TODO make these species, see npc_class in npc_data constexpr Species WARP_CLASS = wrap<Species>(45); constexpr Species FAKE_NPC_CLASS = wrap<Species>(127); -constexpr Species WARP_DEBUG_CLASS = wrap<Species>(722); constexpr Species INVISIBLE_CLASS = wrap<Species>(32767); int npc_event_dequeue(dumb_ptr<map_session_data> sd); int npc_event(dumb_ptr<map_session_data> sd, NpcEvent npcname, int); -int npc_command(dumb_ptr<map_session_data> sd, NpcName npcname, XString command); int npc_touch_areanpc(dumb_ptr<map_session_data>, Borrowed<map_local>, int, int); int npc_click(dumb_ptr<map_session_data>, BlockId); int npc_scriptcont(dumb_ptr<map_session_data>, BlockId); diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 95fabde..e73d79f 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -288,16 +288,12 @@ int pc_iskiller(dumb_ptr<map_session_data> src, { nullpo_retz(src); - if (src->bl_type != BL::PC) + if (src->bl_type != BL::PC || target->bl_type != BL::PC) return 0; - if (src->special_state.killer) + if ((src->state.pvpchannel == 1) && (target->state.pvpchannel == 1) && !src->bl_m->flag.get(MapFlag::NOPVP)) return 1; - - if (target->bl_type != BL::PC) - return 0; - if (target->special_state.killable) + if ((src->state.pvpchannel > 1) && (target->state.pvpchannel == src->state.pvpchannel)) // this one does not respect NOPVP return 1; - return 0; } @@ -320,6 +316,33 @@ int distance(int x0, int y0, int x1, int y1) } static +void pc_pvp_timer(TimerData *, tick_t, BlockId id) +{ + dumb_ptr<map_session_data> sd = map_id2sd(id); + + assert (sd != nullptr); + assert (sd->bl_type == BL::PC); +} + +int pc_setpvptimer(dumb_ptr<map_session_data> sd, interval_t val) +{ + nullpo_retz(sd); + + sd->pvp_timer = Timer(gettick() + val, + std::bind(pc_pvp_timer, ph::_1, ph::_2, + sd->bl_id)); + return 0; +} + +int pc_delpvptimer(dumb_ptr<map_session_data> sd) +{ + nullpo_retz(sd); + + sd->pvp_timer.cancel(); + return 0; +} + +static void pc_invincible_timer(TimerData *, tick_t, BlockId id) { dumb_ptr<map_session_data> sd = map_id2sd(id); @@ -378,7 +401,6 @@ int pc_setrestartvalue(dumb_ptr<map_session_data> sd, int type) clif_updatestatus(sd, SP::SP); sd->heal_xp = 0; // [Fate] Set gainable xp for healing this player to 0 - return 0; } @@ -899,6 +921,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) int bl; int aspd_rate, refinedef = 0; int str, dstr, dex; + int b_pvpchannel = 0; nullpo_retz(sd); @@ -927,6 +950,8 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) b_mdef = sd->mdef; b_mdef2 = sd->mdef2; b_base_atk = sd->base_atk; + if (!pc_isdead(sd) && sd->state.pvpchannel == 1) + b_pvpchannel = sd->state.pvpchannel; sd->max_weight = max_weight_base_0 + sd->status.attrs[ATTR::STR] * 300; @@ -1399,6 +1424,8 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) clif_updatestatus(sd, SP::HP); if (b_sp != sd->status.sp) clif_updatestatus(sd, SP::SP); + if (b_pvpchannel != sd->state.pvpchannel) + sd->state.pvpchannel = b_pvpchannel; return 0; } diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 4bca255..14829d1 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -169,6 +169,8 @@ void pc_setstand(dumb_ptr<map_session_data> sd); void pc_cleanup(dumb_ptr<map_session_data> sd); // [Fate] Clean up after a logged-out PC int pc_read_gm_account(Session *, const std::vector<Packet_Repeat<0x2b15>>&); +int pc_setpvptimer(dumb_ptr<map_session_data> sd, interval_t); +int pc_delpvptimer(dumb_ptr<map_session_data> sd); int pc_setinvincibletimer(dumb_ptr<map_session_data> sd, interval_t); int pc_delinvincibletimer(dumb_ptr<map_session_data> sd); int pc_logout(dumb_ptr<map_session_data> sd); // [fate] Player logs out diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp index 919bf90..3b814aa 100644 --- a/src/map/script-fun.cpp +++ b/src/map/script-fun.cpp @@ -1538,25 +1538,6 @@ void builtin_killmonster(ScriptState *st) BL::MOB); } -static -void builtin_killmonsterall_sub(dumb_ptr<block_list> bl) -{ - mob_delete(bl->is_mob()); -} - -static -void builtin_killmonsterall(ScriptState *st) -{ - MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); - - P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return); - map_foreachinarea(builtin_killmonsterall_sub, - m, - 0, 0, - m->xs, m->ys, - BL::MOB); -} - /*========================================== * NPC主体イベント実行 *------------------------------------------ @@ -2159,6 +2140,37 @@ void builtin_pvpoff(ScriptState *st) } } +static +void builtin_setpvpchannel(ScriptState *st) +{ + dumb_ptr<map_session_data> sd = script_rid2sd(st); + int flag; + flag = conv_num(st, &AARG(0)); + if (flag < 1) + flag = 0; + + sd->state.pvpchannel = flag; +} + +static +void builtin_getpvpflag(ScriptState *st) +{ + dumb_ptr<map_session_data> sd = script_rid2sd(st); + int num = conv_num(st, &AARG(0)); + int flag = 0; + + switch (num){ + case 0: + flag = sd->state.pvpchannel; + break; + case 1: + flag = bool(sd->status.option & Opt0::HIDE); + break; + } + + push_int<ScriptDataInt>(st->stack, flag); +} + /*========================================== * NPCエモーション *------------------------------------------ @@ -2169,7 +2181,7 @@ void builtin_emotion(ScriptState *st) { int type; type = conv_num(st, &AARG(0)); - if (type < 0 || type > 100) + if (type < 0 || type > 200) return; clif_emotion(map_id2bl(st->oid), type); } @@ -2198,15 +2210,6 @@ void builtin_mapwarp(ScriptState *st) // Added by RoVeRT } static -void builtin_cmdothernpc(ScriptState *st) // Added by RoVeRT -{ - NpcName npc = stringish<NpcName>(ZString(conv_str(st, &AARG(0)))); - ZString command = ZString(conv_str(st, &AARG(1))); - - npc_command(map_id2sd(st->rid), npc, command); -} - -static void builtin_mobcount_sub(dumb_ptr<block_list> bl, NpcEvent event, int *c) { if (event == bl->is_mob()->npc_event) @@ -2295,6 +2298,31 @@ void builtin_getitemname(ScriptState *st) } static +void builtin_getitemlink(ScriptState *st) +{ + struct script_data *data; + AString buf; + data = &AARG(0); + ZString name = conv_str(st, data); + + ItemNameId item_id; + Option<P<struct item_data>> item_data_ = itemdb_searchname(name); + OMATCH_BEGIN (item_data_) + { + OMATCH_CASE_SOME (item_data) + { + buf = STRPRINTF("[@@%d|%s@@]"_fmt, item_data->nameid, item_data->jname); + } + OMATCH_CASE_NONE () + { + buf = STRPRINTF("Unknown Item: %s"_fmt, name); + } + } + OMATCH_END (); + push_str<ScriptDataStr>(st->stack, buf); +} + +static void builtin_getspellinvocation(ScriptState *st) { RString name = conv_str(st, &AARG(0)); @@ -2968,6 +2996,95 @@ void builtin_getmap(ScriptState *st) push_str<ScriptDataStr>(st->stack, sd->bl_m->name_); } +/* + * Get the NPC's info + */ +static +void builtin_strnpcinfo(ScriptState *st) +{ + int num = conv_num(st, &AARG(0)); + RString name; + dumb_ptr<npc_data> nd; + + if(HARG(1)){ + NpcName npc = stringish<NpcName>(ZString(conv_str(st, &AARG(1)))); + nd = npc_name2id(npc); + if (!nd) + { + PRINTF("builtin_strnpcinfo: no such npc: %s\n"_fmt, npc); + return; + } + } else { + nd = map_id_is_npc(st->oid); + } + + switch(num) + { + case 0: + name = nd->name; + break; + case 1: + name = nd->name.xislice_h(std::find(nd->name.begin(), nd->name.end(), '#')); + break; + case 2: + name = nd->name.xislice_t(std::find(nd->name.begin(), nd->name.end(), '#')); + break; + case 3: + name = nd->bl_m->name_; + break; + } + + push_str<ScriptDataStr>(st->stack, name); +} + +/*============================ + * Gets the NPC's x pos + *---------------------------- + */ +static +void builtin_getnpcx(ScriptState *st) +{ + dumb_ptr<npc_data> nd; + + if(HARG(0)){ + NpcName name = stringish<NpcName>(ZString(conv_str(st, &AARG(0)))); + nd = npc_name2id(name); + if (!nd) + { + PRINTF("builtin_getnpcx: no such npc: %s\n"_fmt, name); + return; + } + } else { + nd = map_id_is_npc(st->oid); + } + + push_int<ScriptDataInt>(st->stack, nd->bl_x); +} + +/*============================ + * Gets the NPC's y pos + *---------------------------- + */ +static +void builtin_getnpcy(ScriptState *st) +{ + dumb_ptr<npc_data> nd; + + if(HARG(0)){ + NpcName name = stringish<NpcName>(ZString(conv_str(st, &AARG(0)))); + nd = npc_name2id(name); + if (!nd) + { + PRINTF("builtin_getnpcy: no such npc: %s\n"_fmt, name); + return; + } + } else { + nd = map_id_is_npc(st->oid); + } + + push_int<ScriptDataInt>(st->stack, nd->bl_y); +} + static void builtin_mapexit(ScriptState *) { @@ -3030,7 +3147,6 @@ BuiltinFunction builtin_functions[] = BUILTIN(monster, "Mxysmi?"_s, '\0'), BUILTIN(areamonster, "Mxyxysmi?"_s, '\0'), BUILTIN(killmonster, "ME"_s, '\0'), - BUILTIN(killmonsterall, "M"_s, '\0'), BUILTIN(donpcevent, "E"_s, '\0'), BUILTIN(addtimer, "tE"_s, '\0'), BUILTIN(initnpctimer, ""_s, '\0'), @@ -3060,13 +3176,15 @@ BuiltinFunction builtin_functions[] = BUILTIN(getmapflag, "Mi"_s, 'i'), BUILTIN(pvpon, "M"_s, '\0'), BUILTIN(pvpoff, "M"_s, '\0'), + BUILTIN(setpvpchannel, "i"_s, '\0'), + BUILTIN(getpvpflag, "i"_s, 'i'), BUILTIN(emotion, "i"_s, '\0'), BUILTIN(mapwarp, "MMxy"_s, '\0'), - BUILTIN(cmdothernpc, "ss"_s, '\0'), BUILTIN(mobcount, "ME"_s, 'i'), BUILTIN(marriage, "P"_s, 'i'), BUILTIN(divorce, ""_s, 'i'), BUILTIN(getitemname, "I"_s, 's'), + BUILTIN(getitemlink, "I"_s, 's'), BUILTIN(getspellinvocation, "s"_s, 's'), BUILTIN(getpartnerid2, ""_s, 'i'), BUILTIN(getinventorylist, ""_s, '\0'), @@ -3094,6 +3212,9 @@ BuiltinFunction builtin_functions[] = BUILTIN(fakenpcname, "ssi"_s, '\0'), BUILTIN(getx, ""_s, 'i'), BUILTIN(gety, ""_s, 'i'), + BUILTIN(getnpcx, "?"_s, 'i'), + BUILTIN(getnpcy, "?"_s, 'i'), + BUILTIN(strnpcinfo, "i?"_s, 's'), BUILTIN(getmap, ""_s, 's'), BUILTIN(mapexit, ""_s, '\0'), BUILTIN(freeloop, "i"_s, '\0'), diff --git a/src/map/tmw.cpp b/src/map/tmw.cpp index 3f6bb3a..df76720 100644 --- a/src/map/tmw.cpp +++ b/src/map/tmw.cpp @@ -109,8 +109,8 @@ int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, XString message) (sd->chat_lines_in >= battle_config.chat_spam_warn || sd->chat_total_repeats >= battle_config.chat_spam_warn)) { - clif_displaymessage(sd->sess, "WARNING: You are about to be automatically banned for spam!"_s); - clif_displaymessage(sd->sess, "WARNING: Please slow down, do not repeat, and do not SHOUT!"_s); + clif_displaymessage(sd->sess, "##1WARNING : ##BYou are about to be automatically banned for spam!"_s); + clif_displaymessage(sd->sess, "##1WARNING : ##BPlease slow down, do not repeat, and do not SHOUT!"_s); } return 0; diff --git a/tools/config.py b/tools/config.py index 8d1423b..a32e8ca 100755 --- a/tools/config.py +++ b/tools/config.py @@ -581,7 +581,6 @@ def build_config(): map_conf.opt('gm_log', RString, '{}') map_conf.opt('log_file', RString, '{}') - battle_conf.opt('warp_point_debug', bool, 'false') battle_conf.opt('enemy_critical', bool, 'false') battle_conf.opt('enemy_critical_rate', percent, '100') battle_conf.opt('enemy_str', bool, 'true') @@ -614,6 +613,7 @@ def build_config(): battle_conf.opt('mob_count_rate', percent, '100') battle_conf.opt('basic_skill_check', bool, 'true') battle_conf.opt('player_invincible_time', milliseconds, '5_s') + battle_conf.opt('player_pvp_time', milliseconds, '5_s') battle_conf.opt('skill_min_damage', bool, 'false') battle_conf.opt('natural_healhp_interval', milliseconds, '6_s', {map_h}, min='NATURAL_HEAL_INTERVAL') battle_conf.opt('natural_healsp_interval', milliseconds, '8_s', {map_h}, min='NATURAL_HEAL_INTERVAL') |