psu_instance: Add floor_button to make MAG' work better. Fix TargetID issues.

Temporarily disable the Dark God boss zone files because they're wrong in the data.
This commit is contained in:
Loïc Hoguin 2010-07-24 00:53:01 +02:00
parent 473f7f1ae6
commit d62a6bdacd
4 changed files with 69 additions and 35 deletions

View File

@ -383,34 +383,34 @@
{[1003102, 0], [{file, "data/missions/dark-god.1.a.zone-0.nbl"}]},
%~ {[1003102, 1], [{file, "data/missions/dark-god.1.a.zone-1.nbl"}]},
{[1003103, 0], [{file, "data/missions/dark-god.1.s.zone-0.nbl"}]},
{[1003103, 1], [{file, "data/missions/dark-god.1.s.zone-1.nbl"}]},
%~ {[1003103, 1], [{file, "data/missions/dark-god.1.s.zone-1.nbl"}]}, %% @todo
{[1003104, 0], [{file, "data/missions/dark-god.1.s2.zone-0.nbl"}]},
{[1003104, 1], [{file, "data/missions/dark-god.1.s2.zone-1.nbl"}]},
{[1003104, 2], [{file, "data/missions/dark-god.1.s2.zone-2.nbl"}]},
%~ {[1003104, 1], [{file, "data/missions/dark-god.1.s2.zone-1.nbl"}]}, %% @todo
%~ {[1003104, 2], [{file, "data/missions/dark-god.1.s2.zone-2.nbl"}]}, %% @todo
{[1003110, 0], [{file, "data/missions/dark-god.2.c.zone-0.nbl"}]},
{[1003110, 1], [{file, "data/missions/dark-god.2.c.zone-1.nbl"}]},
%~ {[1003110, 1], [{file, "data/missions/dark-god.2.c.zone-1.nbl"}]}, %% @todo
{[1003111, 0], [{file, "data/missions/dark-god.2.b.zone-0.nbl"}]},
{[1003111, 1], [{file, "data/missions/dark-god.2.b.zone-1.nbl"}]},
%~ {[1003111, 1], [{file, "data/missions/dark-god.2.b.zone-1.nbl"}]}, %% @todo
{[1003112, 0], [{file, "data/missions/dark-god.2.a.zone-0.nbl"}]},
{[1003112, 1], [{file, "data/missions/dark-god.2.a.zone-1.nbl"}]},
%~ {[1003112, 1], [{file, "data/missions/dark-god.2.a.zone-1.nbl"}]}, %% @todo
{[1003113, 0], [{file, "data/missions/dark-god.2.s.zone-0.nbl"}]},
%~ {[1003113, 1], [{file, "data/missions/dark-god.2.s.zone-1.nbl"}]},
{[1003114, 0], [{file, "data/missions/dark-god.2.s2.zone-0.nbl"}]},
{[1003114, 1], [{file, "data/missions/dark-god.2.s2.zone-1.nbl"}]},
{[1003114, 2], [{file, "data/missions/dark-god.2.s2.zone-2.nbl"}]},
%~ {[1003114, 1], [{file, "data/missions/dark-god.2.s2.zone-1.nbl"}]}, %% @todo
%~ {[1003114, 2], [{file, "data/missions/dark-god.2.s2.zone-2.nbl"}]}, %% @todo
{[1003120, 0], [{file, "data/missions/dark-god.3.c.zone-0.nbl"}]},
{[1003120, 1], [{file, "data/missions/dark-god.3.c.zone-1.nbl"}]},
%~ {[1003120, 1], [{file, "data/missions/dark-god.3.c.zone-1.nbl"}]}, %% @todo
{[1003121, 0], [{file, "data/missions/dark-god.3.b.zone-0.nbl"}]},
{[1003121, 1], [{file, "data/missions/dark-god.3.b.zone-1.nbl"}]},
%~ {[1003121, 1], [{file, "data/missions/dark-god.3.b.zone-1.nbl"}]}, %% @todo
{[1003122, 0], [{file, "data/missions/dark-god.3.a.zone-0.nbl"}]},
{[1003122, 1], [{file, "data/missions/dark-god.3.a.zone-1.nbl"}]},
%~ {[1003122, 1], [{file, "data/missions/dark-god.3.a.zone-1.nbl"}]}, %% @todo
{[1003123, 0], [{file, "data/missions/dark-god.3.s.zone-0.nbl"}]},
{[1003123, 1], [{file, "data/missions/dark-god.3.s.zone-1.nbl"}]},
%~ {[1003123, 1], [{file, "data/missions/dark-god.3.s.zone-1.nbl"}]}, %% @todo
{[1003124, 0], [{file, "data/missions/dark-god.3.s2.zone-0.nbl"}]},
{[1003124, 1], [{file, "data/missions/dark-god.3.s2.zone-1.nbl"}]},
{[1003124, 2], [{file, "data/missions/dark-god.3.s2.zone-2.nbl"}]},
%~ {[1003124, 1], [{file, "data/missions/dark-god.3.s2.zone-1.nbl"}]}, %% @todo
%~ {[1003124, 2], [{file, "data/missions/dark-god.3.s2.zone-2.nbl"}]}, %% @todo
% Phantom Ruins (Linear Line counter)

