forked from Mirrors/openclonk
447 lines
12 KiB
C
447 lines
12 KiB
C
/**
|
|
Liquid System
|
|
Unit tests for the liquid system. Invokes tests by calling the
|
|
global function Test*_OnStart(int plr) and iterate through all
|
|
tests. The test is completed once Test*_Completed() returns
|
|
true. Then Test*_OnFinished() is called, to be able to reset
|
|
the scenario for the next test.
|
|
|
|
With LaunchTest(int nr) a specific test can be launched when
|
|
called during runtime. A test can be skipped by calling the
|
|
function SkipTest().
|
|
|
|
@author Maikel
|
|
*/
|
|
|
|
|
|
static script_plr;
|
|
|
|
protected func Initialize()
|
|
{
|
|
// Add the no power rule, this is about liquids.
|
|
CreateObject(Rule_NoPowerNeed);
|
|
// Create a script player for some tests.
|
|
script_plr = nil;
|
|
CreateScriptPlayer("Buddy", RGB(0, 0, 255), nil, CSPF_NoEliminationCheck);
|
|
return;
|
|
}
|
|
|
|
protected func InitializePlayer(int plr)
|
|
{
|
|
// Set zoom to full map size.
|
|
SetPlayerZoomByViewRange(plr, LandscapeWidth(), nil, PLRZOOM_Direct);
|
|
|
|
// No FoW to see everything happening.
|
|
SetFoW(false, plr);
|
|
|
|
// All players belong to the first team.
|
|
// The second team only exists for testing.
|
|
SetPlayerTeam(plr, 1);
|
|
|
|
// Initialize script player.
|
|
if (GetPlayerType(plr) == C4PT_Script)
|
|
{
|
|
// Store the player number.
|
|
if (script_plr == nil)
|
|
script_plr = plr;
|
|
// No crew needed.
|
|
GetCrew(plr)->RemoveObject();
|
|
return;
|
|
}
|
|
|
|
// Move player to the start of the scenario.
|
|
GetCrew(plr)->SetPosition(120, 150);
|
|
|
|
// Some knowledge to construct a flagpole.
|
|
GetCrew(plr)->CreateContents(Hammer);
|
|
SetPlrKnowledge(plr, Flagpole);
|
|
|
|
// Add test control effect.
|
|
var effect = AddEffect("IntTestControl", nil, 100, 2);
|
|
effect.testnr = 1;
|
|
effect.launched = false;
|
|
effect.plr = plr;
|
|
return;
|
|
}
|
|
|
|
protected func RemovePlayer(int plr)
|
|
{
|
|
// Remove script player.
|
|
if (GetPlayerType(plr) == C4PT_Script)
|
|
{
|
|
if (plr == script_plr)
|
|
script_plr = nil;
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/*-- Test Control --*/
|
|
|
|
// Aborts the current test and launches the specified test instead.
|
|
global func LaunchTest(int nr)
|
|
{
|
|
// Get the control effect.
|
|
var effect = GetEffect("IntTestControl", nil);
|
|
if (!effect)
|
|
{
|
|
// Create a new control effect and launch the test.
|
|
effect = AddEffect("IntTestControl", nil, 100, 2);
|
|
effect.testnr = nr;
|
|
effect.launched = false;
|
|
effect.plr = GetPlayerByIndex(0, C4PT_User);
|
|
return;
|
|
}
|
|
// Finish the currently running test.
|
|
Call(Format("~Test%d_OnFinished", effect.testnr));
|
|
// Start the requested test by just setting the test number and setting
|
|
// effect.launched to false, effect will handle the rest.
|
|
effect.testnr = nr;
|
|
effect.launched = false;
|
|
return;
|
|
}
|
|
|
|
// Calling this function skips the current test, does not work if last test has been ran already.
|
|
global func SkipTest()
|
|
{
|
|
// Get the control effect.
|
|
var effect = GetEffect("IntTestControl", nil);
|
|
if (!effect)
|
|
return;
|
|
// Finish the previous test.
|
|
Call(Format("~Test%d_OnFinished", effect.testnr));
|
|
// Start the next test by just increasing the test number and setting
|
|
// effect.launched to false, effect will handle the rest.
|
|
effect.testnr++;
|
|
effect.launched = false;
|
|
return;
|
|
}
|
|
|
|
|
|
/*-- Test Effect --*/
|
|
|
|
global func FxIntTestControlStart(object target, proplist effect, int temporary)
|
|
{
|
|
if (temporary)
|
|
return FX_OK;
|
|
// Set default interval.
|
|
effect.Interval = 2;
|
|
return FX_OK;
|
|
}
|
|
|
|
global func FxIntTestControlTimer(object target, proplist effect)
|
|
{
|
|
// Launch new test if needed.
|
|
if (!effect.launched)
|
|
{
|
|
// Log test start.
|
|
Log("=====================================");
|
|
Log("Test %d started:", effect.testnr);
|
|
// Start the test if available, otherwise finish test sequence.
|
|
if (!Call(Format("~Test%d_OnStart", effect.testnr), effect.plr))
|
|
{
|
|
Log("Test %d not available, the previous test was the last test.", effect.testnr);
|
|
Log("=====================================");
|
|
Log("All tests have been successfully completed!");
|
|
return FX_Execute_Kill;
|
|
}
|
|
effect.launched = true;
|
|
}
|
|
// Check whether the current test has been finished.
|
|
if (Call(Format("Test%d_Completed", effect.testnr)))
|
|
{
|
|
effect.launched = false;
|
|
//RemoveTest();
|
|
// Call the test on finished function.
|
|
Call(Format("~Test%d_OnFinished", effect.testnr));
|
|
// Log result and increase test number.
|
|
Log("Test %d successfully completed.", effect.testnr);
|
|
effect.testnr++;
|
|
}
|
|
return FX_OK;
|
|
}
|
|
|
|
|
|
/*-- Liquid Tests --*/
|
|
|
|
global func Test1_OnStart(int plr)
|
|
{
|
|
var foundry = CreateObjectAbove(Foundry, 110, 160, plr);
|
|
foundry->CreateContents(Earth, 10);
|
|
foundry->AddToQueue(Loam, 2);
|
|
|
|
var pump = CreateObjectAbove(Pump, 84, 160, plr);
|
|
var source = CreateObjectAbove(Pipe, 168, 292, plr);
|
|
source->ConnectPipeTo(pump, PIPE_STATE_Source);
|
|
var drain = CreateObjectAbove(Pipe, 240, 100, plr);
|
|
drain->ConnectPipeTo(pump, PIPE_STATE_Drain);
|
|
drain->ConnectPipeTo(foundry, PIPE_STATE_Drain);
|
|
|
|
// Log what the test is about.
|
|
Log("Water supply to foundry.");
|
|
return true;
|
|
}
|
|
|
|
global func Test1_Completed()
|
|
{
|
|
if (ObjectCount(Find_ID(Loam)) >= 2)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
global func Test1_OnFinished()
|
|
{
|
|
RemoveAll(Find_Or(Find_ID(Foundry), Find_ID(Pump), Find_ID(Loam)));
|
|
RestoreWaterLevels();
|
|
return;
|
|
}
|
|
|
|
|
|
global func Test2_OnStart(int plr)
|
|
{
|
|
var foundry = CreateObjectAbove(Foundry, 110, 160, plr);
|
|
foundry->CreateContents(Rock, 60);
|
|
foundry->AddToQueue(Concrete, nil, true);
|
|
|
|
var pump = CreateObjectAbove(Pump, 84, 160, plr);
|
|
var source = CreateObjectAbove(Pipe, 168, 292, plr);
|
|
source->ConnectPipeTo(pump, PIPE_STATE_Source);
|
|
var drain = CreateObjectAbove(Pipe, 240, 100, plr);
|
|
drain->ConnectPipeTo(pump, PIPE_STATE_Drain);
|
|
drain->ConnectPipeTo(foundry, PIPE_STATE_Drain);
|
|
|
|
var pump = CreateObjectAbove(Pump, 240, 160, plr);
|
|
pump->SetResourceSelection([Concrete]);
|
|
var source = CreateObjectAbove(Pipe, 168, 292, plr);
|
|
source->ConnectPipeTo(pump, PIPE_STATE_Source);
|
|
source->ConnectPipeTo(foundry, PIPE_STATE_Source);
|
|
var drain = CreateObjectAbove(Pipe, 240, 100, plr);
|
|
drain->ConnectPipeTo(pump, PIPE_STATE_Drain);
|
|
|
|
// Log what the test is about.
|
|
Log("Water supply to foundry and concrete supply from foundry.");
|
|
return true;
|
|
}
|
|
|
|
global func Test2_Completed()
|
|
{
|
|
if (GetMaterial(240, 60) == Material("Granite"))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
global func Test2_OnFinished()
|
|
{
|
|
RemoveAll(Find_Or(Find_ID(Foundry), Find_ID(Pump), Find_ID(Pipe)));
|
|
RestoreWaterLevels();
|
|
return;
|
|
}
|
|
|
|
|
|
global func Test3_OnStart(int plr)
|
|
{
|
|
DrawMaterialQuad("Oil", 144, 168, 208 + 1, 168, 208 + 1, 304, 144, 304, true);
|
|
|
|
var engine1 = CreateObjectAbove(SteamEngine, 70, 160, plr);
|
|
var engine2 = CreateObjectAbove(SteamEngine, 240, 160, plr);
|
|
var pump1 = CreateObjectAbove(Pump, 16, 160, plr);
|
|
var pump2 = CreateObjectAbove(Pump, 124, 160, plr);
|
|
|
|
var source = CreateObjectAbove(Pipe, 168, 292, plr);
|
|
source->ConnectPipeTo(pump1, PIPE_STATE_Source);
|
|
var drain = CreateObjectAbove(Pipe, 240, 100, plr);
|
|
drain->ConnectPipeTo(pump1, PIPE_STATE_Drain);
|
|
drain->ConnectPipeTo(engine1, PIPE_STATE_Drain);
|
|
|
|
var source = CreateObjectAbove(Pipe, 168, 292, plr);
|
|
source->ConnectPipeTo(pump2, PIPE_STATE_Source);
|
|
source->ConnectPipeTo(engine1, PIPE_STATE_Source);
|
|
var drain = CreateObjectAbove(Pipe, 240, 100, plr);
|
|
drain->ConnectPipeTo(pump2, PIPE_STATE_Drain);
|
|
drain->ConnectPipeTo(engine2, PIPE_STATE_Drain);
|
|
|
|
// Log what the test is about.
|
|
Log("Supply two steam engines with oil in a chain.");
|
|
return true;
|
|
}
|
|
|
|
global func Test3_Completed()
|
|
{
|
|
for (var engine in FindObjects(Find_ID(SteamEngine)))
|
|
if (engine->GetLiquidAmount("Oil") < 300)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
global func Test3_OnFinished()
|
|
{
|
|
RemoveAll(Find_Or(Find_ID(SteamEngine), Find_ID(Pump), Find_ID(Pipe)));
|
|
RestoreWaterLevels();
|
|
return;
|
|
}
|
|
|
|
global func Test4_OnStart(int plr)
|
|
{
|
|
DrawMatBasin("DuroLava", 20, 120);
|
|
|
|
var foundry = CreateObjectAbove(Foundry, 110, 160, plr);
|
|
foundry->CreateContents(Earth, 10);
|
|
foundry->AddToQueue(Loam, 5);
|
|
|
|
var pump = CreateObjectAbove(Pump, 84, 160, plr);
|
|
var source = CreateObject(Pipe, 168, 292, plr);
|
|
source->ConnectPipeTo(pump, PIPE_STATE_Source);
|
|
var drain = CreateObjectAbove(Pipe, 240, 100, plr);
|
|
drain->ConnectPipeTo(pump, PIPE_STATE_Drain);
|
|
drain->ConnectPipeTo(foundry, PIPE_STATE_Drain);
|
|
|
|
ScheduleCall(source, "SetPosition", 100, 0, 20, 120);
|
|
ScheduleCall(foundry, "DoCutPipe", 200, 0, drain);
|
|
|
|
// Log what the test is about.
|
|
Log("Test air switching pumping materials after connection changes.");
|
|
return true;
|
|
}
|
|
|
|
global func Test4_Completed()
|
|
{
|
|
// The test fails if lava is left in the new source rectangle,
|
|
// or if production can be completed (the foundry can produce
|
|
// only 2 loam instead of 5 if the connection changes)
|
|
var could_pump_lava = GetMaterial(20, 125) == Material("Sky");
|
|
var cannot_finish_production = ObjectCount(Find_ID(Loam)) <= 2;
|
|
var producing = FindObject(Find_ID(Foundry))->IsProducing();
|
|
return !producing && could_pump_lava && cannot_finish_production;
|
|
}
|
|
|
|
global func Test4_OnFinished()
|
|
{
|
|
RemoveAll(Find_Or(Find_ID(Foundry), Find_ID(Pump), Find_ID(Loam)));
|
|
RestoreWaterLevels();
|
|
return;
|
|
}
|
|
|
|
|
|
global func Test5_OnStart(int plr)
|
|
{
|
|
RemoveAll(Find_ID(Rule_NoPowerNeed));
|
|
|
|
var engine = CreateObjectAbove(SteamEngine, 40, 160, plr);
|
|
engine->CreateContents(Coal, 10);
|
|
|
|
var pump = CreateObjectAbove(Pump, 84, 160, plr);
|
|
var helmet = GetHiRank(plr)->CreateContents(DivingHelmet);
|
|
var drain = CreateObjectAbove(Pipe, 240, 100, plr);
|
|
drain->ConnectPipeTo(helmet);
|
|
drain->ConnectPipeTo(pump, drain->GetPipeState());
|
|
|
|
// Move player character over the basin
|
|
GetHiRank()->SetPosition(175, 150);
|
|
GetHiRank()->SetComDir(COMD_Down);
|
|
helmet->ControlUse(GetHiRank(plr));
|
|
|
|
// Log what the test is about.
|
|
Log("Test air supply to diving helmet - dive down towards the ground");
|
|
return true;
|
|
}
|
|
|
|
global func Test5_Completed()
|
|
{
|
|
var is_down = GetHiRank()->GetY() > 280;
|
|
if (is_down)
|
|
{
|
|
GetHiRank()->SetComDir(COMD_Up);
|
|
var breath_before = GetHiRank()->GetBreath();
|
|
GetHiRank()->DoBreath(1000);
|
|
var breath_used = GetHiRank().MaxBreath - breath_before;
|
|
|
|
var pump = FindObject(Find_ID(Pump));
|
|
var is_pumping = pump->GetAction() == "Pump";
|
|
var has_air_pipe = pump->IsAirPipeConnected();
|
|
Log("The clonk used %d air, pump is pumping %v, has air pipe %v", breath_used, is_pumping, has_air_pipe);
|
|
if (breath_used <= 70 && is_pumping && has_air_pipe)
|
|
{
|
|
return true;
|
|
}
|
|
Log("There was no air supply to the diving helmet - skipping the failed test");
|
|
SkipTest();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
global func Test5_OnFinished()
|
|
{
|
|
RemoveAll(Find_Or(Find_ID(DivingHelmet), Find_ID(Pump), Find_ID(Pipe), Find_ID(SteamEngine)));
|
|
RestoreWaterLevels();
|
|
CreateObject(Rule_NoPowerNeed);
|
|
return;
|
|
}
|
|
|
|
global func Test6_OnStart(int plr)
|
|
{
|
|
var tank = CreateObjectAbove(LiquidTank, 70, 160, plr);
|
|
var pump1 = CreateObjectAbove(Pump, 16, 160, plr);
|
|
var pump2 = CreateObjectAbove(Pump, 124, 160, plr);
|
|
|
|
var source = CreateObjectAbove(Pipe, 168, 292, plr);
|
|
source->ConnectPipeTo(pump1, PIPE_STATE_Source);
|
|
var drain = CreateObjectAbove(Pipe, 240, 100, plr);
|
|
drain->ConnectPipeTo(pump1, PIPE_STATE_Drain);
|
|
drain->ConnectPipeTo(tank, PIPE_STATE_Drain);
|
|
|
|
var source = CreateObjectAbove(Pipe, 168, 292, plr);
|
|
source->ConnectPipeTo(pump2, PIPE_STATE_Source);
|
|
source->ConnectPipeTo(tank, PIPE_STATE_Source);
|
|
var drain = CreateObjectAbove(Pipe, 240, 100, plr);
|
|
drain->ConnectPipeTo(pump2, PIPE_STATE_Drain);
|
|
|
|
// Log what the test is about.
|
|
Log("Test pumping into and from a liquid tank");
|
|
return true;
|
|
}
|
|
|
|
global func Test6_Completed()
|
|
{
|
|
if (GetMaterial(240, 60) == Material("Water"))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
global func Test6_OnFinished()
|
|
{
|
|
RemoveAll(Find_Or(Find_ID(LiquidTank), Find_ID(Pump), Find_ID(Pipe)));
|
|
RestoreWaterLevels();
|
|
return;
|
|
}
|
|
|
|
|
|
/*-- Helper Functions --*/
|
|
|
|
global func RestoreWaterLevels()
|
|
{
|
|
// Restore water levels.
|
|
DrawMaterialQuad("Water", 144, 168, 208 + 1, 168, 208 + 1, 304, 144, 304, true);
|
|
for (var x = 216; x <= 280; x++)
|
|
for (var y = 24; y <= 120; y++)
|
|
if (GetMaterial(x, y) != Material("BrickSoft"))
|
|
ClearFreeRect(x, y, 1, 1);
|
|
return;
|
|
}
|
|
|
|
global func DrawMatBasin(string mat, int x, int y)
|
|
{
|
|
DrawMaterialQuad("Brick", x - 10, y - 10, x - 10, y + 10, x + 10, y + 10, x + 10, y - 10);
|
|
DrawMaterialQuad(mat, x - 6, y - 6, x - 6, y + 6, x + 6, y + 6, x + 6, y - 6);
|
|
return;
|
|
}
|
|
|
|
global func RemoveWater()
|
|
{
|
|
for (var x = 144; x <= 208 + 1; x++)
|
|
for (var y = 168; y <= 304; y++)
|
|
if (GetMaterial(x, y) != Material("BrickSoft"))
|
|
ClearFreeRect(x, y, 1, 1);
|
|
return;
|
|
}
|