summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgumi <git@gumi.ca>2018-01-01 16:09:22 -0500
committergumi <git@gumi.ca>2018-01-01 18:09:15 -0500
commitb7ec6e535d314a64aeaf426e2e4c068cd7c4bb34 (patch)
treef29e84563c80e5438da35e608967c33c195dde98
parente808b814cd0899342fcba21cc74ec059772ceb5e (diff)
downloadtmwa-b7ec6e535d314a64aeaf426e2e4c068cd7c4bb34.tar.gz
tmwa-b7ec6e535d314a64aeaf426e2e4c068cd7c4bb34.tar.bz2
tmwa-b7ec6e535d314a64aeaf426e2e4c068cd7c4bb34.tar.xz
tmwa-b7ec6e535d314a64aeaf426e2e4c068cd7c4bb34.zip
release v18.1.1v18.1.1
-rw-r--r--CHANGELOG3
m---------deps/attoconf0
-rw-r--r--src/char/int_party.cpp47
-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
-rwxr-xr-xtools/protocol.py28
12 files changed, 209 insertions, 11 deletions
diff --git a/CHANGELOG b/CHANGELOG
index adcc69d..af0cf28 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+v18.1.1
+ - increase party limit to 120
+ - add a command to change party leader
v17.11.12
- fix a bug that did not decrease the npc counter on npc despawn (REDUX)
v16.11.28
diff --git a/deps/attoconf b/deps/attoconf
-Subproject d33fcf6cc7380633329fdaf2e7f7543bbdd2490
+Subproject 7b939e7e4ce36e8b62b10025e567f871731cbf4
diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp
index 5ee65ad..9fdd9bb 100644
--- a/src/char/int_party.cpp
+++ b/src/char/int_party.cpp
@@ -416,6 +416,20 @@ void mapif_party_optionchanged(Session *s, PartyPair p, AccountId account_id,
account_id, p->exp, p->item, flag);
}
+static
+void mapif_party_leaderchanged(Session *s, PartyPair p, AccountId account_id,
+ int leader)
+{
+ Packet_Fixed<0x3828> fixed_28;
+ fixed_28.party_id = p.party_id;
+ fixed_28.account_id = account_id;
+ fixed_28.leader = leader;
+ for (Session *ss : iter_map_sessions())
+ {
+ send_fpacket<0x3828, 11>(ss, fixed_28);
+ }
+}
+
// パーティ脱退通知
static
void mapif_party_leaved(PartyId party_id, AccountId account_id, CharName name)
@@ -603,6 +617,23 @@ void mapif_parse_PartyChangeOption(Session *s, PartyId party_id, AccountId accou
mapif_party_optionchanged(s, p, account_id, flag);
}
+static
+void mapif_parse_PartyChangeLeader(Session *s, PartyId party_id, AccountId account_id,
+ int leader)
+{
+ PartyPair p{party_id, TRY_UNWRAP(party_db.search(party_id), return)};
+
+ for (int i = 0; i < MAX_PARTY; i++)
+ {
+ if (p->member[i].account_id != account_id)
+ continue;
+
+ mapif_party_leaderchanged(s, p, account_id, leader);
+ p->member[i].leader = leader;
+ return;
+ }
+}
+
// パーティ脱退要求
void mapif_parse_PartyLeave(Session *, PartyId party_id, AccountId account_id)
{
@@ -777,6 +808,22 @@ RecvResult inter_party_parse_frommap(Session *ms, uint16_t packet_id)
lv);
break;
}
+ case 0x3026:
+ {
+ Packet_Fixed<0x3026> fixed;
+ rv = recv_fpacket<0x3026, 11>(ms, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ PartyId party_id = fixed.party_id;
+ AccountId account_id = fixed.account_id;
+ uint8_t leader = fixed.leader;
+ mapif_parse_PartyChangeLeader(ms,
+ party_id,
+ account_id,
+ leader);
+ break;
+ }
case 0x3027:
{
Packet_Head<0x3027> head;
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);
diff --git a/tools/protocol.py b/tools/protocol.py
index 1a87263..0c64e6f 100755
--- a/tools/protocol.py
+++ b/tools/protocol.py
@@ -5830,6 +5830,20 @@ def build_context():
3. logged out
''',
)
+ char_map.r(0x3026, 'party change leader',
+ fixed=[
+ at(0, u16, 'packet id'),
+ at(2, party_id, 'party id'),
+ at(6, account_id, 'account id'),
+ at(10, u8, 'leader'),
+ ],
+ fixed_size=11,
+ pre=[],
+ post=[0x3828],
+ desc='''
+ Explicitly request a change of party leader.
+ ''',
+ )
char_map.r(0x3027, 'party message remote begin',
head=[
at(0, u16, 'packet id'),
@@ -6108,6 +6122,20 @@ def build_context():
Actually send a party message to other map servers.
''',
)
+ char_map.s(0x3828, 'party change leader notify',
+ fixed=[
+ at(0, u16, 'packet id'),
+ at(2, party_id, 'party id'),
+ at(6, account_id, 'account id'),
+ at(10, u8, 'leader'),
+ ],
+ fixed_size=11,
+ pre=[0x3026],
+ post=[],
+ desc='''
+ Party leader was changed.
+ ''',
+ )
# TOC_MISC
# any client