diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/atcommand.cpp | 59 | ||||
-rw-r--r-- | src/map/intif.cpp | 50 | ||||
-rw-r--r-- | src/map/intif.hpp | 1 | ||||
-rw-r--r-- | src/map/map.hpp | 2 | ||||
-rw-r--r-- | src/map/npc-parse.cpp | 8 | ||||
-rw-r--r-- | src/map/npc.cpp | 8 | ||||
-rw-r--r-- | src/map/script-call.cpp | 9 | ||||
-rw-r--r-- | src/map/script-fun.cpp | 5 |
8 files changed, 131 insertions, 11 deletions
diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index ad3529d..2e11227 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -902,8 +902,8 @@ ATCE atcommand_whogroup(Session *s, dumb_ptr<map_session_data> sd, AString output; if (pl_gm_level) output = STRPRINTF( - "Name: %s (GM:%d) | Party: '%s'"_fmt, - pl_sd->status_key.name, pl_gm_level, temp0); + "Name: %s (GM:%d) | Party: '%s' (%i)"_fmt, + pl_sd->status_key.name, pl_gm_level, temp0, pl_sd->status.party_id); clif_displaymessage(s, output); count++; } @@ -1019,11 +1019,11 @@ ATCE atcommand_whomapgroup(Session *s, dumb_ptr<map_session_data> sd, PartyName temp0 = p_.pmd_pget(&PartyMost::name).copy_or(stringish<PartyName>("None"_s)); AString output; if (pl_gm_level) - output = STRPRINTF("Name: %s (GM:%d) | Party: '%s'"_fmt, - pl_sd->status_key.name, pl_gm_level, temp0); + output = STRPRINTF("Name: %s (GM:%d) | Party: '%s' (%i)"_fmt, + pl_sd->status_key.name, pl_gm_level, temp0, pl_sd->status.party_id); else - output = STRPRINTF("Name: %s | Party: '%s'"_fmt, - pl_sd->status_key.name, temp0); + output = STRPRINTF("Name: %s | Party: '%s' (%i)"_fmt, + pl_sd->status_key.name, temp0, pl_sd->status.party_id); clif_displaymessage(s, output); count++; } @@ -1092,8 +1092,8 @@ ATCE atcommand_whogm(Session *s, dumb_ptr<map_session_data> sd, Option<PartyPair> p_ = party_search(pl_sd->status.party_id); PartyName temp0 = p_.pmd_pget(&PartyMost::name).copy_or(stringish<PartyName>("None"_s)); output = STRPRINTF( - " Party: '%s'"_fmt, - temp0); + " Party: '%s' (%i)"_fmt, + temp0, pl_sd->status.party_id); clif_displaymessage(s, output); count++; } @@ -3709,6 +3709,46 @@ ATCE atcommand_partyspy(Session *s, dumb_ptr<map_session_data> sd, } static +ATCE atcommand_setpartyleader(Session *s, dumb_ptr<map_session_data> sd, + ZString message) +{ + CharName character; + PartyName party_name; + int value = 0; + + if (!asplit(message, &party_name, &value, &character)) + return ATCE::USAGE; + + + // name first to avoid error when name begin with a number + Option<PartyPair> p_ = party_searchname(party_name); + dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); + + // try with party id + if (p_.is_none()) + p_ = party_search(wrap<PartyId>(static_cast<uint32_t>(atoi(party_name.c_str())))); + + if (p_.is_none() || pl_sd == nullptr) + return ATCE::EXIST; + + OMATCH_BEGIN (p_) + { + OMATCH_CASE_SOME (p) + { + intif_party_changeleader(p.party_id, pl_sd->status_key.account_id, value < 1 ? 0 : 1); + clif_displaymessage(s, "Party leader changed."_s); + } + OMATCH_CASE_NONE () + { + clif_displaymessage(s, "Incorrect party name, or no one from the party is online."_s); + return ATCE::EXIST; + } + } + OMATCH_END (); + return ATCE::OKAY; +} + +static ATCE atcommand_enablenpc(Session *s, dumb_ptr<map_session_data>, ZString message) { @@ -5295,6 +5335,9 @@ Map<XString, AtCommandInfo> atcommand_info = {"party"_s, {"<name>"_s, 99, atcommand_party, "Create a new party"_s}}, + {"setpartyleader"_s, {"<party-name-or-id> <flag> <player>"_s, + 40, atcommand_setpartyleader, + "Change the leader of a party"_s}}, {"mapexit"_s, {""_s, 99, atcommand_mapexit, "Try to kill the server kindly"_s}}, diff --git a/src/map/intif.cpp b/src/map/intif.cpp index d08b94f..fc34a64 100644 --- a/src/map/intif.cpp +++ b/src/map/intif.cpp @@ -234,6 +234,18 @@ void intif_party_changeoption(PartyId party_id, AccountId account_id, int exp, i send_fpacket<0x3023, 14>(char_session, fixed_23); } +void intif_party_changeleader(PartyId party_id, AccountId account_id, int leader) +{ + if (!char_session) + return; + + Packet_Fixed<0x3026> fixed_26; + fixed_26.party_id = party_id; + fixed_26.account_id = account_id; + fixed_26.leader = leader; + send_fpacket<0x3026, 11>(char_session, fixed_26); +} + // パーティ脱退要求 void intif_party_leave(PartyId party_id, AccountId account_id) { @@ -488,6 +500,34 @@ void intif_parse_PartyOptionChanged(Session *, const Packet_Fixed<0x3823>& fixed fixed.item, fixed.flag); } +static +void intif_parse_PartyLeaderChanged(Session *, const Packet_Fixed<0x3828>& fixed) +{ + int i; + PartyPair p = TRY_UNWRAP(party_search(fixed.party_id), return); + + for (i = 0; i < MAX_PARTY; i++) + { + PartyMember *m = &p->member[i]; + + if (m->account_id == fixed.account_id) + { + dumb_ptr<map_session_data> sd = map_id2sd(wrap<BlockId>(unwrap<AccountId>(fixed.account_id))); + m->leader = (fixed.leader > 0 ? 1 : 0); + + if (sd != nullptr) + { + AString msg = STRPRINTF("You are %s a leader of %s."_fmt, + fixed.leader > 0 ? "now"_s : "no longer"_s, p->name); + clif_displaymessage(sd->sess, msg); + } + break; + } + } + + clif_party_info(p, nullptr); +} + // パーティ脱退通知 static void intif_parse_PartyMemberLeaved(Session *, const Packet_Fixed<0x3824>& fixed) @@ -693,6 +733,16 @@ RecvResult intif_parse(Session *s, uint16_t packet_id) intif_parse_PartyMessage(s, head, repeat); break; } + case 0x3828: + { + Packet_Fixed<0x3828> fixed; + rv = recv_fpacket<0x3828, 11>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + intif_parse_PartyLeaderChanged(s, fixed); + break; + } default: return RecvResult::Error; } diff --git a/src/map/intif.hpp b/src/map/intif.hpp index ac68040..a9d66fa 100644 --- a/src/map/intif.hpp +++ b/src/map/intif.hpp @@ -45,6 +45,7 @@ void intif_request_partyinfo(PartyId party_id); void intif_party_addmember(PartyId party_id, AccountId account_id); void intif_party_changeoption(PartyId party_id, AccountId account_id, int exp, int item); +void intif_party_changeleader(PartyId party_id, AccountId account_id, int leader); void intif_party_leave(PartyId party_id, AccountId accound_id); void intif_party_changemap(dumb_ptr<map_session_data> sd, int online); void intif_party_message(PartyId party_id, AccountId account_id, XString mes); diff --git a/src/map/map.hpp b/src/map/map.hpp index 897787e..44c5bfb 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -340,6 +340,8 @@ struct npc_data : block_list Opt0 option; short flag; + bool deletion_pending; + std::list<RString> eventqueuel; Array<Timer, MAX_EVENTTIMER> eventtimer; short arenaflag; diff --git a/src/map/npc-parse.cpp b/src/map/npc-parse.cpp index 99e6267..47b851c 100644 --- a/src/map/npc-parse.cpp +++ b/src/map/npc-parse.cpp @@ -164,6 +164,8 @@ bool npc_load_warp(ast::npc::Warp& warp) nd->warp.xs = xs; nd->warp.ys = ys; + nd->deletion_pending = false; + npc_warp++; nd->bl_type = BL::NPC; nd->npc_subtype = NpcSubtype::WARP; @@ -226,6 +228,8 @@ bool npc_load_shop(ast::npc::Shop& shop) nd->opt2 = Opt2::ZERO; nd->opt3 = Opt3::ZERO; + nd->deletion_pending = false; + npc_shop++; nd->bl_type = BL::NPC; nd->npc_subtype = NpcSubtype::SHOP; @@ -454,6 +458,8 @@ bool npc_load_script_none(ast::script::ScriptBody& body, ast::npc::ScriptNone& s nd->opt2 = Opt2::ZERO; nd->opt3 = Opt3::ZERO; + nd->deletion_pending = false; + npc_script++; nd->bl_type = BL::NPC; nd->npc_subtype = NpcSubtype::SCRIPT; @@ -562,6 +568,8 @@ bool npc_load_script_map(ast::script::ScriptBody& body, ast::npc::ScriptMap& scr nd->opt2 = Opt2::ZERO; nd->opt3 = Opt3::ZERO; + nd->deletion_pending = false; + npc_script++; nd->bl_type = BL::NPC; nd->npc_subtype = NpcSubtype::SCRIPT; diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 32a5a54..a7cbf5d 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -358,7 +358,7 @@ void npc_eventtimer(TimerData *, tick_t, BlockId id, NpcEvent data) data); return; }); - if ((nd = ev->nd) == nullptr) + if ((nd = ev->nd) == nullptr || nd->deletion_pending == true) { if (battle_config.error_log) PRINTF("npc_event: event not found [%s]\n"_fmt, @@ -611,7 +611,7 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, ev.pos = ev2->pos; } - if ((nd = ev.nd) == nullptr) + if ((nd = ev.nd) == nullptr || nd->deletion_pending == true) { if (!mob_kill && battle_config.error_log) PRINTF("npc_event: event not found [%s]\n"_fmt, @@ -1078,6 +1078,10 @@ void npc_propagate_update(dumb_ptr<npc_data> nd) void npc_free(dumb_ptr<npc_data> nd) { + if (nd == nullptr || nd->deletion_pending == true) + return; + + nd->deletion_pending = true; clif_clearchar(nd, BeingRemoveWhy::GONE); npc_propagate_update(nd); map_deliddb(nd); diff --git a/src/map/script-call.cpp b/src/map/script-call.cpp index d54e234..7c7d4e6 100644 --- a/src/map/script-call.cpp +++ b/src/map/script-call.cpp @@ -383,6 +383,9 @@ void pop_stack(struct script_stack *stack, int start, int end) static ByteCode get_com(ScriptPointer *script) { + if (script == nullptr) + return ByteCode::NOP; + if (static_cast<uint8_t>(script->peek()) >= 0x80) { // synthetic! Does not advance pos yet. @@ -742,10 +745,16 @@ void run_func(ScriptState *st) static void run_script_main(ScriptState *st, Borrowed<const ScriptBuffer> rootscript) { + if (st == nullptr) + return; + int cmdcount = script_config.check_cmdcount; int gotocount = script_config.check_gotocount; struct script_stack *stack = st->stack; + if (stack == nullptr) + return; + st->defsp = stack->stack_datav.size(); int rerun_pos = st->scriptp.pos; diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp index 2036782..8aa8b5c 100644 --- a/src/map/script-fun.cpp +++ b/src/map/script-fun.cpp @@ -1130,8 +1130,9 @@ void builtin_destroy(ScriptState *st) return; nd = nd->is_script(); - //assert(nd->disposable == true); we don't care about it anymore npc_free(nd); + st->oid = BlockId(); + if (!HARG(0)) st->state = ScriptEndState::END; } @@ -1196,6 +1197,8 @@ void builtin_puppet(ScriptState *st) nd->npc_subtype = NpcSubtype::SCRIPT; npc_script++; + nd->deletion_pending = false; + nd->n = map_addnpc(nd->bl_m, nd); map_addblock(nd); |