psu_proto: Move all existing object actions to events.

This commit is contained in:
Loïc Hoguin 2010-08-25 01:42:37 +02:00
parent 83316ddf6f
commit d799215d0d
2 changed files with 267 additions and 79 deletions

View File

@ -772,6 +772,87 @@ event({npc_shop_request, ShopID}) ->
_ -> send_1a02(0, 0, 1, 0, 0) _ -> send_1a02(0, 0, 1, 0, 0)
end; end;
%% @todo Not sure what are those hardcoded values.
event({object_boss_gate_activate, ObjectID}) ->
send_1213(ObjectID, 0),
send_1215(2, 16#7008),
%% @todo Following sent after the warp?
send_1213(37, 0),
%% @todo Why resend this?
send_1213(ObjectID, 0);
event({object_boss_gate_enter, ObjectID}) ->
send_1213(ObjectID, 1);
%% @todo Do we need to send something back here?
event({object_boss_gate_leave, _ObjectID}) ->
ignore;
%% @todo Second send_1211 argument should be User#egs_user_model.lid. Fix when it's correctly handled.
event({object_chair_sit, ObjectTargetID}) ->
%~ {ok, User} = egs_user_model:read(get(gid)),
send_1211(ObjectTargetID, 0, 8, 0);
%% @todo Second send_1211 argument should be User#egs_user_model.lid. Fix when it's correctly handled.
event({object_chair_stand, ObjectTargetID}) ->
%~ {ok, User} = egs_user_model:read(get(gid)),
send_1211(ObjectTargetID, 0, 8, 2);
event({object_crystal_activate, ObjectID}) ->
send_1213(ObjectID, 1);
event({object_key_console_enable, ObjectID}) ->
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, [EventID|_]} = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
send_1205(EventID, BlockID, 0),
send_1213(ObjectID, 1);
event({object_key_console_init, ObjectID}) ->
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, [_, EventID, _]} = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
send_1205(EventID, BlockID, 0);
event({object_key_console_open_gate, ObjectID}) ->
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, [_, _, EventID]} = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
send_1205(EventID, BlockID, 0),
send_1213(ObjectID, 1);
%% @todo Now that it's separate from object_key_console_enable, handle it better than that, don't need a list of events.
event({object_key_enable, ObjectID}) ->
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, [EventID|_]} = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
send_1205(EventID, BlockID, 0),
send_1213(ObjectID, 1);
%% @todo Some switch objects apparently work differently, like the light switch in Mines in MAG'.
event({object_switch_off, ObjectID}) ->
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, EventID} = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
send_1205(EventID, BlockID, 1),
send_1213(ObjectID, 0);
event({object_switch_on, ObjectID}) ->
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, EventID} = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
send_1205(EventID, BlockID, 0),
send_1213(ObjectID, 1);
event({object_vehicle_boost_enable, ObjectID}) ->
send_1213(ObjectID, 1);
event({object_vehicle_boost_respawn, ObjectID}) ->
send_1213(ObjectID, 0);
%% @todo Second send_1211 argument should be User#egs_user_model.lid. Fix when it's correctly handled.
event({object_warp_take, BlockID, ListNb, ObjectNb}) ->
{ok, User} = egs_user_model:read(get(gid)),
Pos = psu_instance:warp_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, BlockID, ListNb, ObjectNb),
NewUser = User#egs_user_model{pos=Pos},
egs_user_model:write(NewUser),
send_0503(User#egs_user_model.pos),
send_1211(16#ffffffff, 0, 14, 0);
event(player_type_availability_request) -> event(player_type_availability_request) ->
send_1a07(); send_1a07();
@ -920,83 +1001,6 @@ handle(16#0f07, Data) ->
log("after enter vehicle: ~b ~b", [A, B]), log("after enter vehicle: ~b ~b", [A, B]),
send(<< (header(16#120f))/binary, A:32/little-unsigned-integer, B:32/little-unsigned-integer >>); send(<< (header(16#120f))/binary, A:32/little-unsigned-integer, B:32/little-unsigned-integer >>);
%% @doc Object event handler.
%% @todo Handle all events appropriately.
%% @todo B should be the ObjType.
handle(16#0f0a, Data) ->
<< BlockID:16/little-unsigned-integer, ListNb:16/little-unsigned-integer, ObjectNb:16/little-unsigned-integer, _MapID:16/little-unsigned-integer, ObjectID:16/little-unsigned-integer,
_:16, A:32/little-unsigned-integer, B:32/little-unsigned-integer, _:32, C:32/little-unsigned-integer, _:272, Action:8, _/bits >> = Data,
log("object event handler: action ~b object ~b a ~b b ~b c ~b", [Action, ObjectID, A, B, C]),
case Action of
0 -> % warp
{ok, User} = egs_user_model:read(get(gid)),
Pos = psu_instance:warp_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, BlockID, ListNb, ObjectNb),
NewUser = User#egs_user_model{pos=Pos},
egs_user_model:write(NewUser),
send_0503(User#egs_user_model.pos),
send_1211(A, C, B, 0);
3 -> % crystal activation
send_1213(ObjectID, 1);
4 -> % enter boss gate
send_1213(ObjectID, 1);
5 -> % leave boss gate
% probably 1213, unknown last value
ignore;
6 -> % activate boss gate
send_1213(ObjectID, 0),
send_1215(2, 16#7008),
%% @todo Sent after warp but not necessarily, also what's 37 (should be a B1 object) and why resend the 1213(id)?
send_1213(37, 0),
send_1213(ObjectID, 0);
9 -> % healing pad
% 0117, 0111, 0117?
ignore;
12 -> % pick/use key, pick vehicle_boost
{ok, User} = egs_user_model:read(get(gid)),
Args = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
case Args of
undefined -> %% vehicle boost doesn't send an event
ignore;
{BlockID, [EventID|_]} ->
send_1205(EventID, BlockID, 0)
end,
send_1213(ObjectID, 1);
13 -> % floor_button on (also sent when clearing a few of the rooms in black nest)
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, EventID} = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
send_1205(EventID, BlockID, 0),
send_1213(ObjectID, 1);
14 -> % floor_button off
%% @todo Apparently when it's not a floor_button but a light switch, this here should be handled differently.
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, EventID} = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
send_1205(EventID, BlockID, 1),
send_1213(ObjectID, 0);
%~ 19 -> % activate trap
%~ ignore;
20 -> % enter counter/elevator/room/spaceport/pick key/use key
ignore;
23 -> % initialize key slots (called when picking a key or checking the gate directly with no key)
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, [_, EventID, _]} = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
send_1205(EventID, BlockID, 0); % in block 1, 202 = key [1] x1, 203 = key [-] x1
24 -> % open gate (only when client has key)
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, [_, _, EventID]} = psu_instance:std_event(User#egs_user_model.instancepid, (User#egs_user_model.area)#psu_area.zoneid, ObjectID),
send_1205(EventID, BlockID, 0),
send_1213(ObjectID, 1);
25 -> % sit on chair
send_1211(A, C, 8, 0);
26 -> % sit out of chair
send_1211(A, C, 8, 2);
28 -> % respawn object picked (like vehicle_boost)
send_1213(ObjectID, 0);
%~ 30 -> % @todo (phantom ruins block 4, dark god 2 block 1 (fake key block))
%~ ignore;
_ ->
log("object event ~b", [Action])
end;
%% @todo Not sure yet. %% @todo Not sure yet.
handle(16#1019, _) -> handle(16#1019, _) ->
ignore; ignore;
@ -1518,6 +1522,7 @@ send_1207() ->
send(<< (header(16#1207))/binary, Chunk/binary, Chunk/binary, Chunk/binary, Chunk/binary, Chunk/binary, Chunk/binary >>). send(<< (header(16#1207))/binary, Chunk/binary, Chunk/binary, Chunk/binary, Chunk/binary, Chunk/binary, Chunk/binary >>).
%% @todo Object interaction? Figure out. C probably the interaction type. %% @todo Object interaction? Figure out. C probably the interaction type.
%% @todo Apparently A would be TargetID/ffffffff, B would be the player LID, C would be the object type? D still completely unknown.
send_1211(A, B, C, D) -> send_1211(A, B, C, D) ->
send(<< (header(16#1211))/binary, A:32/little-unsigned-integer, B:32/little-unsigned-integer, C:32/little-unsigned-integer, D:32/little-unsigned-integer >>). send(<< (header(16#1211))/binary, A:32/little-unsigned-integer, B:32/little-unsigned-integer, C:32/little-unsigned-integer, D:32/little-unsigned-integer >>).

View File

@ -40,11 +40,11 @@ log(Msg, FmtVars) ->
%% @spec assert() -> ok %% @spec assert() -> ok
%% @doc Log a detailed message when the function is called. %% @doc Log a detailed message when the function is called.
-define(ASSERT(), log("assert error in module ~p on line ~p~n", [?MODULE, ?LINE])). -define(ASSERT(), log("assert error in module ~p on line ~p", [?MODULE, ?LINE])).
%% @spec assert(A, B) -> ok %% @spec assert(A, B) -> ok
%% @doc Log a detailed message when the assertion A =:= B fails. %% @doc Log a detailed message when the assertion A =:= B fails.
-define(ASSERT_EQ(A, B), if A =:= B -> ok; true -> log("assert error in module ~p on line ~p~n", [?MODULE, ?LINE]) end). -define(ASSERT_EQ(A, B), if A =:= B -> ok; true -> log("assert error in module ~p on line ~p", [?MODULE, ?LINE]) end).
%% @spec parse(Packet) -> Result %% @spec parse(Packet) -> Result
%% @doc Parse the packet and return a result accordingly. %% @doc Parse the packet and return a result accordingly.
@ -382,6 +382,189 @@ parse(Size, 16#0c0f, Channel, Data) ->
?ASSERT_EQ(VarI, 0), ?ASSERT_EQ(VarI, 0),
{counter_quest_options_request, CounterID}; {counter_quest_options_request, CounterID};
parse(Size, 16#0f0a, 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, BlockID:16/little, ListNb:16/little,
ObjectNb:16/little, _MapID:16/little, ObjectID:16/little, VarJ:16/little, ObjectTargetID:32/little,
ObjectType:16/little, VarK:16/little, ObjectBaseTargetID:16/little, VarL:16/little, _PartyPosOrLID:32/little,
VarN:32/little, VarO:32/little, VarP:32/little, VarQ:32/little, VarR:32/little, VarS:32/little,
VarT:32/little, VarU:32/little, ObjectType2:16/little, EventID:8, VarV:8, VarW:32/little >> = 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),
?ASSERT_EQ(VarK, 0),
?ASSERT_EQ(VarP, 16#ffffffff),
?ASSERT_EQ(VarQ, 16#ffffffff),
?ASSERT_EQ(VarR, 16#ffffffff),
?ASSERT_EQ(VarS, 0),
?ASSERT_EQ(VarT, 0),
?ASSERT_EQ(VarU, 0),
?ASSERT_EQ(ObjectType, ObjectType2),
case [ObjectType, EventID] of
[ 5, 13] ->
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_switch_on, ObjectID};
[ 5, 14] ->
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_switch_off, ObjectID};
[ 9, 20] ->
%% @todo We probably need to handle it for Airboard Rally.
ignore; %% object_sensor_trigger
[14, 0] ->
?ASSERT_EQ(ObjectID, 16#ffff),
?ASSERT_EQ(ObjectTargetID, 16#ffffffff),
?ASSERT_EQ(ObjectBaseTargetID, 16#ffff),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
{object_warp_take, BlockID, ListNb, ObjectNb};
[22, 12] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(ObjectTargetID, 16#ffffffff),
?ASSERT_EQ(ObjectBaseTargetID, 16#ffff),
?ASSERT_EQ(VarL, 116),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_key_console_enable, ObjectID};
[22, 23] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(ObjectTargetID, 16#ffffffff),
?ASSERT_EQ(ObjectBaseTargetID, 16#ffff),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_key_console_init, ObjectID};
[22, 24] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(ObjectTargetID, 16#ffffffff),
?ASSERT_EQ(ObjectBaseTargetID, 16#ffff),
?ASSERT_EQ(VarL, 116),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_key_console_open_gate, ObjectID};
[31, 12] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(ObjectTargetID, 16#ffffffff),
?ASSERT_EQ(ObjectBaseTargetID, 16#ffff),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_key_enable, ObjectID};
[48, 4] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(VarL, 116),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_boss_gate_enter, ObjectID};
[48, 5] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(VarL, 116),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_boss_gate_leave, ObjectID};
[48, 6] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(VarL, 116),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_boss_gate_activate, ObjectID};
[48, 7] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(VarL, 116),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
?ASSERT(),
ignore; %% @todo object_boss_gate_???
[49, 3] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(ObjectTargetID, 16#ffffffff),
?ASSERT_EQ(ObjectBaseTargetID, 16#ffff),
?ASSERT_EQ(VarL, 116),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_crystal_activate, ObjectID};
[51, 1] ->
?ASSERT_EQ(VarL, 116),
?ASSERT_EQ(ObjectTargetID, VarN),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
?ASSERT(),
ignore; %% @todo object_goggle_target_???
[56, 25] ->
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_chair_sit, ObjectTargetID};
[56, 26] ->
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_chair_stand, ObjectTargetID};
[57, 12] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(ObjectTargetID, 16#ffffffff),
?ASSERT_EQ(ObjectBaseTargetID, 16#ffff),
?ASSERT_EQ(VarL, 116),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
{object_vehicle_boost_enable, ObjectID};
[57, 28] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(ObjectTargetID, 16#ffffffff),
?ASSERT_EQ(ObjectBaseTargetID, 16#ffff),
?ASSERT_EQ(VarL, 116),
?ASSERT_EQ(VarN, 16#ffffffff),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
{object_vehicle_boost_respawn, ObjectID};
[71, 27] ->
?ASSERT_EQ(VarJ, 134),
?ASSERT_EQ(ObjectTargetID, VarN),
?ASSERT_EQ(VarO, 16#ffffffff),
?ASSERT_EQ(VarV, 1),
?ASSERT_EQ(VarW, 0),
?ASSERT(),
ignore; %% @todo object_trap(3rd)_???
_ -> %% Unhandled actions.
log("unknown 0f0a ObjectType ~p EventID ~p", [ObjectType, EventID]),
ignore
end;
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),