forked from Mirrors/openclonk
Add MtBrame.ocs, a cooperative scenario for BeyondTheRocks
parent
db4ad404b1
commit
a0b13ad238
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,9 @@
|
|||
[DefCore]
|
||||
id=Dialogue
|
||||
Version=5,2,0,1
|
||||
Category=C4D_StaticBack
|
||||
Width=8
|
||||
Height=20
|
||||
Offset=-4,-10
|
||||
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
|
@ -0,0 +1,215 @@
|
|||
/**
|
||||
Dialogue
|
||||
|
||||
Attach to a non player charachter to provide a message interface.
|
||||
*/
|
||||
|
||||
|
||||
local dlg_target;
|
||||
local dlg_name;
|
||||
local dlg_info;
|
||||
local dlg_progress;
|
||||
local dlg_status;
|
||||
|
||||
static const DLG_Status_Active = 0;
|
||||
static const DLG_Status_Stop = 1;
|
||||
static const DLG_Status_Remove = 2;
|
||||
|
||||
|
||||
/*-- Dialogue creation --*/
|
||||
|
||||
// Sets a new dialogue for a npc.
|
||||
global func SetDialogue(string name)
|
||||
{
|
||||
if (!this)
|
||||
return;
|
||||
var dialogue = CreateObject(Dialogue);
|
||||
dialogue->InitDialogue(name, this);
|
||||
|
||||
dialogue->SetObjectLayer(nil);
|
||||
|
||||
return dialogue;
|
||||
}
|
||||
|
||||
// Removes the existing dialogue of an object.
|
||||
global func RemoveDialogue()
|
||||
{
|
||||
if (!this)
|
||||
return;
|
||||
|
||||
var dialogue = FindObject(Find_ID(Dialogue), Find_ActionTarget(this));
|
||||
if (dialogue)
|
||||
dialogue->RemoveObject();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*-- Dialogue properties --*/
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
// Dialogue progress to one.
|
||||
dlg_progress = 1;
|
||||
|
||||
dlg_status = DLG_Status_Active;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public func InitDialogue(string name, object target)
|
||||
{
|
||||
dlg_target = target;
|
||||
dlg_name = name;
|
||||
|
||||
// Attach dialogue object to target.
|
||||
SetAction("Dialogue", target);
|
||||
|
||||
// Update dialogue to target.
|
||||
UpdateDialogue();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private func UpdateDialogue()
|
||||
{
|
||||
// Adapt size to target and its direction.
|
||||
var wdt = dlg_target->GetID()->GetDefWidth();
|
||||
var hgt = dlg_target->GetID()->GetDefHeight();
|
||||
var dir = dlg_target->GetDir();
|
||||
SetShape(-wdt/2 + 2*(dir-1)*wdt, -hgt/2, 3*wdt, hgt);
|
||||
// Transfer target name.
|
||||
//SetName(Format("$MsgSpeak$", dlg_target->GetName()));
|
||||
return;
|
||||
}
|
||||
|
||||
public func SetDialogueInfo()
|
||||
{
|
||||
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public func SetDialogueProgress(int progress)
|
||||
{
|
||||
dlg_progress = Max(1, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
public func SetDialogueStatus(int status)
|
||||
{
|
||||
dlg_status = status;
|
||||
return;
|
||||
}
|
||||
|
||||
/*-- Interaction --*/
|
||||
|
||||
// Players can talk to NPC via the interaction bar.
|
||||
public func IsInteractable() { return true; }
|
||||
|
||||
// Adapt appearance in the interaction bar.
|
||||
public func GetInteractionMetaInfo(object clonk)
|
||||
{
|
||||
if (InDialogue(clonk))
|
||||
return { Description = Format("$MsgSpeak$", dlg_target->GetName()) , IconName = nil, IconID = Clonk, Selected = true };
|
||||
|
||||
return { Description = Format("$MsgSpeak$", dlg_target->GetName()) , IconName = nil, IconID = Clonk, Selected = false };
|
||||
}
|
||||
|
||||
// Called on player interaction.
|
||||
public func Interact(object clonk)
|
||||
{
|
||||
// Currently in a dialogue: abort that dialogue.
|
||||
if (InDialogue(clonk))
|
||||
clonk->CloseMenu();
|
||||
|
||||
// No conversation context: abort.
|
||||
if (!dlg_name)
|
||||
return true;
|
||||
|
||||
// Stop dialogue?
|
||||
if (dlg_status == DLG_Status_Stop)
|
||||
{
|
||||
clonk->CloseMenu();
|
||||
dlg_status = DLG_Status_Active;
|
||||
return true;
|
||||
}
|
||||
// Remove dialogue?
|
||||
if (dlg_status == DLG_Status_Remove)
|
||||
{
|
||||
clonk->CloseMenu();
|
||||
RemoveObject();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Start conversation context.
|
||||
// Update dialogue progress first.
|
||||
var progress = dlg_progress;
|
||||
dlg_progress++;
|
||||
// Then call relevant functions.
|
||||
Call(Format("Dlg_%s_%d", dlg_name, progress), clonk);
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private func InDialogue(object clonk)
|
||||
{
|
||||
return clonk->GetMenu() == Dialogue;
|
||||
}
|
||||
|
||||
public func MessageBoxAll(string message, object talker)
|
||||
{
|
||||
for(var i = 0; i < GetPlayerCount(); ++i)
|
||||
MessageBox(message, GetCursor(GetPlayerByIndex(i)), talker);
|
||||
}
|
||||
|
||||
private func MessageBox(string message, object clonk, object talker)
|
||||
{
|
||||
// Use current NPC as talker if unspecified.
|
||||
if (!talker)
|
||||
talker = dlg_target;
|
||||
|
||||
// Use a menu for this dialogue.
|
||||
clonk->CreateMenu(Dialogue, this, C4MN_Extra_None, nil, nil, C4MN_Style_Dialog, false, Dialogue);
|
||||
|
||||
// Add NPC portrait.
|
||||
//var portrait = Format("%i", talker->GetID()); //, Dialogue, talker->GetColor(), "1");
|
||||
clonk->AddMenuItem("", "", Dialogue, nil, nil, nil, C4MN_Add_ImgObject, talker); //TextSpec);
|
||||
|
||||
// Add NPC message.
|
||||
var msg = Format("<c %x>%s:</c> %s", talker->GetColor(), talker->GetName(), message);
|
||||
clonk->AddMenuItem(msg, "", nil, nil, nil, nil, C4MN_Add_ForceNoDesc);
|
||||
|
||||
// Add answers.
|
||||
//for (var i = 0; i < GetLength(message.Answers); i++)
|
||||
//{
|
||||
// var ans = message.Answers[i][0];
|
||||
// var call_back = message.Answers[i][1];
|
||||
// target->AddMenuItem(ans, call_back, nil, nil, target, nil, C4MN_Add_ForceNoDesc);
|
||||
//}
|
||||
|
||||
// Set menu decoration.
|
||||
clonk->SetMenuDecoration(GUI_MenuDeco);
|
||||
|
||||
// Set text progress to NPC name.
|
||||
var name = dlg_target->GetName();
|
||||
var n_length;
|
||||
while (GetChar(name, n_length))
|
||||
n_length++;
|
||||
clonk->SetMenuTextProgress(n_length + 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
local ActMap = {
|
||||
Dialogue = {
|
||||
Prototype = Action,
|
||||
Name = "Dialogue",
|
||||
Procedure = DFA_ATTACH,
|
||||
Delay = 0,
|
||||
NextAction = "Dialogue",
|
||||
}
|
||||
};
|
||||
local Name = "$Name$";
|
|
@ -0,0 +1,2 @@
|
|||
Name=Dialogue
|
||||
MsgSpeak=%s ansprechen
|
|
@ -0,0 +1,2 @@
|
|||
Name=Dialogue
|
||||
MsgSpeak=Speak to %s
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,5 @@
|
|||
[DefCore]
|
||||
id=Goal_GetBack
|
||||
Version=5,2,0,1
|
||||
Category=C4D_StaticBack|C4D_Goal
|
||||
Picture=0,0,128,128
|
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,50 @@
|
|||
/*--
|
||||
Get back goal
|
||||
Author: ck
|
||||
|
||||
All players have to get back to the hut
|
||||
--*/
|
||||
|
||||
|
||||
#include Library_Goal
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
return inherited(...);
|
||||
}
|
||||
|
||||
public func IsFulfilled()
|
||||
{
|
||||
var cabin = FindObject(Find_ID(WoodenCabin));
|
||||
if (!cabin)
|
||||
return false;
|
||||
if (!GetPlayerCount() || GetEffect("IntIntro"))
|
||||
return false;
|
||||
|
||||
for(var i = 0; i < GetPlayerCount(); ++i)
|
||||
{
|
||||
var plr = GetPlayerByIndex(i), obj;
|
||||
for(var j = 0; obj = GetCrew(plr, j); ++j)
|
||||
if(ObjectDistance(obj, cabin) > 80)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public func Activate(int byplr)
|
||||
{
|
||||
if (IsFulfilled())
|
||||
MessageWindow("$MsgGoalFulfilled$", byplr);
|
||||
else
|
||||
MessageWindow("$MsgGoalUnFulfilled$", byplr);
|
||||
return;
|
||||
}
|
||||
|
||||
public func GetShortDescription(int plr)
|
||||
{
|
||||
return "{{WoodenCabin}}"; // TODO
|
||||
}
|
||||
|
||||
/*-- Proplist --*/
|
||||
local Name = "$Name$";
|
|
@ -0,0 +1,3 @@
|
|||
Name=Finde den Weg zurück
|
||||
MsgGoalFulfilled=Ihr habt den Weg zurück gefunden.
|
||||
MsgGoalUnFulfilled=Ihr seid noch nicht zuhause.
|
|
@ -0,0 +1,3 @@
|
|||
Name=Find your way back home
|
||||
MsgGoalFulfilled=You have made your way back home.
|
||||
MsgGoalUnFulfilled=You are not at home yet.
|
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
|
@ -0,0 +1,38 @@
|
|||
[Head]
|
||||
Icon=23
|
||||
Title=MtBrame
|
||||
Version=5,2,90,21
|
||||
Difficulty=50
|
||||
MaxPlayer=3
|
||||
NoInitialize=true
|
||||
|
||||
[Game]
|
||||
Rules=Rule_TeamAccount=1
|
||||
|
||||
[Player1]
|
||||
Crew=Clonk=1
|
||||
Knowledge=Lorry=1;Catapult=1;Pickaxe=1;Axe=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;Loam=1
|
||||
|
||||
[Player2]
|
||||
Crew=Clonk=1
|
||||
Knowledge=Lorry=1;Catapult=1;Pickaxe=1;Axe=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;Loam=1
|
||||
|
||||
[Player3]
|
||||
Crew=Clonk=1
|
||||
Knowledge=Lorry=1;Catapult=1;Pickaxe=1;Axe=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;Loam=1
|
||||
|
||||
[Player4]
|
||||
Crew=Clonk=1
|
||||
Knowledge=Lorry=1;Catapult=1;Pickaxe=1;Axe=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;Loam=1
|
||||
|
||||
[Landscape]
|
||||
Sky=Clouds2
|
||||
MapWidth=200,0,64,10000
|
||||
MapHeight=175,0,40,10000
|
||||
NoScan=true
|
||||
NewStyleLandscape=2
|
||||
|
||||
[Weather]
|
||||
Climate=30,10,0,100
|
||||
YearSpeed=0,0,0,100
|
||||
Wind=0,100,-100,100
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
Mt. Brame
|
||||
Find a way back to your hut, defeating the dangers of Mt. Brame
|
||||
|
||||
@authors ck
|
||||
*/
|
||||
|
||||
static g_is_initialized;
|
||||
|
||||
func DoInit(int first_player)
|
||||
{
|
||||
// Set time of day to morning and create some clouds and celestials.
|
||||
Cloud->Place(20);
|
||||
CreateObject(Environment_Celestial);
|
||||
var time = CreateObject(Environment_Time);
|
||||
time->SetTime(400);
|
||||
time->SetCycleSpeed(4);
|
||||
|
||||
// Workshop owner
|
||||
var workshop = FindObject(Find_ID(ToolsWorkshop));
|
||||
if (workshop) workshop->SetOwner(first_player);
|
||||
|
||||
// Goal
|
||||
CreateObject(Goal_GetBack);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
func InitializePlayer(int plr)
|
||||
{
|
||||
var crew;
|
||||
// Scenario init
|
||||
if (!g_is_initialized) g_is_initialized = DoInit(plr);
|
||||
// Start intro if not yet started
|
||||
IntroStart();
|
||||
// Add player to intro if recently started
|
||||
if(!IntroAddPlayer(plr))
|
||||
{
|
||||
// Too late for entry? Just start in the valley
|
||||
var index = 0;
|
||||
for(var index = 0; crew = GetCrew(plr, index); ++index)
|
||||
{
|
||||
var x = 260*8/10 + Random(50);
|
||||
var y = 1350*8/10;
|
||||
crew->SetPosition(x , y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
|
||||
static g_intro_initialized;
|
||||
|
||||
global func IntroStart()
|
||||
{
|
||||
if(!g_intro_initialized && !GetEffect("IntIntro"))
|
||||
{
|
||||
AddEffect("IntIntro", nil, 1, 2, nil, nil);
|
||||
g_intro_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
global func IntroAddPlayer(int plr)
|
||||
{
|
||||
var effect = GetEffect("IntIntro");
|
||||
if(!effect) return false;
|
||||
if(effect.Time > 30) return false;
|
||||
|
||||
var crew;
|
||||
for(var index = 0; crew = GetCrew(plr, index); ++index)
|
||||
{
|
||||
var skin = crew->GetCrewExtraData("Skin");
|
||||
if (skin == nil) skin = GetPlrClonkSkin(plr);
|
||||
|
||||
var container = effect.Cabin->CreateContents(Clonk);
|
||||
container->SetOwner(plr);
|
||||
if(skin != nil) container->SetSkin(skin);
|
||||
container->SetName(crew->GetName());
|
||||
container->SetAction("Walk");
|
||||
crew->Enter(container);
|
||||
|
||||
SetPlrView(plr, crew);
|
||||
SetPlayerViewLock(plr, true);
|
||||
SetPlayerZoomByViewRange(plr, 320, 240);
|
||||
|
||||
container->SetCommand("None", container);
|
||||
crew->SetCommand("None", crew);
|
||||
|
||||
effect.Players[GetLength(effect.Players)] = crew;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
global func IntroCreateBoompack(int x, int y, int fuel)
|
||||
{
|
||||
var boompack = CreateObject(Boompack, x, y, NO_OWNER);
|
||||
boompack->SetFuel(fuel);
|
||||
boompack->SetDirectionDeviation(8); // make sure direction of boompack is roughly kept
|
||||
boompack->SetControllable(false);
|
||||
return boompack;
|
||||
}
|
||||
|
||||
global func FxIntIntroStart(object target, proplist effect)
|
||||
{
|
||||
effect.Cabin = FindObject(Find_ID(WoodenCabin));
|
||||
if(!effect.Cabin) return -1;
|
||||
|
||||
effect.Sister = CreateObject(Clonk, 174, 532, NO_OWNER);
|
||||
effect.Sister->MakeInvincible();
|
||||
effect.Sister->MakeNonFlammable();
|
||||
effect.Sister->SetSkin(1);
|
||||
effect.Sister->SetName("$NameSister$");
|
||||
effect.Sister->SetColor(RGB(213, 68, 172));
|
||||
effect.Sister->SetObjectLayer(effect.Sister);
|
||||
effect.Sister->SetDir(DIR_Right);
|
||||
|
||||
effect.Dialog = effect.Sister->SetDialogue("Sister");
|
||||
effect.Rock = effect.Sister->CreateContents(Rock);
|
||||
effect.Rock->SetObjectLayer(0);
|
||||
effect.Players = [];
|
||||
}
|
||||
|
||||
global func FxIntIntroTimer(object target, proplist effect, int time)
|
||||
{
|
||||
if(effect.Time == 40)
|
||||
{
|
||||
effect.Sister->SetCommand("MoveTo", effect.Sister, effect.Cabin->GetX() + 65 - effect.Sister->GetX(), effect.Cabin->GetY() + 10 - effect.Sister->GetY());
|
||||
}
|
||||
|
||||
if(effect.Time == 110)
|
||||
effect.Dialog->MessageBoxAll("$MsgIntro1$", effect.Sister);
|
||||
|
||||
if(effect.Time == 150)
|
||||
{
|
||||
for(var crew in effect.Players)
|
||||
{
|
||||
crew = crew->Contained();
|
||||
|
||||
crew->SetCommand("Exit", crew);
|
||||
crew->AppendCommand("MoveTo", crew, effect.Cabin->GetX() + RandomX(10,40) - crew->GetX(), effect.Cabin->GetY() - crew->GetY());
|
||||
}
|
||||
}
|
||||
|
||||
if(effect.Time == 200)
|
||||
effect.Dialog->MessageBoxAll("$MsgIntro2$", GetCrew(GetPlayerByIndex(Random(GetPlayerCount())), 0));
|
||||
|
||||
if(effect.Time == 270)
|
||||
{
|
||||
effect.Dialog->MessageBoxAll("$MsgIntro3$", effect.Sister);
|
||||
}
|
||||
|
||||
if(effect.Time == 350)
|
||||
{
|
||||
effect.Sister->SetCommand("MoveTo", effect.Sister, 214 - effect.Sister->GetX(), 540 - effect.Sister->GetY());
|
||||
}
|
||||
|
||||
if(effect.Time == 370)
|
||||
{
|
||||
for(var crew in effect.Players)
|
||||
{
|
||||
crew = crew->Contained();
|
||||
crew->SetCommand("MoveTo", crew, 245 - crew->GetX(), 555 - crew->GetY());
|
||||
}
|
||||
}
|
||||
|
||||
if(effect.Time == 500)
|
||||
{
|
||||
effect.Sister->SetCommand("MoveTo", effect.Sister, 214 - effect.Sister->GetX(), 540 - effect.Sister->GetY());
|
||||
for(var crew in effect.Players)
|
||||
crew->Contained()->SetDir(DIR_Left);
|
||||
effect.Dialog->MessageBoxAll("$MsgIntro4$", GetCrew(GetPlayerByIndex(Random(GetPlayerCount())), 0));
|
||||
}
|
||||
|
||||
if(effect.Time == 520)
|
||||
effect.Sister->SetDir(DIR_Right);
|
||||
|
||||
if(effect.Time == 550)
|
||||
{
|
||||
effect.Sister->ObjectCommand("Throw", effect.Rock, 500, 100);
|
||||
for(var i = 0; i < GetPlayerCount(); ++i)
|
||||
SetPlrView(GetPlayerByIndex(i), effect.Sister);
|
||||
}
|
||||
|
||||
if(effect.Time == 570)
|
||||
{
|
||||
effect.Dialog->MessageBoxAll("$MsgIntro5$", effect.Sister);
|
||||
}
|
||||
|
||||
if(effect.Time == 620)
|
||||
{
|
||||
effect.Dialog->MessageBoxAll("$MsgIntro6$", GetCrew(GetPlayerByIndex(Random(GetPlayerCount())), 0));
|
||||
}
|
||||
|
||||
if(effect.Time == 700)
|
||||
{
|
||||
effect.Dialog->MessageBoxAll("$MsgIntro7$", effect.Sister);
|
||||
}
|
||||
|
||||
if(effect.Time == 800)
|
||||
{
|
||||
effect.Dialog->MessageBoxAll("$MsgIntro8$", effect.Sister);
|
||||
}
|
||||
|
||||
if(effect.Time == 860)
|
||||
{
|
||||
effect.Sister->SetCommand("Enter", effect.Cabin);
|
||||
}
|
||||
|
||||
if(effect.Time == 920)
|
||||
{
|
||||
for(var i = 0; i < GetPlayerCount(); ++i)
|
||||
GetCursor(GetPlayerByIndex(i))->CloseMenu();
|
||||
}
|
||||
|
||||
if(effect.Time == 950)
|
||||
{
|
||||
for(var crew in effect.Players)
|
||||
{
|
||||
SetPlrView(crew->GetOwner(), crew);
|
||||
SetPlayerViewLock(crew->GetOwner(), true);
|
||||
var container = crew->Contained();
|
||||
crew->Exit(0, 10);
|
||||
container->RemoveObject();
|
||||
}
|
||||
|
||||
for(var i = 0; i < GetPlayerCount(); ++i)
|
||||
GetCursor(GetPlayerByIndex(i))->CloseMenu();
|
||||
}
|
||||
|
||||
if(effect.Time >= 1000)
|
||||
{
|
||||
// just to be sure...
|
||||
effect.Sister->Enter(effect.Cabin);
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#appendto ToolsWorkshop
|
||||
|
||||
private func PowerNeed() { return 0; }
|
|
@ -0,0 +1,12 @@
|
|||
# Intro
|
||||
NameSister=Ruth
|
||||
|
||||
# Intro
|
||||
MsgIntro1=Hey ihr Schlafmützen, schaut mal was ich gefunden habe!
|
||||
MsgIntro2=...was? Wo denn?
|
||||
MsgIntro3=Dort unten, am Hang!
|
||||
MsgIntro4=Und was soll hier sein..?
|
||||
MsgIntro5=Hihi...!
|
||||
MsgIntro6=Waaaaaah!
|
||||
MsgIntro7=Hm, war vielleicht doch ein bisschen tief?
|
||||
MsgIntro8=Egal, die werden schon rausfinden...
|
|
@ -0,0 +1,11 @@
|
|||
NameSister=Ruth
|
||||
|
||||
# Intro
|
||||
MsgIntro1=Hey sleepyheads! Check out what I have found!
|
||||
MsgIntro2=...what? And where?
|
||||
MsgIntro3=Down there, at the hillside!
|
||||
MsgIntro4=And what's supposed to be here..?
|
||||
MsgIntro5=Hihi...!
|
||||
MsgIntro6=Waaaaaah!
|
||||
MsgIntro7=Hm, maybe it was a bit deep in the end?
|
||||
MsgIntro8=Whatever, they will find their way...
|
|
@ -0,0 +1,5 @@
|
|||
[Teams]
|
||||
Active=false
|
||||
Custom=false
|
||||
AllowHostilityChange=true
|
||||
AutoGenerateTeams=true
|
|
@ -0,0 +1,2 @@
|
|||
DE:Mount Brame
|
||||
US:Mount Brame
|
Loading…
Reference in New Issue