openclonk/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/Script.c

331 lines
7.3 KiB
C
Raw Normal View History

2014-12-30 19:24:13 +00:00
/**
Steam Engine
Burns fuels like coal, wood and oil to produce power. The steam engine
produces 120 units of power independent of the fuel. However, the fuel
2014-12-30 19:24:13 +00:00
determines the amount of fuel and thereby the burn time.
@author Maikel (orignal script), Marky (fuel liquid)
2014-12-30 19:24:13 +00:00
*/
2009-12-29 13:44:16 +00:00
#include Library_Structure
#include Library_Ownable
#include Library_PowerProducer
#include Library_Flag
#include Library_LiquidContainer
#include Library_PipeControl
local DefaultFlagRadius = 200;
2009-12-29 13:44:16 +00:00
static const SteamEngine_produced_power = 120;
local fuel_amount;
// Possibly connected cable station
local cable_station;
public func Construction()
{
SetAction("Default");
return _inherited(...);
}
public func Initialize()
2014-12-30 19:24:13 +00:00
{
fuel_amount = 0;
AddTimer("ContentsCheck", 10);
2014-12-30 19:24:13 +00:00
return _inherited(...);
2009-12-29 13:44:16 +00:00
}
public func IsHammerBuildable() { return true; }
// This structure has a collection zone, which can not be flipped.
public func NoConstructionFlip() { return true; }
public func IsContainer() { return true; }
public func RejectCollect(id item, object obj)
{
2016-03-25 15:13:11 +00:00
// Accept fuel only
if (obj->~IsFuel())
return false;
2016-03-25 15:13:11 +00:00
// Is the object a container? If so, try to empty it.
if (obj->~IsContainer() || obj->~IsLiquidContainer())
{
GrabContents(obj);
2016-03-25 15:13:11 +00:00
}
return true;
}
public func Collection(object obj, bool put)
{
Sound("Objects::Clonk");
}
2014-12-30 19:24:13 +00:00
public func ContentsCheck()
2009-12-29 13:44:16 +00:00
{
2014-12-30 19:24:13 +00:00
// Ejects non fuel items immediately
var fuel = FindObject(Find_Container(this), Find_Not(Find_Func("IsFuel")));
if (fuel)
{
fuel->Exit(-45, 21, -20, -1, -1, -30);
2014-12-30 19:24:13 +00:00
Sound("Chuff");
}
2014-12-30 19:24:13 +00:00
// If active don't do anything.
if (IsWorking())
2014-12-30 19:24:13 +00:00
return;
// If there is fuel available let the network know.
if (GetFuelAmount() > 0 || GetFuelContents())
2014-12-30 19:24:13 +00:00
RegisterPowerProduction(SteamEngine_produced_power);
return;
}
2015-03-09 17:55:18 +00:00
public func GetFuelAmount()
{
return fuel_amount;
2015-03-09 17:55:18 +00:00
}
2014-12-30 19:24:13 +00:00
/*-- Power Production --*/
// Produces power on demand, so not steady.
public func IsSteadyPowerProducer() { return false; }
// Low priority so that other sources of power are drained before burning fuel.
public func GetProducerPriority() { return 0; }
// Callback from the power library for production of power request.
public func OnPowerProductionStart(int amount)
{
// Check if there is fuel.
RefillFuel();
2014-12-30 19:24:13 +00:00
// There is enough fuel so start producing power and notify network of this.
if (GetAction() == "Default")
2014-12-30 19:24:13 +00:00
SetAction("Work");
return true;
2009-12-29 13:44:16 +00:00
}
2014-12-30 19:24:13 +00:00
// Callback from the power library requesting to stop power production.
2015-02-03 11:05:47 +00:00
public func OnPowerProductionStop(int amount)
2014-12-30 19:24:13 +00:00
{
// Set action to idle when it was working.
if (IsWorking())
SetAction("Default");
2014-12-30 19:24:13 +00:00
return true;
2009-12-29 13:44:16 +00:00
}
2014-12-30 19:24:13 +00:00
// Start call from working action.
public func WorkStart()
{
Sound("Structures::SteamEngine", {loop_count = 1});
2014-12-30 19:24:13 +00:00
return;
}
// Status?
public func IsWorking(){ return GetAction() == "Work";}
2014-12-30 19:24:13 +00:00
// Phase call from working action, every two frames.
public func Working()
{
DoFuelAmount(-2); // Reduce the fuel amount by 1 per frame
RefillFuel(); // Check if there is still enough fuel available.
if (!GetFuelAmount())
{
// Set action to idle and unregister this producer as available from the network.
SetAction("Default");
UnregisterPowerProduction();
}
// Request fuel from cable car network if there is not fuel object available.
if (!GetFuelContents())
RequestFuel();
Smoking(); // Smoke from the exhaust shaft.
2014-12-30 19:24:13 +00:00
return;
}
2014-12-30 19:24:13 +00:00
// Stop call from working action.
public func WorkStop()
{
2014-12-30 19:24:13 +00:00
// Don't kill the sound in this call, since that would interupt the sound effect.
return;
}
2014-12-30 19:24:13 +00:00
// Abort call from working action.
public func WorkAbort()
{
2014-12-30 19:24:13 +00:00
// Sound can be safely stopped here since this action will always end with an abort call.
Sound("Structures::SteamEngine", {loop_count = -1});
2014-12-30 19:24:13 +00:00
return;
}
public func RefillFuel()
{
// Check if there is still enough fuel available.
var no_fuel = GetFuelAmount() <= 0;
2016-02-27 13:43:24 +00:00
// The reserve is probably not necessary
var should_keep_reserve = IsWorking() && GetNeutralPipe() && GetFuelAmount() < 100;
if (no_fuel || should_keep_reserve)
{
var fuel_extracted;
// Search for new fuel among the contents.
var fuel = GetFuelContents();
if (fuel)
{
fuel_extracted = fuel->~GetFuelAmount();
if (!fuel->~OnFuelRemoved(fuel_extracted))
fuel->RemoveObject();
2016-03-01 18:54:55 +00:00
DoFuelAmount(fuel_extracted * 18);
}
}
}
public func GetFuelContents()
{
return FindObject(Find_Container(this), Find_Func("IsFuel"));
}
public func DoFuelAmount(int amount)
{
fuel_amount += amount;
}
public func Smoking()
{
// Smoke from the exhaust shaft
Smoke(-20 * GetCalcDir() + RandomX(-2, 2), -26, 10);
Smoke(-20 * GetCalcDir() + RandomX(-2, 2), -24, 8);
Smoke(-20 * GetCalcDir() + RandomX(-2, 2), -24, 10);
}
2014-12-30 19:24:13 +00:00
public func IsLiquidContainerForMaterial(string liquid)
{
return WildcardMatch("Oil", liquid);
}
public func GetLiquidContainerMaxFillLevel(liquid_name)
{
return 300;
}
// The foundry may have one drain and one source.
public func QueryConnectPipe(object pipe, bool do_msg)
{
if (GetDrainPipe() && GetSourcePipe())
{
if (do_msg) pipe->Report("$MsgHasPipes$");
return true;
}
else if (GetSourcePipe() && pipe->IsSourcePipe())
{
if (do_msg) pipe->Report("$MsgSourcePipeProhibited$");
return true;
}
else if (GetDrainPipe() && pipe->IsDrainPipe())
{
if (do_msg) pipe->Report("$MsgDrainPipeProhibited$");
return true;
}
else if (pipe->IsAirPipe())
{
if (do_msg) pipe->Report("$MsgPipeProhibited$");
return true;
}
return false;
}
// Set to source or drain pipe.
public func OnPipeConnect(object pipe, string specific_pipe_state)
{
if (PIPE_STATE_Source == specific_pipe_state)
{
SetSourcePipe(pipe);
pipe->SetSourcePipe();
}
else if (PIPE_STATE_Drain == specific_pipe_state)
{
SetDrainPipe(pipe);
pipe->SetDrainPipe();
}
else
{
if (!GetDrainPipe())
OnPipeConnect(pipe, PIPE_STATE_Drain);
else if (!GetSourcePipe())
OnPipeConnect(pipe, PIPE_STATE_Source);
}
pipe->Report("$MsgConnectedPipe$");
}
/*-- Cable Network --*/
public func AcceptsCableStationConnection() { return true; }
public func IsNoCableStationConnected() { return !cable_station; }
public func ConnectCableStation(object station)
{
cable_station = station;
}
public func RequestFuel()
{
// For now just request coal as it is the safest type of fuel, that is least needed by other structures.
if (cable_station)
cable_station->AddRequest({type = Coal, min_amount = 1, max_amount = 5});
return;
}
2014-12-30 19:24:13 +00:00
/*-- Properties --*/
local ActMap = {
Default = {
Prototype = Action,
Name = "Default",
Procedure = DFA_NONE,
Directions = 2,
FlipDir = 1,
Length = 1,
Delay = 0,
2014-12-30 19:24:13 +00:00
FacetBase = 1,
NextAction = "Default",
},
Work = {
Prototype = Action,
Name = "Work",
Procedure = DFA_NONE,
Directions = 2,
FlipDir = 1,
Length = 20,
Delay = 2,
FacetBase = 1,
NextAction = "Work",
Animation = "Work",
2014-12-30 19:24:13 +00:00
PhaseCall = "Working",
StartCall = "WorkStart",
EndCall = "WorkStop",
AbortCall = "WorkAbort",
},
};
2014-12-30 19:24:13 +00:00
protected func Definition(def)
{
SetProperty("MeshTransformation", Trans_Mul(Trans_Rotate(25, 0, 1, 0), Trans_Scale(625)), def);
SetProperty("PictureTransformation", Trans_Mul(Trans_Translate(-4000, -18000, 60000), Trans_Rotate(25, 0, 1, 0), Trans_Scale(625)), def);
return _inherited(def, ...);
2012-04-15 11:13:14 +00:00
}
2014-12-30 19:24:13 +00:00
local ContainBlast = true;
local BlastIncinerate = 130;
local HitPoints = 100;
local FireproofContainer = true;
2012-04-15 11:13:14 +00:00
local Name = "$Name$";
local Description = "$Description$";
local Components = {Rock = 6, Metal = 3};