View File

@ -874,11 +874,16 @@ handle(16#0f0a, Data) ->
send_1205(EventID, BlockID, 0),
send_1213(ObjectID, 1);
13 -> % floor_button on (also sent when clearing a few of the rooms in black nest)
% 1205 1213
ignore;
{ok, User} = egs_user_model:read(get(gid)),
{BlockID, EventID} = psu_instance:floor_button_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
% 1205(same, with 1 as last value) 1213(same, with 0 as last value)
ignore;
%% @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:floor_button_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

View File

@ -20,7 +20,7 @@
-module(psu_instance).
-behavior(gen_server).
-export([start_link/1, stop/1, key_event/3, spawn_cleared_event/3, warp_event/5, hit/3]). %% API.
-export([start_link/1, stop/1, floor_button_event/3, key_event/3, spawn_cleared_event/3, warp_event/5, hit/3]). %% API.
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). %% gen_server.
-include_lib("stdlib/include/qlc.hrl").
@ -43,6 +43,10 @@ start_link(Zones) ->
stop(InstancePid) ->
gen_server:call(InstancePid, stop).
%% @todo @spec
floor_button_event(InstancePid, ZoneID, ObjectID) ->
gen_server:call(InstancePid, {floor_button_event, ZoneID, ObjectID}).
%% @todo @spec event(ServerPid, ObjectID, Args) -> Response
key_event(InstancePid, ZoneID, ObjectID) ->
gen_server:call(InstancePid, {key_event, ZoneID, ObjectID}).
@ -88,6 +92,11 @@ object_init([{box, _Model, Breakable, TrigEventID}|Tail], ZoneID, BlockID, Objec
end,
object_init(Tail, ZoneID, BlockID, ObjectID + 1, TargetID + 1, ListIndex, ObjectIndex + 1);
%% @doc floor_button: {InstancePid, ZoneID, floor_button, ObjectID
object_init([{floor_button, TrigEventID}|Tail], ZoneID, BlockID, ObjectID, TargetID, ListIndex, ObjectIndex) ->
object_insert(#psu_object{id={self(), ZoneID, floor_button, ObjectID}, instancepid=self(), type=floor_button, args={BlockID, TrigEventID}}),
object_init(Tail, ZoneID, BlockID, ObjectID + 1, TargetID + 1, ListIndex, ObjectIndex + 1);
%% @doc key: {InstancePid, ZoneID, key, ObjectID}
object_init([{key, _KeySet, TrigEventID, _ReqEventID}|Tail], ZoneID, BlockID, ObjectID, TargetID, ListIndex, ObjectIndex) ->
object_insert(#psu_object{id={self(), ZoneID, key, ObjectID}, instancepid=self(), type=key, args={BlockID, [TrigEventID]}}),
@ -110,25 +119,22 @@ object_init([{warp, DestX, DestY, DestZ, DestDir}|Tail], ZoneID, BlockID, Object
object_insert(#psu_object{id={self(), ZoneID, warp, BlockID, ListIndex, ObjectIndex}, instancepid=self(), type=warp, args=#pos{x=DestX, y=DestY, z=DestZ, dir=DestDir}}),
object_init(Tail, ZoneID, BlockID, ObjectID, TargetID, ListIndex, ObjectIndex + 1);
%% @doc Ignore for now: crystal
%% @todo Probably have 2 TargetID because of its on/off state.
object_init([crystal|Tail], ZoneID, BlockID, ObjectID, TargetID, ListIndex, ObjectIndex) ->
object_init(Tail, ZoneID, BlockID, ObjectID + 1, TargetID + 2, ListIndex, ObjectIndex + 1);
%% @doc Ignore for now: floor_button, shoot_button, google_target, trap (all kinds)
%% @doc Ignore for now: shoot_button, google_target, trap (all kinds)
object_init([Object|Tail], ZoneID, BlockID, ObjectID, TargetID, ListIndex, ObjectIndex)
when Object =:= floor_button;
Object =:= shoot_button;
Object =:= google_target;
when Object =:= shoot_button;
Object =:= goggle_target;
Object =:= trap ->
object_init(Tail, ZoneID, BlockID, ObjectID + 1, TargetID + 1, ListIndex, ObjectIndex + 1);
%% @doc Ignore for now: 'exit' (seems to take a TargetID but not an ObjectID
object_init(['exit'|Tail], ZoneID, BlockID, ObjectID, TargetID, ListIndex, ObjectIndex) ->
object_init(Tail, ZoneID, BlockID, ObjectID, TargetID + 1, ListIndex, ObjectIndex + 1);
%% @doc Ignore for now: objects without any ObjectID or TargetID.
object_init([Object|Tail], ZoneID, BlockID, ObjectID, TargetID, ListIndex, ObjectIndex)
when Object =:= static_model;
Object =:= invisible_block;
Object =:= entrance;
Object =:= 'exit';
Object =:= label;
Object =:= hidden_minimap_section;
Object =:= fog;
@ -142,6 +148,10 @@ object_init([_Object|Tail], ZoneID, BlockID, ObjectID, TargetID, ListIndex, Obje
%% Event handlers
handle_call({floor_button_event, ZoneID, ObjectID}, _From, State) ->
#psu_object{args=Args} = object_select({self(), ZoneID, floor_button, ObjectID}),
{reply, Args, State};
handle_call({key_event, ZoneID, ObjectID}, _From, State) ->
#psu_object{args=Args} = object_select({self(), ZoneID, key, ObjectID}),
{reply, Args, State};

View File

@ -24,7 +24,7 @@
-define(NBL, "./nbl").
run() ->
List = [parse_zone(QuestID, Filename) || {[QuestID, ZoneID], [{file, Filename}]} <- ?ZONES, ZoneID =:= 0, QuestID < 1100000],
List = [{QuestID, parse_quest(QuestID)} || {QuestID, _} <- ?QUESTS, QuestID < 1100000],
Begin = "%% This file is automatically generated by EGS.
%% Please do not edit it manually, as you would risk losing your changes.
@ -35,17 +35,20 @@ run() ->
Missions = io_lib:format("~s~p~s", [Begin, List, End]),
file:write_file("include/missions.hrl", Missions).
parse_zone(QuestID, NblFilename) ->
parse_quest(QuestID) ->
[{ZoneID, parse_zone(Filename)} || {[ZoneQuestID, ZoneID], [{file, Filename}]} <- ?ZONES, ZoneQuestID =:= QuestID].
parse_zone(NblFilename) ->
Files = nbl_list_files(NblFilename),
log("~p", [Files]),
nbl_extract_files(NblFilename),
Filename = "set_r3.rel",
Filename = "set_r0.rel",
BasePtr = calc_base_ptr(Filename, Files, 0),
{ok, << $N, $X, $R, 0, EndRelPtr:32/little-unsigned-integer, AreaIDListRelPtr:32/little-unsigned-integer, 0:32, Data/bits >>} = file:read_file(io_lib:format("tmp/~s", [Filename])),
log("header: end ptr(~b) areaid list ptr(~b)", [EndRelPtr, AreaIDListRelPtr]),
{ok, _AreaCode, NbMaps, MapsListPtr} = parse_areaid_list(Data, AreaIDListRelPtr - 16),
MapList = parse_mapnumbers_list(Data, NbMaps, MapsListPtr - BasePtr - 16),
ObjList = {QuestID, [{0, [{MapID, parse_object_list_headers(BasePtr, Data, NbHeaders, ObjListHeadersPtr - BasePtr - 16)} || {MapID, NbHeaders, ObjListHeadersPtr} <- MapList]}]},
ObjList = [{MapID, parse_object_list_headers(BasePtr, Data, NbHeaders, ObjListHeadersPtr - BasePtr - 16)} || {MapID, NbHeaders, ObjListHeadersPtr} <- MapList],
nbl_cleanup(),
ObjList.
@ -128,12 +131,18 @@ parse_object_args(ObjType, Params, Data, Ptr) ->
parse_object_args(4, _Params, _Data) ->
static_model;
parse_object_args(5, _Params, _Data) ->
floor_button;
%% @todo Many unknowns.
parse_object_args(5, _Params, Data) ->
<< _:352, TrigEvent:16/little-unsigned-integer, _/bits >> = Data,
log("floor_button: trigevent(~p)", [TrigEvent]),
{floor_button, TrigEvent};
parse_object_args(6, _Params, _Data) ->
fog;
parse_object_args(9, _Params, _Data) ->
menu_prompt;
parse_object_args(10, _Params, _Data) ->
invisible_block;
@ -161,6 +170,9 @@ parse_object_args(14, {params, {pos, PosX, PosY, PosZ}, _Rot}, Data) ->
parse_object_args(17, _Params, _Data) ->
fence;
parse_object_args(18, _Params, _Data) ->
npc;
parse_object_args(20, _Params, _Data) ->
door;
@ -219,6 +231,9 @@ parse_object_args(43, _Params, _Data) ->
parse_object_args(44, _Params, _Data) ->
trap;
parse_object_args(45, _Params, _Data) ->
npc_talk;
parse_object_args(48, _Params, _Data) ->
boss_gate;
@ -234,6 +249,10 @@ parse_object_args(51, _Params, _Data) ->
parse_object_args(53, _Params, _Data) ->
label;
%% @todo Find out! Only used in the cake sisters shop so far.
parse_object_args(59, _Params, _Data) ->
unknown_object;
parse_object_args(62, _Params, _Data) ->
pp_cube;