forked from Mirrors/openclonk
331 lines
7.3 KiB
C
331 lines
7.3 KiB
C
/**
|
|
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
|
|
determines the amount of fuel and thereby the burn time.
|
|
|
|
@author Maikel (orignal script), Marky (fuel liquid)
|
|
*/
|
|
|
|
#include Library_Structure
|
|
#include Library_Ownable
|
|
#include Library_PowerProducer
|
|
#include Library_Flag
|
|
#include Library_LiquidContainer
|
|
#include Library_PipeControl
|
|
|
|
local DefaultFlagRadius = 200;
|
|
|
|
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()
|
|
{
|
|
fuel_amount = 0;
|
|
AddTimer("ContentsCheck", 10);
|
|
return _inherited(...);
|
|
}
|
|
|
|
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)
|
|
{
|
|
// Accept fuel only
|
|
if (obj->~IsFuel())
|
|
return false;
|
|
|
|
// Is the object a container? If so, try to empty it.
|
|
if (obj->~IsContainer() || obj->~IsLiquidContainer())
|
|
{
|
|
GrabContents(obj);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public func Collection(object obj, bool put)
|
|
{
|
|
Sound("Objects::Clonk");
|
|
}
|
|
|
|
public func ContentsCheck()
|
|
{
|
|
// 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);
|
|
Sound("Chuff");
|
|
}
|
|
|
|
// If active don't do anything.
|
|
if (IsWorking())
|
|
return;
|
|
|
|
// If there is fuel available let the network know.
|
|
if (GetFuelAmount() > 0 || GetFuelContents())
|
|
RegisterPowerProduction(SteamEngine_produced_power);
|
|
return;
|
|
}
|
|
|
|
|
|
public func GetFuelAmount()
|
|
{
|
|
return fuel_amount;
|
|
}
|
|
|
|
|
|
/*-- 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();
|
|
// There is enough fuel so start producing power and notify network of this.
|
|
if (GetAction() == "Default")
|
|
SetAction("Work");
|
|
return true;
|
|
}
|
|
|
|
// Callback from the power library requesting to stop power production.
|
|
public func OnPowerProductionStop(int amount)
|
|
{
|
|
// Set action to idle when it was working.
|
|
if (IsWorking())
|
|
SetAction("Default");
|
|
return true;
|
|
}
|
|
|
|
// Start call from working action.
|
|
public func WorkStart()
|
|
{
|
|
Sound("Structures::SteamEngine", {loop_count = 1});
|
|
return;
|
|
}
|
|
|
|
// Status?
|
|
public func IsWorking(){ return GetAction() == "Work";}
|
|
|
|
// 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.
|
|
return;
|
|
}
|
|
|
|
// Stop call from working action.
|
|
public func WorkStop()
|
|
{
|
|
// Don't kill the sound in this call, since that would interupt the sound effect.
|
|
return;
|
|
}
|
|
|
|
// Abort call from working action.
|
|
public func WorkAbort()
|
|
{
|
|
// Sound can be safely stopped here since this action will always end with an abort call.
|
|
Sound("Structures::SteamEngine", {loop_count = -1});
|
|
return;
|
|
}
|
|
|
|
public func RefillFuel()
|
|
{
|
|
// Check if there is still enough fuel available.
|
|
var no_fuel = GetFuelAmount() <= 0;
|
|
// 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();
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
/*-- Properties --*/
|
|
|
|
local ActMap = {
|
|
Default = {
|
|
Prototype = Action,
|
|
Name = "Default",
|
|
Procedure = DFA_NONE,
|
|
Directions = 2,
|
|
FlipDir = 1,
|
|
Length = 1,
|
|
Delay = 0,
|
|
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",
|
|
PhaseCall = "Working",
|
|
StartCall = "WorkStart",
|
|
EndCall = "WorkStop",
|
|
AbortCall = "WorkAbort",
|
|
},
|
|
};
|
|
|
|
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, ...);
|
|
}
|
|
|
|
local ContainBlast = true;
|
|
local BlastIncinerate = 130;
|
|
local HitPoints = 100;
|
|
local FireproofContainer = true;
|
|
local Name = "$Name$";
|
|
local Description = "$Description$";
|
|
local Components = {Rock = 6, Metal = 3}; |