From 97f87019b7fa8a5e2fb4a749ddf7b1c8aadcee73 Mon Sep 17 00:00:00 2001 From: Maikel de Vries Date: Tue, 13 Mar 2018 20:37:46 +0100 Subject: [PATCH] waterfall: implement editor interface --- planet/Arena.ocf/RockBottom.ocs/Script.c | 4 +- .../Environment.ocd/Waterfall.ocd/DefCore.txt | 3 + .../Waterfall.ocd/Graphics.png | Bin 0 -> 2953 bytes .../Environment.ocd/Waterfall.ocd/Script.c | 241 +++++++++++------- .../Waterfall.ocd/StringTblDE.txt | 20 ++ .../Waterfall.ocd/StringTblUS.txt | 20 ++ planet/Tutorials.ocf/Tutorial01.ocs/Script.c | 4 +- planet/Worlds.ocf/Chine.ocs/Script.c | 2 +- planet/Worlds.ocf/RapidRefining.ocs/Script.c | 2 +- 9 files changed, 202 insertions(+), 94 deletions(-) create mode 100644 planet/Objects.ocd/Environment.ocd/Waterfall.ocd/Graphics.png diff --git a/planet/Arena.ocf/RockBottom.ocs/Script.c b/planet/Arena.ocf/RockBottom.ocs/Script.c index bb579ae49..e389cbee5 100644 --- a/planet/Arena.ocf/RockBottom.ocs/Script.c +++ b/planet/Arena.ocf/RockBottom.ocs/Script.c @@ -35,9 +35,9 @@ protected func Initialize() var waterfall; waterfall = CreateWaterfall(130, 53, 2, "Water"); - waterfall->SetDirection(4, 0, 3, 6); + waterfall->SetDirection(6, 3, 2, 3); waterfall = CreateWaterfall(144, 50, 8, "Water"); - waterfall->SetDirection(6, 0, 5, 6); + waterfall->SetDirection(9, 3, 3, 3); CreateLiquidDrain(100, 315, 10); CreateLiquidDrain(130, 315, 10); CreateLiquidDrain(160, 315, 10); diff --git a/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/DefCore.txt b/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/DefCore.txt index e7cb7c985..f94bf6347 100644 --- a/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/DefCore.txt +++ b/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/DefCore.txt @@ -2,3 +2,6 @@ id=Waterfall Version=8,0 Category=C4D_StaticBack +Width=32 +Height=32 +Offset=-16,-16 \ No newline at end of file diff --git a/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/Graphics.png b/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/Graphics.png new file mode 100644 index 0000000000000000000000000000000000000000..75508d7aa7076dd9cd948a412f76f2d1f4f00ae9 GIT binary patch literal 2953 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.FxWaterfallLiquidSource, 100, 1, x, y, strength, mat); + return waterfall; } -protected func FxIntWaterfallStart(object target, proplist effect, int temporary, int x, int y, int strength, string mat) +local FxWaterfallLiquidSource = new Effect { - if (temporary) - return 1; - effect.X = x; - effect.Y = y; - effect.Strength = strength; - effect.Material = mat; - // Start sound. - target->Sound("Environment::Waterfall", false, 5 * effect.Strength, nil, 1); - return 1; -} - -protected func FxIntWaterfallTimer(object target, proplist effect) -{ - // Insert liquid at location every frame. - for (var i = 0; i < effect.Strength / 2; i++) - InsertMaterial(Material(effect.Material), AbsX(effect.X), AbsY(effect.Y), effect.XDir + Random(effect.XVar), effect.YDir + Random(effect.YVar)); - return 1; -} - -protected func FxIntWaterfallStop(object target, proplist effect, bool temporary) -{ - if (temporary) - return 1; - // Stop sound. - target->Sound("Environment::Waterfall", false, 5 * effect.Strength, nil, -1); - return 1; -} + Construction = func(int x, int y, int strength, string mat) + { + this.source_position = [x, y]; + this.source_direction = [x, y]; + this.source_x = x; + this.source_y = y; + this.source_strength = strength; + this.source_mat = mat; + // Start sound. + Target->Sound("Environment::Waterfall", false, 5 * this.source_strength, nil, 1); + return FX_OK; + }, + Timer = func(int time) + { + // Insert liquid at location every frame. + for (var i = 0; i < this.source_strength / 2; i++) + Global->InsertMaterial(Material(this.source_mat), this.source_x, this.source_y, this.xdir + RandomX(-this.xvar, this.xvar), this.ydir + RandomX(-this.yvar, this.yvar)); + return FX_OK; + }, + Destruction = func() + { + // Stop sound. + Target->Sound("Environment::Waterfall", false, 5 * this.source_strength, nil, -1); + return FX_OK; + }, + EditorProps = + { + source_strength = { Name = "$EditorSourceStrength$", EditorHelp = "$EditorSourceStrengthHelp$", Type = "int", Min = 2, Max = 100 }, + source_mat = { Name = "$EditorSourceMaterial$", EditorHelp = "$EditorSourceMaterialHelp$", Type = "enum", Options = [ + { Name = "$EditorSourceMaterialWater$", Value = "Water" }, + { Name = "$EditorSourceMaterialAcid$", Value = "Acid" }, + { Name = "$EditorSourceMaterialLava$", Value = "Lava" }, + { Name = "$EditorSourceMaterialDuroLava$", Value = "DuroLava" }, + { Name = "$EditorSourceMaterialOil$", Value = "Oil" } + ] }, + // TODO: Replace these two properties with an arrow in editor once available. + source_position = { Name = "$EditorSourcePosition$", EditorHelp = "$EditorSourcePositionHelp$", Type = "point", Relative = false, Color = 0x008fff, Set = "SetSourcePosition" }, + source_direction = { Name = "$EditorSourceDirection$", EditorHelp = "$EditorSourceDirectionHelp$", Type = "point", Relative = false, Color = 0x006bbb, Set = "SetSourceDirection" } + }, + SetSourcePosition = func(array pos) + { + this.source_position = pos; + this.source_x = pos[0]; + this.source_y = pos[1]; + }, + SetSourceDirection = func(array dir) + { + this.source_direction = dir; + this.xdir = dir[0] - this.source_x; + this.ydir = dir[1] - this.source_y; + this.xvar = Abs(this.xdir / 2); + this.yvar = Abs(this.ydir / 2); + } +}; public func SetStrength(int strength) { - var effect = GetEffect("IntWaterfall", this); - if (effect) - effect.Strength = BoundBy(strength, 0, 100); + var fx_waterfall = GetEffect("FxWaterfallLiquidSource", this); + if (fx_waterfall) + fx_waterfall.source_strength = BoundBy(strength, 0, 100); return; } public func SetMaterial(int material) { - var effect = GetEffect("IntWaterfall", this); - if (effect) - effect.Material = material; + var fx_waterfall = GetEffect("FxWaterfallLiquidSource", this); + if (fx_waterfall) + fx_waterfall.source_mat = material; return; } public func SetDirection(int xdir, int ydir, int xvar, int yvar) { - var effect = GetEffect("IntWaterfall", this); - if (effect) + var fx_waterfall = GetEffect("FxWaterfallLiquidSource", this); + if (fx_waterfall) { - effect.XDir = xdir; - effect.YDir = ydir; - effect.XVar = xvar; - effect.YVar = yvar; + fx_waterfall.xdir = xdir; + fx_waterfall.ydir = ydir; + fx_waterfall.xvar = xvar; + fx_waterfall.yvar = yvar; + fx_waterfall.source_direction = [fx_waterfall.source_x + xdir, fx_waterfall.source_y + ydir]; } return; } @@ -85,58 +108,100 @@ public func SetSoundLocation(int x, int y) { SetPosition(x, y); // Update sound. - var effect = GetEffect("IntWaterfall", this); - if (effect) - Sound("Environment::Waterfall", false, 5 * effect.Strength, nil, 1); + var fx_waterfall = GetEffect("FxWaterfallLiquidSource", this); + if (fx_waterfall) + Sound("Environment::Waterfall", false, 5 * fx_waterfall.source_strength, nil, 1); return; } -// Scenario saving -func SaveScenarioObject(props) -{ - if (!inherited(props, ...)) return false; - var fx_waterfall = GetEffect("IntWaterfall", this), fx_drain = GetEffect("IntLiquidDrain", this); - if (!fx_waterfall && !fx_drain) return false; // effects lost? don't save dead object then - // Waterfall has its own creation procedure - props->RemoveCreation(); - if (fx_waterfall) - { - props->Add(SAVEOBJ_Creation, "CreateWaterfall(%d, %d, %d, %v)",fx_waterfall.X, fx_waterfall.Y, fx_waterfall.Strength, fx_waterfall.Material); - if (fx_waterfall.X != GetX() || fx_waterfall.Y != GetY()) props->AddCall("Position", this, "SetSoundLocation", GetX(), GetY()); - if (fx_waterfall.XDir || fx_waterfall.YDir || fx_waterfall.XVar || fx_waterfall.YVar) - props->AddCall("Direction", this, "SetDirection", fx_waterfall.XDir, fx_waterfall.YDir, fx_waterfall.XVar, fx_waterfall.YVar); - } - if (fx_drain) props->Add(SAVEOBJ_Creation, "CreateLiquidDrain(%d, %d, %d)",fx_drain.X, fx_drain.Y, fx_drain.Strength); - return true; -} - - /*-- Liquid Drain --*/ global func CreateLiquidDrain(int x, int y, int strength) { var drain = CreateObjectAbove(Waterfall, x, y, NO_OWNER); - AddEffect("IntLiquidDrain", drain, 100, 1, drain, nil, x, y, strength); + drain->CreateEffect(drain.FxWaterfallLiquidDrain, 100, 1, x, y, strength); return drain; } -protected func FxIntLiquidDrainStart(object target, proplist effect, int temporary, int x, int y, int strength) +local FxWaterfallLiquidDrain = new Effect { - if (temporary) - return 1; - effect.X = x; - effect.Y = y; - effect.Strength = strength; - return 1; -} + Construction = func(int x, int y, int strength) + { + this.drain_position = [x, y]; + this.drain_x = x; + this.drain_y = y; + this.drain_strength = strength; + return FX_OK; + }, + Timer = func(int time) + { + Global->ExtractLiquidAmount(this.drain_x, this.drain_y, this.drain_strength / 2); + return FX_OK; + }, + EditorProps = + { + drain_strength = { Name = "$EditorDrainStrength$", EditorHelp = "$EditorDrainStrengthHelp$", Type = "int", Min = 2, Max = 100}, + drain_position = { Name = "$EditorDrainPosition$", EditorHelp = "$EditorDrainPositionHelp$", Type = "point", Relative = false, Color = 0x00ff8f, Set = "SetDrainPosition" } + }, + SetDrainPosition = func(array pos) + { + this.drain_position = pos; + this.drain_x = pos[0]; + this.drain_y = pos[1]; + } +}; -protected func FxIntLiquidDrainTimer(object target, proplist effect) + +/*-- Editor --*/ + +public func EditorInitialize() { - ExtractLiquidAmount(AbsX(effect.X), AbsY(effect.Y),effect.Strength / 2); - return 1; + // Init waterfall with the source directly above the drain. + this->CreateEffect(this.FxWaterfallLiquidSource, 100, 1, GetX(), GetY() - 40, 10, "Water"); + this->CreateEffect(this.FxWaterfallLiquidDrain, 100, 1, GetX(), GetY() + 40, 10); + return; } +/*-- Scenario Saving --*/ + +public func SaveScenarioObject(proplist props) +{ + if (!inherited(props, ...)) + return false; + var fx_source = GetEffect("FxWaterfallLiquidSource", this); + var fx_drain = GetEffect("FxWaterfallLiquidDrain", this); + if (!fx_source && !fx_drain) + return false; + if (fx_source) + { + props->AddCall("SourceEffect", this, "AddSourceEffect", fx_source.source_x, fx_source.source_y, fx_source.source_strength, Format("%v", fx_source.source_mat)); + if (fx_source.source_x != GetX() || fx_source.source_y != GetY()) + props->AddCall("SoundLocation", this, "SetSoundLocation", GetX(), GetY()); + if (fx_source.xdir || fx_source.xdir || fx_source.xvar || fx_source.yvar) + props->AddCall("Direction", this, "SetDirection", fx_source.xdir, fx_source.ydir, fx_source.xvar, fx_source.yvar); + } + if (fx_drain) + props->AddCall("DrainEffect", this, "AddDrainEffect", fx_drain.drain_x, fx_drain.drain_y, fx_drain.drain_strength); + return true; +} + +public func AddSourceEffect(int x, int y, int strength, string mat) +{ + CreateEffect(this.FxWaterfallLiquidSource, 100, 1, x, y, strength, mat); + return; +} + +public func AddDrainEffect(int x, int y, int strength) +{ + CreateEffect(this.FxWaterfallLiquidDrain, 100, 1, x, y, strength); + return; +} + + +/*-- Properties --*/ local Name = "$Name$"; +local Description = "$Description$"; +local Visibility = VIS_Editor; diff --git a/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/StringTblDE.txt b/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/StringTblDE.txt index b889168f3..94b7ab14f 100644 --- a/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/StringTblDE.txt +++ b/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/StringTblDE.txt @@ -1 +1,21 @@ Name=Wasserfall +Description=Spawns liquid pixels at a regular interval, place at a cliff to create a waterfall. The waterfall sound is played at the position of this object. + +EditorSourceStrength=Source strength +EditorSourceStrengthHelp=Amount of pixels the sources creates per 2 frames. +EditorSourceMaterial=Source material +EditorSourceMaterialHelp=The type of liquid to create. +EditorSourceMaterialWater=Water +EditorSourceMaterialAcid=Acid +EditorSourceMaterialLava=Lava +EditorSourceMaterialDuroLava=DuroLava +EditorSourceMaterialOil=Oil +EditorSourcePosition=Source position +EditorSourcePositionHelp=Set the position of the source. +EditorSourceDirection=Source direction +EditorSourceDirectionHelp=Set the direction of liquid insertion, relative to the source position. + +EditorDrainStrength=Drain strength +EditorDrainStrengthHelp=Amount of pixels the drain removes per 2 frames. +EditorDrainPosition=Drain position +EditorDrainPositionHelp=Set the position of the drain. \ No newline at end of file diff --git a/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/StringTblUS.txt b/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/StringTblUS.txt index 8a8423e80..ced439f21 100644 --- a/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/StringTblUS.txt +++ b/planet/Objects.ocd/Environment.ocd/Waterfall.ocd/StringTblUS.txt @@ -1 +1,21 @@ Name=Waterfall +Description=Spawns liquid pixels at a regular interval, place at a cliff to create a waterfall. The waterfall sound is played at the position of this object. + +EditorSourceStrength=Source strength +EditorSourceStrengthHelp=Amount of pixels the sources creates per 2 frames. +EditorSourceMaterial=Source material +EditorSourceMaterialHelp=The type of liquid to create. +EditorSourceMaterialWater=Water +EditorSourceMaterialAcid=Acid +EditorSourceMaterialLava=Lava +EditorSourceMaterialDuroLava=DuroLava +EditorSourceMaterialOil=Oil +EditorSourcePosition=Source position +EditorSourcePositionHelp=Set the position of the source. +EditorSourceDirection=Source direction +EditorSourceDirectionHelp=Set the direction of liquid insertion, relative to the source position. + +EditorDrainStrength=Drain strength +EditorDrainStrengthHelp=Amount of pixels the drain removes per 2 frames. +EditorDrainPosition=Drain position +EditorDrainPositionHelp=Set the position of the drain. \ No newline at end of file diff --git a/planet/Tutorials.ocf/Tutorial01.ocs/Script.c b/planet/Tutorials.ocf/Tutorial01.ocs/Script.c index ade7ffd58..8e52d4077 100644 --- a/planet/Tutorials.ocf/Tutorial01.ocs/Script.c +++ b/planet/Tutorials.ocf/Tutorial01.ocs/Script.c @@ -92,9 +92,9 @@ private func InitCaveEntrance() trunk.MeshTransformation = [-70, 0, 998, 0, 0, 1000, 0, 0, -998, 0, -70, 0]; var waterfall; waterfall = CreateWaterfall(325, 448, 2, "Water"); - waterfall->SetDirection(2, 0, 3, 6); + waterfall->SetDirection(3, 3, 1, 3); waterfall = CreateWaterfall(338, 450, 8, "Water"); - waterfall->SetDirection(1, 0, 4, 8); + waterfall->SetDirection(3, 4, 2, 4); CreateLiquidDrain(160, 648, 10); CreateLiquidDrain(184, 648, 10); CreateLiquidDrain(208, 648, 10); diff --git a/planet/Worlds.ocf/Chine.ocs/Script.c b/planet/Worlds.ocf/Chine.ocs/Script.c index 773c61510..42b66f91a 100644 --- a/planet/Worlds.ocf/Chine.ocs/Script.c +++ b/planet/Worlds.ocf/Chine.ocs/Script.c @@ -144,7 +144,7 @@ private func InitEnvironment(int map_size, int difficulty) for (var i = 0; i < 16 + 4 * difficulty; i++) { var fall = CreateWaterfall(waterfall_x + 2, 0, RandomX(3, 4), "Water"); - fall->SetDirection(RandomX(10, 12), 8, 8, 8); + fall->SetDirection(RandomX(14, 16), 12, 4, 4); fall->SetSoundLocation(LandscapeWidth() / 2, Random(LandscapeHeight())); } var trunk = CreateObjectAbove(Trunk, waterfall_x + 2, 20); diff --git a/planet/Worlds.ocf/RapidRefining.ocs/Script.c b/planet/Worlds.ocf/RapidRefining.ocs/Script.c index d1fa12ee2..30c3a5685 100644 --- a/planet/Worlds.ocf/RapidRefining.ocs/Script.c +++ b/planet/Worlds.ocf/RapidRefining.ocs/Script.c @@ -156,7 +156,7 @@ private func InitEnvironment(int difficulty) trunk->MakeInvincible(); var waterfall = CreateWaterfall(waterfall_x + 22, waterfall_y - 10, 10, "Water"); - waterfall->SetDirection(2, 0, 3, 6); + waterfall->SetDirection(3, 3, 2, 3); waterfall->SetSoundLocation(waterfall_x + 40, waterfall_y + 240); CreateLiquidDrain(8, 1040, 10);