summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/atcommand.cpp59
-rw-r--r--src/map/intif.cpp50
-rw-r--r--src/map/intif.hpp1
-rw-r--r--src/map/map.hpp2
-rw-r--r--src/map/npc-parse.cpp8
-rw-r--r--src/map/npc.cpp8
-rw-r--r--src/map/script-call.cpp9
-rw-r--r--src/map/script-fun.cpp5
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);