psu_proto: Add a new event: party_remove_member. NPCs can now be removed from the party.

This commit is contained in:
Loïc Hoguin 2010-09-02 23:48:27 +02:00
parent bab8913645
commit f785b290bb
3 changed files with 83 additions and 14 deletions

View File

@ -220,9 +220,9 @@ char_load(User) ->
send_0d01(User), send_0d01(User),
% 0246 % 0246
send_0a0a(), send_0a0a(),
send_1006(5), send_1006(5, 0),
send_1005((User#egs_user_model.character)#characters.name), send_1005((User#egs_user_model.character)#characters.name),
send_1006(12), send_1006(12, 0),
send_0210(), send_0210(),
send_0222(), send_0222(),
send_1500(User), send_1500(User),
@ -450,7 +450,8 @@ loop(SoFar) ->
send_0233(SpawnList), send_0233(SpawnList),
?MODULE:loop(SoFar); ?MODULE:loop(SoFar);
{psu_player_unspawn, Spawn} -> {psu_player_unspawn, Spawn} ->
send_0204(Spawn#egs_user_model.id, Spawn#egs_user_model.lid, 5), {ok, User} = egs_user_model:read(get(gid)),
send_0204(User, Spawn, 5),
?MODULE:loop(SoFar); ?MODULE:loop(SoFar);
{psu_warp, QuestID, ZoneID, MapID, EntryID} -> {psu_warp, QuestID, ZoneID, MapID, EntryID} ->
event({area_change, QuestID, ZoneID, MapID, EntryID}), event({area_change, QuestID, ZoneID, MapID, EntryID}),
@ -754,7 +755,7 @@ event(lumilass_options_request) ->
%% @todo Probably replenish the player HP when entering a non-mission area rather than when aborting the mission? %% @todo Probably replenish the player HP when entering a non-mission area rather than when aborting the mission?
event(mission_abort) -> event(mission_abort) ->
send_1006(11), send_1006(11, 0),
{ok, User} = egs_user_model:read(get(gid)), {ok, User} = egs_user_model:read(get(gid)),
%% delete the mission %% delete the mission
if User#egs_user_model.instancepid =:= undefined -> ignore; if User#egs_user_model.instancepid =:= undefined -> ignore;
@ -956,6 +957,20 @@ event({object_warp_take, BlockID, ListNb, ObjectNb}) ->
send_0503(User#egs_user_model.pos), send_0503(User#egs_user_model.pos),
send_1211(16#ffffffff, 0, 14, 0); send_1211(16#ffffffff, 0, 14, 0);
event({party_remove_member, PartyPos}) ->
log("party remove member ~b", [PartyPos]),
{ok, DestUser} = egs_user_model:read(get(gid)),
{ok, RemovedGID} = psu_party:get_member(DestUser#egs_user_model.partypid, PartyPos),
psu_party:remove_member(DestUser#egs_user_model.partypid, PartyPos),
{ok, RemovedUser} = egs_user_model:read(RemovedGID),
case (RemovedUser#egs_user_model.character)#characters.type of
npc -> egs_user_model:delete(RemovedGID);
_ -> ignore
end,
send_1006(8, PartyPos),
send_0204(DestUser, RemovedUser, 1),
psu_proto:send_0215(DestUser, 0);
event({player_options_change, Options}) -> event({player_options_change, Options}) ->
{ok, User} = egs_user_model:read(get(gid)), {ok, User} = egs_user_model:read(get(gid)),
file:write_file(io_lib:format("save/~s/~b-character.options", [User#egs_user_model.folder, (User#egs_user_model.character)#characters.slot]), Options); file:write_file(io_lib:format("save/~s/~b-character.options", [User#egs_user_model.folder, (User#egs_user_model.character)#characters.slot]), Options);
@ -1174,11 +1189,16 @@ send_0202() ->
send(<< 16#02020300:32, 0:352 >>). send(<< 16#02020300:32, 0:352 >>).
%% @todo Not sure. Used for unspawning, and more. %% @todo Not sure. Used for unspawning, and more.
send_0204(PlayerGID, PlayerLID, Action) -> send_0204(DestUser, TargetUser, Action) ->
GID = get(gid), DestGID = DestUser#egs_user_model.id,
send(<< 16#02040300:32, 0:32, 16#00001200:32, PlayerGID:32/little-unsigned-integer, 0:64, TargetTypeID = case (TargetUser#egs_user_model.character)#characters.type of
16#00011300:32, GID:32/little-unsigned-integer, 0:64, PlayerGID:32/little-unsigned-integer, npc -> 16#00001d00;
PlayerLID:32/little-unsigned-integer, Action:32/little-unsigned-integer >>). _ -> 16#00001200
end,
#egs_user_model{id=TargetGID, lid=TargetLID} = TargetUser,
send(<< 16#02040300:32, 0:32, TargetTypeID:32, TargetGID:32/little-unsigned-integer, 0:64,
16#00011300:32, DestGID:32/little-unsigned-integer, 0:64, TargetGID:32/little-unsigned-integer,
TargetLID:32/little-unsigned-integer, Action:32/little-unsigned-integer >>).
%% @doc Indicate to the client that loading should finish. %% @doc Indicate to the client that loading should finish.
%% @todo Last value seems to be 2 most of the time. Never 0 though. Apparently counters have it at 4. %% @todo Last value seems to be 2 most of the time. Never 0 though. Apparently counters have it at 4.
@ -1414,10 +1434,9 @@ send_1005(Name) ->
send(<< (header(16#1005))/binary, Before/binary, GID:32/little-unsigned-integer, 0:64, Name/binary, After/binary >>). send(<< (header(16#1005))/binary, Before/binary, GID:32/little-unsigned-integer, 0:64, Name/binary, After/binary >>).
%% @doc Party-related command probably controlling the party state. %% @doc Party-related command probably controlling the party state.
%% Value 11 aborts the mission. %% EventID 11 aborts the mission.
%% @todo Figure out what the packet is. send_1006(EventID, PartyPos) ->
send_1006(N) -> send(<< (header(16#1006))/binary, EventID:8, PartyPos:8, 0:16 >>).
send(<< (header(16#1006))/binary, N:32/little-unsigned-integer >>).
%% @doc Send the player's current location. %% @doc Send the player's current location.
send_100e(QuestID, ZoneID, MapID, Location, CounterID) -> send_100e(QuestID, ZoneID, MapID, Location, CounterID) ->

View File

@ -19,7 +19,7 @@
-module(psu_party). -module(psu_party).
-behavior(gen_server). -behavior(gen_server).
-export([start_link/1, stop/1, join/3, leave/2, get_instance/1, set_instance/2, remove_instance/1, get_npc/1]). %% API. -export([start_link/1, stop/1, join/3, leave/2, get_instance/1, set_instance/2, remove_instance/1, get_member/2, remove_member/2, get_npc/1]). %% API.
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). %% gen_server. -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). %% gen_server.
-record(state, {free_spots, users, instancepid}). -record(state, {free_spots, users, instancepid}).
@ -50,6 +50,14 @@ set_instance(PartyPid, InstancePid) ->
remove_instance(PartyPid) -> remove_instance(PartyPid) ->
gen_server:cast(PartyPid, remove_instance). gen_server:cast(PartyPid, remove_instance).
%% @doc Return the user at the given position.
get_member(PartyPid, Spot) ->
gen_server:call(PartyPid, {get_member, Spot}).
%% @doc Remove a member from the party.
remove_member(PartyPid, Spot) ->
gen_server:cast(PartyPid, {remove_member, Spot}).
%% @doc Returns a list of NPC UserID. %% @doc Returns a list of NPC UserID.
get_npc(PartyPid) -> get_npc(PartyPid) ->
gen_server:call(PartyPid, get_npc). gen_server:call(PartyPid, get_npc).
@ -82,6 +90,10 @@ handle_call({join, PlayerType, UserID}, _From, State) ->
handle_call(get_instance, _From, State) -> handle_call(get_instance, _From, State) ->
{reply, {ok, State#state.instancepid}, State}; {reply, {ok, State#state.instancepid}, State};
handle_call({get_member, Spot}, _From, State) ->
[UserID] = [FoundUserID || {PlayerSpot, _PlayerType, FoundUserID} <- State#state.users, PlayerSpot =:= Spot],
{reply, {ok, UserID}, State};
handle_call(get_npc, _From, State) -> handle_call(get_npc, _From, State) ->
List = [{Spot, UserID} || {Spot, PlayerType, UserID} <- State#state.users, PlayerType =:= npc], List = [{Spot, UserID} || {Spot, PlayerType, UserID} <- State#state.users, PlayerType =:= npc],
{reply, {ok, List}, State}; {reply, {ok, List}, State};
@ -109,6 +121,11 @@ handle_cast({set_instance, InstancePid}, State) ->
handle_cast(remove_instance, State) -> handle_cast(remove_instance, State) ->
{noreply, State#state{instancepid=undefined}}; {noreply, State#state{instancepid=undefined}};
handle_cast({remove_member, Spot}, State) ->
Users = [{PlayerSpot, PlayerType, UserID} || {PlayerSpot, PlayerType, UserID} <- State#state.users, PlayerSpot =/= Spot],
FreeSpots = State#state.free_spots,
{noreply, State#state{free_spots=[Spot|FreeSpots], users=Users}};
handle_cast(_Msg, State) -> handle_cast(_Msg, State) ->
{noreply, State}. {noreply, State}.

View File

@ -366,6 +366,23 @@ parse(Size, 16#080d, Channel, Data) ->
?ASSERT_EQ(VarI, 0), ?ASSERT_EQ(VarI, 0),
ignore; ignore;
%% @todo Find out what it's really doing!
parse(Size, 16#080f, Channel, Data) ->
<< _LID:16/little, VarA:16/little, VarB:32/little, VarC:32/little, VarD:32/little, VarE:32/little,
VarF:32/little, VarG:32/little, VarH:32/little, VarI:32/little, _PartyPos:32/little >> = Data,
?ASSERT_EQ(Size, 48),
?ASSERT_EQ(Channel, 2),
?ASSERT_EQ(VarA, 0),
?ASSERT_EQ(VarB, 0),
?ASSERT_EQ(VarC, 0),
?ASSERT_EQ(VarD, 0),
?ASSERT_EQ(VarE, 0),
?ASSERT_EQ(VarF, 0),
?ASSERT_EQ(VarG, 0),
?ASSERT_EQ(VarH, 0),
?ASSERT_EQ(VarI, 0),
ignore;
parse(Size, 16#0811, Channel, Data) -> parse(Size, 16#0811, Channel, Data) ->
<< _LID:16/little, VarA:16/little, VarB:32/little, VarC:32/little, VarD:32/little, VarE:32/little, VarF:32/little, VarG:32/little, VarH:32/little, VarI:32/little, << _LID:16/little, VarA:16/little, VarB:32/little, VarC:32/little, VarD:32/little, VarE:32/little, VarF:32/little, VarG:32/little, VarH:32/little, VarI:32/little,
_CounterType:8, VarJ:8, FromZoneID:16/little, FromMapID:16/little, FromEntryID:16/little, CounterID:32/little, VarK:32/little >> = Data, _CounterType:8, VarJ:8, FromZoneID:16/little, FromMapID:16/little, FromEntryID:16/little, CounterID:32/little, VarK:32/little >> = Data,
@ -798,6 +815,22 @@ parse(Size, 16#0f0a, Channel, Data) ->
ignore ignore
end; end;
parse(Size, 16#1007, Channel, Data) ->
<< VarA:32/little, VarB:32/little, VarC:32/little, VarD:32/little, VarE:32/little, VarF:32/little,
VarG:32/little, VarH:32/little, VarI:32/little, PartyPos:32/little, _Name:512/bits >> = Data,
?ASSERT_EQ(Size, 112),
?ASSERT_EQ(Channel, 2),
?ASSERT_EQ(VarA, 0),
?ASSERT_EQ(VarB, 0),
?ASSERT_EQ(VarC, 0),
?ASSERT_EQ(VarD, 0),
?ASSERT_EQ(VarE, 0),
?ASSERT_EQ(VarF, 0),
?ASSERT_EQ(VarG, 0),
?ASSERT_EQ(VarH, 0),
?ASSERT_EQ(VarI, 0),
{party_remove_member, PartyPos};
parse(Size, 16#1705, Channel, Data) -> parse(Size, 16#1705, Channel, Data) ->
<< _LID:16/little, VarA:16/little, VarB:32/little, VarC:32/little, VarD:32/little, VarE:32/little, VarF:32/little, VarG:32/little, VarH:32/little, VarI:32/little >> = Data, << _LID:16/little, VarA:16/little, VarB:32/little, VarC:32/little, VarD:32/little, VarE:32/little, VarF:32/little, VarG:32/little, VarH:32/little, VarI:32/little >> = Data,
?ASSERT_EQ(Size, 44), ?ASSERT_EQ(Size, 44),