Added 15-puzzles to the project.
parent
8b2d19f096
commit
72d27870f0
|
@ -1,4 +1,4 @@
|
|||
char * AssetPathLUT[7] =
|
||||
char * AssetPathLUT[8] =
|
||||
{
|
||||
"",
|
||||
"backgrounds/unknown.png",
|
||||
|
@ -7,9 +7,10 @@ char * AssetPathLUT[7] =
|
|||
"characters/test_normal.png",
|
||||
"characters/test_happy.png",
|
||||
"characters/monika_leaning.png",
|
||||
"puzzles/duck.png",
|
||||
};
|
||||
|
||||
bool AssetIsPermanentLUT[7] =
|
||||
bool AssetIsPermanentLUT[8] =
|
||||
{
|
||||
true,
|
||||
true,
|
||||
|
@ -18,9 +19,10 @@ false,
|
|||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
};
|
||||
|
||||
char * AssetNameLUT[7] =
|
||||
char * AssetNameLUT[8] =
|
||||
{
|
||||
"None",
|
||||
"Error",
|
||||
|
@ -29,9 +31,10 @@ char * AssetNameLUT[7] =
|
|||
"ArthurNormal",
|
||||
"ArthurHappy",
|
||||
"MonikaLeaning",
|
||||
"Duck",
|
||||
};
|
||||
|
||||
r32 AssetScaleLUT[7] =
|
||||
r32 AssetScaleLUT[8] =
|
||||
{
|
||||
0,
|
||||
0,
|
||||
|
@ -40,5 +43,6 @@ r32 AssetScaleLUT[7] =
|
|||
0.017,
|
||||
0.017,
|
||||
0.033,
|
||||
1,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
extern char * AssetPathLUT[7];
|
||||
extern char * AssetPathLUT[8];
|
||||
|
||||
extern bool AssetIsPermanentLUT[7];
|
||||
extern bool AssetIsPermanentLUT[8];
|
||||
|
||||
extern char * AssetNameLUT[7];
|
||||
extern char * AssetNameLUT[8];
|
||||
|
||||
extern r32 AssetScaleLUT[7];
|
||||
extern r32 AssetScaleLUT[8];
|
||||
|
||||
typedef s32 asset_id;
|
||||
enum
|
||||
|
@ -16,6 +16,7 @@ AssetID_DDLCBackground,
|
|||
AssetID_ArthurNormal,
|
||||
AssetID_ArthurHappy,
|
||||
AssetID_MonikaLeaning,
|
||||
AssetID_Duck,
|
||||
AssetID_COUNT,
|
||||
};
|
||||
|
||||
|
|
|
@ -133,6 +133,8 @@ static S2_CALL_FUNCTION(S2_Call_CharacterSet); // sets the state of a charac
|
|||
static S2_CALL_FUNCTION(S2_Call_CharacterRemove); // removes a character
|
||||
static S2_CALL_FUNCTION(S2_Call_CharacterSetTalking); // makes a character talking
|
||||
static S2_CALL_FUNCTION(S2_Call_CharacterUnsetAllTalking); // makes no characters talking
|
||||
static S2_CALL_FUNCTION(S2_Call_NavLoad); // loads a nav scene
|
||||
static S2_CALL_FUNCTION(S2_Call_Puzzle15); // plays the 15-puzzle
|
||||
|
||||
global read_only scene2_call_function *S2_CallBindingLookup[] =
|
||||
{
|
||||
|
@ -146,6 +148,8 @@ S2_Call_CharacterSet,
|
|||
S2_Call_CharacterRemove,
|
||||
S2_Call_CharacterSetTalking,
|
||||
S2_Call_CharacterUnsetAllTalking,
|
||||
S2_Call_NavLoad,
|
||||
S2_Call_Puzzle15,
|
||||
};
|
||||
|
||||
global read_only string S2_CallNameLookup[] =
|
||||
|
@ -160,5 +164,7 @@ StrComp("ctr_set"),
|
|||
StrComp("ctr_remove"),
|
||||
StrComp("ctr_set_talking"),
|
||||
StrComp("ctr_unset_all_talking"),
|
||||
StrComp("nav_load"),
|
||||
StrComp("puzzle_15"),
|
||||
};
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
|||
|
||||
//- sixten: load startup scene
|
||||
temp Scratch = GetScratch();
|
||||
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, Platform_ReadEntireFile(Scratch.Arena, StrLit("data/while_test.vns")));
|
||||
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, Platform_ReadEntireFile(Scratch.Arena, StrLit("data/omori.vns")));
|
||||
SV_SetCurrentSource(&Scene);
|
||||
ReleaseScratch(Scratch);
|
||||
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
//- sixten: monika
|
||||
{ MonikaLeaning, "characters/monika_leaning.png", false, 0.033 }
|
||||
|
||||
////////////////////////////////
|
||||
//~ sixten: puzzles
|
||||
|
||||
{ Duck, "puzzles/duck.png", false, 1 }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1021,5 +1021,9 @@ static scene2_run_result S2_Run(arena *Arena, scene2_runtime *Runtime, compiled_
|
|||
}
|
||||
|
||||
Done:;
|
||||
if(Runtime->InstructionPointer >= ProcInfo->InstructionEnd)
|
||||
{
|
||||
S2_SetCurrentProc(Runtime, S_EmptyProcInfo);
|
||||
}
|
||||
return(Result);
|
||||
}
|
|
@ -91,6 +91,8 @@ struct scene2_proc_info
|
|||
u64 InstructionEnd;
|
||||
};
|
||||
|
||||
global scene2_proc_info S_EmptyProcInfo = {StrComp(""), 0, 0};
|
||||
|
||||
struct scene2_proc_node
|
||||
{
|
||||
scene2_proc_node *Next;
|
||||
|
@ -286,7 +288,7 @@ static b32 S2_ObjectIsTrue(scene2_object Object);
|
|||
static compiled_scene2 S2_CompiledFromString(arena *Arena, string String);
|
||||
static compiled_scene2 S2_CopyCompiledScene(arena *Arena, compiled_scene2 *Source);
|
||||
|
||||
static void S2_SetCurrentProc(scene2_runtime *Runtime, scene2_proc_info *Info);
|
||||
static void S2_SetCurrentProc(scene2_runtime *Runtime, scene2_proc_info Info);
|
||||
static scene2_proc_info S2_ProcFromName(compiled_scene2 *Compiled, string Name);
|
||||
|
||||
#endif //VN_SCENE2_H
|
||||
|
|
|
@ -77,6 +77,11 @@
|
|||
{ ctr_set_talking, S2_Call_CharacterSetTalking, "makes a character talking" },
|
||||
{ ctr_unset_all_talking, S2_Call_CharacterUnsetAllTalking, "makes no characters talking" },
|
||||
|
||||
// sixten: nav management calls
|
||||
{ nav_load, S2_Call_NavLoad, "loads a nav scene" },
|
||||
|
||||
// sixten: puzzle management calls
|
||||
{ puzzle_15, S2_Call_Puzzle15, "plays the 15-puzzle" },
|
||||
}
|
||||
|
||||
@table_gen
|
||||
|
|
|
@ -135,9 +135,9 @@ static S2_CALL_FUNCTION(S2_Call_CharacterRemove)
|
|||
|
||||
string Target = TargetObject.As.String;
|
||||
|
||||
scene_view_character_data *CharacterBegin = SceneView->Characters;
|
||||
scene_view_character_data *CharacterEnd = SceneView->Characters+SceneView->CharactersUsed;
|
||||
scene_view_character_data *Character = CharacterBegin;
|
||||
scene_view_character_data *CharacterBegin = SceneView->Characters;
|
||||
scene_view_character_data *CharacterEnd = SceneView->Characters+SceneView->CharactersUsed;
|
||||
scene_view_character_data *Character = CharacterBegin;
|
||||
|
||||
// sixten: check if the character exists
|
||||
for(;Character < CharacterEnd; Character += 1)
|
||||
|
@ -200,3 +200,60 @@ static S2_CALL_FUNCTION(S2_Call_CharacterUnsetAllTalking)
|
|||
Character->Talking = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void SV_LoadNavItems(string FileName);
|
||||
static S2_CALL_FUNCTION(S2_Call_NavLoad)
|
||||
{
|
||||
scene2_object Object = S2_StackPop(Runtime);
|
||||
if(Object.Kind == S2_ObjectKind_String)
|
||||
{
|
||||
SV_LoadNavItems(Object.As.String);
|
||||
}
|
||||
}
|
||||
|
||||
static S2_CALL_FUNCTION(S2_Call_Puzzle15)
|
||||
{
|
||||
scene_view *SceneView = (scene_view *)Runtime->Data;
|
||||
SceneView->Mode = SV_Mode_P15;
|
||||
SceneView->BoardOpenT = 0;
|
||||
SceneView->TimeSinceBoardUpdate = 0;
|
||||
SceneView->TimeSinceBoardClear = 0;
|
||||
SceneView->BoardIsComplete = false;
|
||||
|
||||
// sixten: generate random board
|
||||
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
|
||||
{
|
||||
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
|
||||
{
|
||||
SceneView->Board[BoardY][BoardX] = (1+BoardX+BoardY*4)%16;
|
||||
}
|
||||
}
|
||||
|
||||
v2_s32 EmptyP = V2S32(3, 3);
|
||||
s32 ShuffleCount = 10000;
|
||||
for(s32 Index = 0; Index < ShuffleCount; Index += 1)
|
||||
{
|
||||
s32 DeltaX = (rand() % 2)*2-1;
|
||||
s32 DeltaY = (rand() % 2)*2-1;
|
||||
|
||||
// sixten: apply x-action
|
||||
s32 NewEmptyX = EmptyP.x+DeltaX;
|
||||
if(0 <= NewEmptyX && NewEmptyX < 4)
|
||||
{
|
||||
SceneView->Board[EmptyP.y][EmptyP.x] = SceneView->Board[EmptyP.y][NewEmptyX];
|
||||
SceneView->Board[EmptyP.y][NewEmptyX] = 0;
|
||||
EmptyP.x = NewEmptyX;
|
||||
}
|
||||
|
||||
// sixten: apply y-action
|
||||
s32 NewEmptyY = EmptyP.y+DeltaY;
|
||||
if(0 <= NewEmptyY && NewEmptyY < 4)
|
||||
{
|
||||
SceneView->Board[EmptyP.y][EmptyP.x] = SceneView->Board[NewEmptyY][EmptyP.x];
|
||||
SceneView->Board[NewEmptyY][EmptyP.x] = 0;
|
||||
EmptyP.y = NewEmptyY;
|
||||
}
|
||||
}
|
||||
|
||||
Copy(SceneView->PrevBoard, SceneView->Board, sizeof(SceneView->Board));
|
||||
}
|
|
@ -27,12 +27,11 @@ static void SV_Reset(void)
|
|||
SceneView->CharactersUsed = 0;
|
||||
}
|
||||
|
||||
static void SV_LoadNavItems(void)
|
||||
static void SV_LoadNavItems(string FileName)
|
||||
{
|
||||
#if 0
|
||||
scene_view *SceneView = SV_GetState();
|
||||
temp Scratch = GetScratch();
|
||||
string NavData = Platform_ReadEntireFile(Scratch.Arena, SceneView->Runtime.Compiled.NavFileName);
|
||||
string NavData = Platform_ReadEntireFile(Scratch.Arena, FileName);
|
||||
|
||||
if(NavData.Count != 0)
|
||||
{
|
||||
|
@ -114,7 +113,6 @@ static void SV_LoadNavItems(void)
|
|||
}
|
||||
}
|
||||
ReleaseScratch(Scratch);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SV_SetCurrentSource(compiled_scene2 *Compiled)
|
||||
|
@ -128,10 +126,6 @@ static void SV_SetCurrentSource(compiled_scene2 *Compiled)
|
|||
ArenaClear(SceneView->SceneArena);
|
||||
|
||||
SceneView->Compiled = S2_CopyCompiledScene(SceneView->SceneArena, Compiled);
|
||||
|
||||
SV_LoadNavItems();
|
||||
|
||||
//- sixten: find main proc
|
||||
S2_SetCurrentProc(Runtime, S2_ProcFromName(Compiled, StrLit("main")));
|
||||
}
|
||||
|
||||
|
@ -494,219 +488,250 @@ static ui_signal BuildNavItemAndLabel(scene_nav_item *Item, r32 GlobalScale, v2_
|
|||
return(Signal);
|
||||
}
|
||||
|
||||
static void BuildNavView(scene_view *View, ui_box *Box, v2_r32 BoxDim)
|
||||
static UI_CUSTOM_DRAW_CALLBACK(Puzzle15DrawCallback)
|
||||
{
|
||||
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
|
||||
|
||||
for(int ItemIndex = 0; ItemIndex < View->NavItemCount; ++ItemIndex)
|
||||
{
|
||||
scene_nav_item *Item = View->NavItems+ItemIndex;
|
||||
if(BuildNavItemAndLabel(Item, GlobalScale, BoxDim).Clicked)
|
||||
{
|
||||
// sixten: apply the action
|
||||
if(Item->Action.Kind == S_NavAction_Proc)
|
||||
{
|
||||
S2_SetCurrentProc(&View->Runtime, S2_ProcFromName(&View->Compiled, Item->Action.Content));
|
||||
}
|
||||
else if(Item->Action.Kind == S_NavAction_Scene)
|
||||
{
|
||||
temp Scratch = GetScratch();
|
||||
string Filepath = PushFormat(Scratch.Arena, "data/%S.vns", Item->Action.Content);;
|
||||
|
||||
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, Filepath);
|
||||
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, SceneInput);
|
||||
SV_SetCurrentSource(&Scene);
|
||||
|
||||
ReleaseScratch(Scratch);
|
||||
}
|
||||
}
|
||||
}
|
||||
scene_view *SceneView = (scene_view *)Data;
|
||||
render_handle Texture = A_TextureFromAssetID(AssetID_Duck);
|
||||
v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture));
|
||||
v2_r32 PieceDim = DimOfRange(Box->Rect)*0.25f;
|
||||
v2_r32 Offset = Box->Rect.Min+V2R32(0, (1.0f - SceneView->BoardOpenT)*PieceDim.y);
|
||||
if(SceneView->TimeSinceBoardClear < 2)
|
||||
{
|
||||
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
|
||||
{
|
||||
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
|
||||
{
|
||||
v2_r32 SourceDim = TextureDim*0.25f;
|
||||
u8 BoardValue = SceneView->Board[BoardY][BoardX];
|
||||
if(BoardValue)
|
||||
{
|
||||
s32 PrevBoardX = BoardX;
|
||||
s32 PrevBoardY = BoardY;
|
||||
if(SceneView->PrevBoard[PrevBoardY][PrevBoardX] != BoardValue)
|
||||
{
|
||||
for(PrevBoardY = 0; PrevBoardY < 4; PrevBoardY += 1)
|
||||
{
|
||||
for(PrevBoardX = 0; PrevBoardX < 4; PrevBoardX += 1)
|
||||
{
|
||||
if(SceneView->PrevBoard[PrevBoardY][PrevBoardX] == BoardValue)
|
||||
{
|
||||
goto FoundPrevTile;
|
||||
}
|
||||
}
|
||||
}
|
||||
FoundPrevTile:;
|
||||
}
|
||||
|
||||
BoardValue -= 1;
|
||||
s32 SourceX = BoardValue % 4;
|
||||
s32 SourceY = BoardValue / 4;
|
||||
|
||||
v2_r32 BoardP = LinearBlend(V2R32(PrevBoardX, PrevBoardY), V2R32(BoardX, BoardY), Clamp01(Pow(SceneView->TimeSinceBoardUpdate*5, 4)));
|
||||
|
||||
range2_r32 Source = Range2R32(V2R32(SourceX*SourceDim.x, SourceY*SourceDim.y), V2R32((SourceX+1)*SourceDim.x, (SourceY+1)*SourceDim.y));
|
||||
range2_r32 Dest = Range2R32(Offset+BoardP*PieceDim, Offset+(BoardP+V2R32(1, 1))*PieceDim);
|
||||
v4_r32 Color = SetAlpha(Color_White, SceneView->BoardOpenT);
|
||||
PushTexturedQuad(Group, Dest, Source, Color, Color, Color, Color, 3, 3, 3, 3, 1.5f, 0, Texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(SceneView->BoardIsComplete)
|
||||
{
|
||||
r32 CompleteT = Clamp01(Pow(SceneView->TimeSinceBoardClear, 5))*Clamp01(3-SceneView->TimeSinceBoardClear);
|
||||
range2_r32 Source = Range2R32(V2R32(0, 0), TextureDim);
|
||||
range2_r32 Dest = Pad(Box->Rect, PieceDim*(1.0f-CompleteT));
|
||||
v4_r32 Color = SetAlpha(Color_White, CompleteT);
|
||||
PushTexturedQuad(Group, Dest, Source, Color, Color, Color, Color, 3, 3, 3, 3, 1.5f, 0, Texture);
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildScene(scene_view *View)
|
||||
static void BuildScene(scene_view *SceneView)
|
||||
{
|
||||
v2_r32 ParentDim = UI_CalculateBoxDim(UI_TopParent());
|
||||
|
||||
r32 TargetRatio = 16.0f/9.0f;
|
||||
r32 ActualRatio = ParentDim.x/ParentDim.y;
|
||||
|
||||
v2_r32 BoxDim = ParentDim;
|
||||
|
||||
if(ActualRatio>TargetRatio)
|
||||
{
|
||||
BoxDim.x = BoxDim.y*TargetRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
BoxDim.y = BoxDim.x/TargetRatio;
|
||||
}
|
||||
|
||||
UI_SetNextWidth(UI_Pixels(BoxDim.x, 1));
|
||||
UI_SetNextHeight(UI_Pixels(BoxDim.y, 1));
|
||||
UI_SetNextLayoutAxis(Axis2_Y);
|
||||
UI_SetNextFixedP((ParentDim-BoxDim)*0.5f);
|
||||
ui_box *Box = UI_MakeBox(UI_BoxFlag_Clip|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, StrLit("Scene View"));
|
||||
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, View);
|
||||
|
||||
UI_Parent(Box)
|
||||
{
|
||||
if(SV_CurrentlyInProc())
|
||||
{
|
||||
BuildProcView(View, Box, BoxDim);
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildNavView(View, Box, BoxDim);
|
||||
}
|
||||
}
|
||||
v2_r32 ParentDim = UI_CalculateBoxDim(UI_TopParent());
|
||||
|
||||
r32 TargetRatio = 16.0f/9.0f;
|
||||
r32 ActualRatio = ParentDim.x/ParentDim.y;
|
||||
|
||||
v2_r32 BoxDim = ParentDim;
|
||||
|
||||
if(ActualRatio > TargetRatio)
|
||||
{
|
||||
BoxDim.x = BoxDim.y*TargetRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
BoxDim.y = BoxDim.x/TargetRatio;
|
||||
}
|
||||
|
||||
UI_SetNextWidth(UI_Pixels(BoxDim.x, 1));
|
||||
UI_SetNextHeight(UI_Pixels(BoxDim.y, 1));
|
||||
UI_SetNextLayoutAxis(Axis2_Y);
|
||||
UI_SetNextFixedP((ParentDim-BoxDim)*0.5f);
|
||||
ui_box *Box = UI_MakeBox(UI_BoxFlag_Clip|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, StrLit("Scene View"));
|
||||
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, SceneView);
|
||||
|
||||
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
|
||||
|
||||
UI_Parent(Box)
|
||||
{
|
||||
switch(SceneView->Mode)
|
||||
{
|
||||
case SV_Mode_Scene:
|
||||
{
|
||||
// sixten(NOTE): when this is rewritten, put it inside THIS function.
|
||||
BuildProcView(SceneView, Box, BoxDim);
|
||||
} break;
|
||||
case SV_Mode_Nav:
|
||||
{
|
||||
for(int ItemIndex = 0; ItemIndex < SceneView->NavItemCount; ++ItemIndex)
|
||||
{
|
||||
scene_nav_item *Item = SceneView->NavItems+ItemIndex;
|
||||
if(BuildNavItemAndLabel(Item, GlobalScale, BoxDim).Clicked)
|
||||
{
|
||||
// sixten: apply the action
|
||||
if(Item->Action.Kind == S_NavAction_Proc)
|
||||
{
|
||||
S2_SetCurrentProc(&SceneView->Runtime, S2_ProcFromName(&SceneView->Compiled, Item->Action.Content));
|
||||
}
|
||||
else if(Item->Action.Kind == S_NavAction_Scene)
|
||||
{
|
||||
temp Scratch = GetScratch();
|
||||
string Filepath = PushFormat(Scratch.Arena, "data/%S.vns", Item->Action.Content);;
|
||||
|
||||
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, Filepath);
|
||||
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, SceneInput);
|
||||
SV_SetCurrentSource(&Scene);
|
||||
|
||||
ReleaseScratch(Scratch);
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SV_Mode_P15:
|
||||
{
|
||||
UI_WidthFill UI_HeightFill UI_BackgroundColor(SetAlpha(Color_Black, 0.5*SceneView->BoardOpenT*Clamp01(2-SceneView->TimeSinceBoardClear*0.5))) UI_LayoutAxis(Axis2_X)
|
||||
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit("15 Puzzle Darken")))
|
||||
{
|
||||
UI_Padding(UI_Percent(1, 0)) UI_Width(UI_ChildrenSum(1, 1)) UI_Column() UI_Padding(UI_Percent(1, 0))
|
||||
{
|
||||
UI_SetNextSize(UI_Em(25, 1), UI_Em(25, 1));
|
||||
ui_box *PuzzleBox = UI_MakeBox(0, StrLit("Puzzle Box"));
|
||||
UI_EquipBoxCustomDrawCallback(PuzzleBox, Puzzle15DrawCallback, SceneView);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildErrorScreen(scene_view *SceneView, vn_input *Input)
|
||||
{
|
||||
UI_SetNextLayoutAxis(Axis2_X);
|
||||
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit("Container")))
|
||||
{
|
||||
UI_Padding(UI_Em(3, 1)) UI_Width(UI_Percent(1, 0)) UI_Column() UI_Padding(UI_Em(3, 1))
|
||||
{
|
||||
UI_Font(Font_Bold) UI_Size(UI_TextContent(0, 1), UI_TextContent(0, 1)) UI_FontSize(32) UI_LabelF("A runtime error has occurred");
|
||||
s64 ErrorIndex = 0;
|
||||
UI_SetNextLayoutAxis(Axis2_X);
|
||||
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit("Container")))
|
||||
{
|
||||
UI_Padding(UI_Em(3, 1)) UI_Width(UI_Percent(1, 0)) UI_Column() UI_Padding(UI_Em(3, 1))
|
||||
{
|
||||
UI_Font(Font_Bold) UI_Size(UI_TextContent(0, 1), UI_TextContent(0, 1)) UI_FontSize(32) UI_LabelF("A runtime error has occurred");
|
||||
s64 ErrorIndex = 0;
|
||||
for(scene2_message *Message = SceneView->Messages.First; Message != 0; Message = Message->Next, ErrorIndex += 1)
|
||||
{
|
||||
UI_Spacer(UI_Em(3, 1));
|
||||
UI_SetNextCornerRadius(3);
|
||||
UI_Size(UI_Percent(1, 1), UI_Percent(1, 0)) UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawDropShadow|UI_BoxFlag_DrawBorder, "%i", ErrorIndex))
|
||||
UI_Size(UI_TextContent(30, 1), UI_TextContent(30, 1))
|
||||
{
|
||||
{
|
||||
UI_Spacer(UI_Em(3, 1));
|
||||
UI_SetNextCornerRadius(3);
|
||||
UI_Size(UI_Percent(1, 1), UI_Percent(1, 0)) UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawDropShadow|UI_BoxFlag_DrawBorder, "%i", ErrorIndex))
|
||||
UI_Size(UI_TextContent(30, 1), UI_TextContent(30, 1))
|
||||
{
|
||||
UI_Label(Message->Message);
|
||||
}
|
||||
}
|
||||
UI_Spacer(UI_Em(3, 1));
|
||||
UI_Size(UI_Percent(1, 1), UI_Em(2, 1)) UI_Row()
|
||||
UI_Width(UI_TextContent(30, 1)) UI_CornerRadius(4)
|
||||
{
|
||||
ui_signal IgnoreSignal = UI_ButtonF("Ignore");
|
||||
if(IgnoreSignal.Hovering)
|
||||
{
|
||||
UI_TooltipLabel(StrLit("Continue running the script, may lead to more errors."), UI_MouseP());
|
||||
}
|
||||
if(IgnoreSignal.Clicked)
|
||||
{
|
||||
}
|
||||
}
|
||||
UI_Spacer(UI_Em(3, 1));
|
||||
UI_Size(UI_Percent(1, 1), UI_Em(2, 1)) UI_Row()
|
||||
UI_Width(UI_TextContent(30, 1)) UI_CornerRadius(4)
|
||||
{
|
||||
ui_signal IgnoreSignal = UI_ButtonF("Ignore");
|
||||
if(IgnoreSignal.Hovering)
|
||||
{
|
||||
UI_TooltipLabel(StrLit("Continue running the script, may lead to more errors."), UI_MouseP());
|
||||
}
|
||||
if(IgnoreSignal.Clicked)
|
||||
{
|
||||
ZeroStruct(&SceneView->Messages);
|
||||
ArenaClear(SceneView->MessageArena);
|
||||
}
|
||||
|
||||
UI_Spacer(UI_Em(1, 1));
|
||||
|
||||
ui_signal RestartSignal = UI_ButtonF("Restart");
|
||||
if(RestartSignal.Hovering)
|
||||
{
|
||||
UI_TooltipLabel(StrLit("Restarts the script, may lose progress."), UI_MouseP());
|
||||
}
|
||||
if(RestartSignal.Clicked)
|
||||
{
|
||||
SV_Reset();
|
||||
}
|
||||
|
||||
UI_Spacer(UI_Em(1, 1));
|
||||
if(UI_ButtonF("Exit Program").Clicked)
|
||||
{
|
||||
Input->ExitRequested = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UI_Spacer(UI_Em(1, 1));
|
||||
|
||||
ui_signal RestartSignal = UI_ButtonF("Restart");
|
||||
if(RestartSignal.Hovering)
|
||||
{
|
||||
UI_TooltipLabel(StrLit("Restarts the script, may lose progress."), UI_MouseP());
|
||||
}
|
||||
if(RestartSignal.Clicked)
|
||||
{
|
||||
SV_Reset();
|
||||
}
|
||||
|
||||
UI_Spacer(UI_Em(1, 1));
|
||||
if(UI_ButtonF("Exit Program").Clicked)
|
||||
{
|
||||
Input->ExitRequested = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static scene_view_character_data *SV_CharacterDataFromName(string Name)
|
||||
{
|
||||
scene_view_character_data *Result = 0;
|
||||
|
||||
scene_view *View = SV_GetState();
|
||||
|
||||
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
|
||||
{
|
||||
scene_view_character_data *Character = View->Characters + CharacterIndex;
|
||||
if(AreEqual(Character->Name, Name))
|
||||
{
|
||||
Result = Character;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//- sixten: create character if not initialized
|
||||
if(!Result && View->CharactersUsed < ArrayCount(View->Characters))
|
||||
{
|
||||
s32 CharacterIndex = View->CharactersUsed;
|
||||
View->CharactersUsed += 1;
|
||||
|
||||
Result = View->Characters + CharacterIndex;
|
||||
*Result = {};
|
||||
Result->Name = Name;
|
||||
Result->Active = true;
|
||||
Result->PctP = (r32)(CharacterIndex + 1) / (View->CharactersUsed + 1);
|
||||
}
|
||||
|
||||
return(Result);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static scene_view_character_texture_info SV_CharacterTextureFromAction(scene_character_action *Action)
|
||||
{
|
||||
scene_view_character_texture_info Result = {};
|
||||
Result.Texture = EmptyRenderHandle();
|
||||
Result.Scale = 1.0f;
|
||||
|
||||
asset_id AssetID = Action->State;
|
||||
Result.Texture = A_TextureFromAssetID(AssetID);
|
||||
Result.Scale = A_ScaleFromAssetID(AssetID);
|
||||
scene_view_character_data *Result = 0;
|
||||
|
||||
#if 0
|
||||
if(AreEqual(StrLit("arthur"), Action->Target))
|
||||
{
|
||||
|
||||
scene_view *View = SV_GetState();
|
||||
|
||||
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
|
||||
{
|
||||
scene_view_character_data *Character = View->Characters + CharacterIndex;
|
||||
if(AreEqual(Character->Name, Name))
|
||||
{
|
||||
Result = Character;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//- sixten: create character if not initialized
|
||||
if(!Result && View->CharactersUsed < ArrayCount(View->Characters))
|
||||
{
|
||||
s32 CharacterIndex = View->CharactersUsed;
|
||||
View->CharactersUsed += 1;
|
||||
|
||||
switch(Action->State)
|
||||
{
|
||||
case CR_State_Normal: { Result.Texture = View->TestNormal; } break;
|
||||
case CR_State_Happy: { Result.Texture = View->TestHappy; } break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
Result.Scale = 0.017f;
|
||||
}
|
||||
else if(AreEqual(StrLit("monika"), Action->Target))
|
||||
{
|
||||
switch(Action->State)
|
||||
{
|
||||
case CR_State_Leaning: { Result.Texture = View->MonikaLeaning; } break;
|
||||
default: break;
|
||||
}
|
||||
Result.Scale = 0.033f;
|
||||
}
|
||||
#endif
|
||||
return(Result);
|
||||
Result = View->Characters + CharacterIndex;
|
||||
*Result = {};
|
||||
Result->Name = Name;
|
||||
Result->Active = true;
|
||||
Result->PctP = (r32)(CharacterIndex + 1) / (View->CharactersUsed + 1);
|
||||
}
|
||||
|
||||
return(Result);
|
||||
}
|
||||
#endif
|
||||
|
||||
static r32 SV_CalculateTargetPctP(s32 TrueCharacterIndex)
|
||||
{
|
||||
scene_view *View = SV_GetState();
|
||||
s32 CharacterCount = 0;
|
||||
s32 AssumedCharacterIndex = 0;
|
||||
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
|
||||
{
|
||||
scene_view_character_data *Data = View->Characters + CharacterIndex;
|
||||
if(Data->Active)
|
||||
{
|
||||
CharacterCount += 1;
|
||||
if(CharacterIndex < TrueCharacterIndex)
|
||||
{
|
||||
AssumedCharacterIndex += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
r32 Result = (r32)(AssumedCharacterIndex + 1) / (Max(CharacterCount, 1) + 1);
|
||||
return(Result);
|
||||
scene_view *View = SV_GetState();
|
||||
s32 CharacterCount = 0;
|
||||
s32 AssumedCharacterIndex = 0;
|
||||
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
|
||||
{
|
||||
scene_view_character_data *Data = View->Characters + CharacterIndex;
|
||||
if(Data->Active)
|
||||
{
|
||||
CharacterCount += 1;
|
||||
if(CharacterIndex < TrueCharacterIndex)
|
||||
{
|
||||
AssumedCharacterIndex += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
r32 Result = (r32)(AssumedCharacterIndex + 1) / (Max(CharacterCount, 1) + 1);
|
||||
return(Result);
|
||||
}
|
||||
|
||||
static void SV_UpdateInDialog(arena *FrameArena)
|
||||
|
@ -870,34 +895,34 @@ static void SV_UpdateInDialog(arena *FrameArena)
|
|||
|
||||
static void SV_Update(arena *FrameArena)
|
||||
{
|
||||
scene_view *SceneView = SV_GetState();
|
||||
|
||||
//- sixten: update the characters
|
||||
{
|
||||
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
|
||||
{
|
||||
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
|
||||
|
||||
if(!SV_CurrentlyInProc())
|
||||
{
|
||||
Data->Active = false;
|
||||
Data->Talking = false;
|
||||
}
|
||||
|
||||
AC_AnimateValueDirect(Data->Active, 0.5f, &Data->ActiveT);
|
||||
AC_AnimateValueDirect(Data->Talking, 0.4f, &Data->TalkingT);
|
||||
|
||||
r32 TargetPctP;
|
||||
if(Data->Active)
|
||||
{
|
||||
TargetPctP = SV_CalculateTargetPctP(CharacterIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
TargetPctP = (r32)(CharacterIndex+1)/(SceneView->CharactersUsed+1);
|
||||
}
|
||||
AC_AnimateValueDirect(TargetPctP, 0.4f, &Data->PctP);
|
||||
}
|
||||
scene_view *SceneView = SV_GetState();
|
||||
|
||||
//- sixten: update the characters
|
||||
{
|
||||
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
|
||||
{
|
||||
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
|
||||
|
||||
if(!SV_CurrentlyInProc())
|
||||
{
|
||||
Data->Active = false;
|
||||
Data->Talking = false;
|
||||
}
|
||||
|
||||
AC_AnimateValueDirect(Data->Active, 0.5f, &Data->ActiveT);
|
||||
AC_AnimateValueDirect(Data->Talking, 0.4f, &Data->TalkingT);
|
||||
|
||||
r32 TargetPctP;
|
||||
if(Data->Active)
|
||||
{
|
||||
TargetPctP = SV_CalculateTargetPctP(CharacterIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
TargetPctP = (r32)(CharacterIndex+1)/(SceneView->CharactersUsed+1);
|
||||
}
|
||||
AC_AnimateValueDirect(TargetPctP, 0.4f, &Data->PctP);
|
||||
}
|
||||
|
||||
// sixten: prune any unactive characters
|
||||
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
|
||||
|
@ -910,13 +935,144 @@ static void SV_Update(arena *FrameArena)
|
|||
CharacterIndex -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- sixten: update scene
|
||||
if(SV_CurrentlyInProc())
|
||||
{
|
||||
SV_UpdateInDialog(FrameArena);
|
||||
}
|
||||
}
|
||||
|
||||
// sixten(HACK): if a scene has been triggered, switch mode
|
||||
if(SceneView->Mode == SV_Mode_Nav && SV_CurrentlyInProc())
|
||||
{
|
||||
SceneView->Mode = SV_Mode_Scene;
|
||||
}
|
||||
|
||||
switch(SceneView->Mode)
|
||||
{
|
||||
case SV_Mode_Scene:
|
||||
{
|
||||
//- sixten: gather user input
|
||||
b32 MousePressed = false;
|
||||
for(platform_event *Event = SceneView->EventList->First; Event != 0; Event = Event->Next)
|
||||
{
|
||||
if(Event->Type == PlatformEvent_Press && Event->Key == Key_MouseLeft)
|
||||
{
|
||||
MousePressed = true;
|
||||
}
|
||||
}
|
||||
b32 PlayerAction = (Platform_KeyPress(SceneView->EventList, Key_Space)||MousePressed);
|
||||
|
||||
//- sixten: check if we can skip the current textbox
|
||||
if(PlayerAction && SceneView->TextboxRevealed < SceneView->TextboxUsed)
|
||||
{
|
||||
PlayerAction = false;
|
||||
SceneView->TextboxRevealed = SceneView->TextboxUsed;
|
||||
}
|
||||
|
||||
//- sixten: update the textbox
|
||||
r32 CharsPerSecond = 25.0f;
|
||||
SceneView->TextboxRevealed = Min((r32)SceneView->TextboxUsed, SceneView->TextboxRevealed+CharsPerSecond*SceneView->dtForFrame);
|
||||
|
||||
//- sixten: run the runtime
|
||||
scene2_run_result RunResult = S2_Run(FrameArena, &SceneView->Runtime, &SceneView->Compiled, PlayerAction);
|
||||
|
||||
//- sixten: append messages
|
||||
S2_ConcatMessageList(SceneView->MessageArena, &SceneView->Messages, &RunResult.Messages);
|
||||
|
||||
for(scene2_action *Action = RunResult.Actions.First; Action != 0; Action = Action->Next)
|
||||
{
|
||||
switch(Action->Kind)
|
||||
{
|
||||
case S2_ActionKind_None: { InvalidCodepath; } break;
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
}
|
||||
|
||||
// sixten: check if the scene is finished
|
||||
if(!SV_CurrentlyInProc() && SceneView->Mode == SV_Mode_Scene)
|
||||
{
|
||||
SceneView->Mode = SV_Mode_Nav;
|
||||
}
|
||||
} break;
|
||||
|
||||
case SV_Mode_Nav:
|
||||
{
|
||||
} break;
|
||||
|
||||
case SV_Mode_P15:
|
||||
{
|
||||
SceneView->TimeSinceBoardUpdate += SceneView->dtForFrame;
|
||||
AC_AnimateValueDirect(1, 2.0f, &SceneView->BoardOpenT);
|
||||
|
||||
if(SceneView->BoardIsComplete)
|
||||
{
|
||||
SceneView->TimeSinceBoardClear += SceneView->dtForFrame;
|
||||
if(SceneView->TimeSinceBoardClear > 3.5f)
|
||||
{
|
||||
SceneView->Mode = SV_Mode_Scene;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v2_s32 BoardDelta = V2S32(0, 0);
|
||||
|
||||
if(Platform_KeyPress(SceneView->EventList, Key_Up)) { BoardDelta.y += 1; }
|
||||
if(Platform_KeyPress(SceneView->EventList, Key_Down)) { BoardDelta.y -= 1; }
|
||||
if(Platform_KeyPress(SceneView->EventList, Key_Left)) { BoardDelta.x += 1; }
|
||||
if(Platform_KeyPress(SceneView->EventList, Key_Right)) { BoardDelta.x -= 1; }
|
||||
|
||||
if(BoardDelta.x != 0 || BoardDelta.y != 0)
|
||||
{
|
||||
if(BoardDelta.x && BoardDelta.y)
|
||||
{
|
||||
BoardDelta.y = 0;
|
||||
}
|
||||
// sixten: find the current empty square
|
||||
v2_s32 EmptyP = V2S32(-10, -10);
|
||||
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
|
||||
{
|
||||
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
|
||||
{
|
||||
if(SceneView->Board[BoardY][BoardX] == 0)
|
||||
{
|
||||
EmptyP = V2S32(BoardX, BoardY);
|
||||
goto FoundEmptyP;
|
||||
}
|
||||
}
|
||||
}
|
||||
FoundEmptyP:;
|
||||
|
||||
// sixten: check if we are able to perform an action
|
||||
range2_s32 BoardRange = Range2S32(V2S32(0, 0), V2S32(4, 4));
|
||||
v2_s32 NewEmptyP = EmptyP+BoardDelta;
|
||||
if(InRange(BoardRange, NewEmptyP))
|
||||
{
|
||||
SceneView->TimeSinceBoardUpdate = 0;
|
||||
Copy(SceneView->PrevBoard, SceneView->Board, sizeof(SceneView->Board));
|
||||
|
||||
SceneView->Board[EmptyP.y][EmptyP.x] = SceneView->Board[NewEmptyP.y][NewEmptyP.x];
|
||||
SceneView->Board[NewEmptyP.y][NewEmptyP.x] = 0;
|
||||
}
|
||||
|
||||
// sixten: check if board is completed
|
||||
b32 BoardIsComplete = true;
|
||||
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
|
||||
{
|
||||
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
|
||||
{
|
||||
if(SceneView->Board[BoardY][BoardX] != (1+BoardX+BoardY*4)%16)
|
||||
{
|
||||
BoardIsComplete = false;
|
||||
goto BoardNotComplete;
|
||||
}
|
||||
}
|
||||
}
|
||||
BoardNotComplete:;
|
||||
|
||||
if(BoardIsComplete)
|
||||
{
|
||||
SceneView->BoardIsComplete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
static void SV_BuildSceneView(vn_input *Input)
|
||||
|
@ -930,18 +1086,4 @@ static void SV_BuildSceneView(vn_input *Input)
|
|||
{
|
||||
BuildScene(SceneView);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
scene_user_input Input = SV_GatherInputs(); // note that we here could consume a player interaction for skipping the text
|
||||
scene_runtime_result Result = S_Run(&Runtime, &Inputs);
|
||||
for(scene_action *Action = Result.FirstAction; Action != 0; Action = Action->Next)
|
||||
{
|
||||
switch(Action->Kind)
|
||||
{
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
|
@ -66,6 +66,13 @@ struct scene_nav
|
|||
s32 ItemMax;
|
||||
};
|
||||
|
||||
enum scene_view_mode
|
||||
{
|
||||
SV_Mode_Scene,
|
||||
SV_Mode_Nav,
|
||||
SV_Mode_P15,
|
||||
};
|
||||
|
||||
struct scene_view
|
||||
{
|
||||
arena *SceneArena;
|
||||
|
@ -73,6 +80,7 @@ struct scene_view
|
|||
//- sixten: state
|
||||
scene2_runtime Runtime;
|
||||
compiled_scene2 Compiled;
|
||||
scene_view_mode Mode;
|
||||
|
||||
//- sixten: messages
|
||||
arena *MessageArena;
|
||||
|
@ -94,6 +102,14 @@ struct scene_view
|
|||
//- sixten: input per frame
|
||||
platform_event_list *EventList;
|
||||
r32 dtForFrame;
|
||||
|
||||
//- sixten: 15-puzzle
|
||||
r32 BoardOpenT;
|
||||
u8 Board[4][4];
|
||||
u8 PrevBoard[4][4];
|
||||
b32 BoardIsComplete;
|
||||
r32 TimeSinceBoardUpdate;
|
||||
r32 TimeSinceBoardClear;
|
||||
};
|
||||
|
||||
static void SV_SetState(scene_view *View);
|
||||
|
|
|
@ -273,12 +273,12 @@ static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View)
|
|||
UI_SetNextWidth(UI_ChildrenSum(1, 1));
|
||||
UI_SetNextHeight(UI_Percent(1, 1));
|
||||
UI_SetNextBackgroundColor(Brighten(BackgroundColor, 1.2f));
|
||||
UI_SetNextBorderColor(LinearBlend(UI_TopBackgroundColor(), Color_Grey, 0.5));
|
||||
UI_SetNextBorderColor(Darken(LinearBlend(UI_TopBackgroundColor(), Color_White, 0.2f), 1.2f));
|
||||
UI_SetNextLayoutAxis(Axis2_X);
|
||||
UI_SetNextCornerRadii(V4R32(3.0, 3.0, 0, 0));
|
||||
UI_SetNextCornerRadii(V4R32(5.0, 5.0, 0, 0));
|
||||
|
||||
ui_box *TabBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
|
||||
//UI_BoxFlag_DrawBorder |
|
||||
UI_BoxFlag_DrawBorder |
|
||||
UI_BoxFlag_DrawDropShadow |
|
||||
UI_BoxFlag_HotAnimation |
|
||||
UI_BoxFlag_ActiveAnimation |
|
||||
|
|
|
@ -240,12 +240,6 @@ static void W_BuildNavEditor(workspace_view *View)
|
|||
{
|
||||
W_NavEditorSerializeItems(Editor);
|
||||
}
|
||||
|
||||
//- sixten: create force reload
|
||||
if(UI_ButtonF("%U", FontIcon_ArrowsCW).Clicked)
|
||||
{
|
||||
SV_LoadNavItems();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,34 @@
|
|||
proc main
|
||||
call nav_load("data/omori.vnn")
|
||||
call proc_set("omori_1")
|
||||
end
|
||||
|
||||
proc omori_1
|
||||
s = "Sunny"
|
||||
|
||||
$(s) "There is something I have to tell you."
|
||||
$(s) "It's about MARI."
|
||||
$(s) "..."
|
||||
$(s) "She didn't kill herself."
|
||||
|
||||
$(s) "It was the day of the recital."
|
||||
$(s) "We had been rehearsing for hours, but no matter how much time we spent it was never good enough."
|
||||
$(s) "I had just messed up a note when in my anger I stormed out."
|
||||
$(s) "MARI was quick to follow me, just in time to see me throw the violin to the ground."
|
||||
$(s) "We were at the top of the stairs when she finally managed to grab my arm."
|
||||
$(s) "She was so calm... Not mad at all... Just disappointed."
|
||||
$(s) "But I didn't want to be there. I didn't want her to be there. I just wanted to go away."
|
||||
$(s) "Before I was able to run away again, she blocked my path and without thinking I pushed and..."
|
||||
$(s) "...she fell."
|
||||
$(s) "She fell down the stairs."
|
||||
|
||||
$(s) "That same day, BASIL happened to be visiting."
|
||||
$(s) "He couldn't believe what he saw and in order to protect me..."
|
||||
$(s) "...he and I staged MARI's suicide."
|
||||
end
|
||||
|
||||
proc puzzle_test
|
||||
$ "Can you beat the IMPOSSIBLE duck puzzle?"
|
||||
call puzzle_15()
|
||||
$ "Wow, you actually did it."
|
||||
end
|
Binary file not shown.
After Width: | Height: | Size: 569 KiB |
Loading…
Reference in New Issue