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

238 lines
5.3 KiB
C

/**
Foundry
Melts iron ore to metal, using some sort of fuel.
@authors Ringwaul, Maikel
*/
#include Library_Structure
#include Library_Ownable
#include Library_Producer
#include Library_LampPost
#include Library_LiquidContainer
#include Library_PipeControl
// Foundry does not need power.
public func PowerNeed() { return 0; }
public func IsPowerConsumer() { return false; }
public func LampPosition(id def) { return [-11 * GetCalcDir(), 2]; }
public func Construction(object creator)
{
AddTimer("CollectionZone", 1);
SetAction("Default");
return _inherited(creator, ...);
}
public func IsHammerBuildable() { return true; }
public func Initialize()
{
// Update vertices to fit shape of flipped building after construction is finished.
// Vertices are being reset when the construction is finished (i.e. on shape updates).
if (GetDir() == DIR_Right)
FlipVertices();
return _inherited(...);
}
public func SetDir(int dir)
{
// Update vertices to fit shape of flipped building when dir is changed.
if (GetDir() != dir)
FlipVertices();
return _inherited(dir, ...);
}
/*-- Production --*/
private func IgnoreKnowledge() { return true; }
private func IsProduct(id product_id)
{
return product_id->~IsFoundryProduct();
}
private func ProductionTime(id product) { return _inherited(product, ...) ?? 290; }
public func OnProductionStart(id product)
{
AddEffect("Smelting", this, 100, 1, this);
Sound("Structures::Furnace::Start");
return;
}
public func OnProductionHold(id product)
{
return;
}
public func OnProductionFinish(id product)
{
RemoveEffect("Smelting", this);
return;
}
// Timer, check for objects to collect in the designated collection zone
public func CollectionZone()
{
if (GetCon() < 100)
return;
for (var obj in FindObjects(Find_InRect(16 - 45 * GetDir(), 3, 13, 13), Find_OCF(OCF_Collectible), Find_NoContainer(), Find_Layer(GetObjectLayer())))
Collect(obj, true);
}
public func Collection()
{
Sound("Objects::Clonk");
return _inherited(...);
}
public func FxSmeltingTimer(object target, proplist effect, int time)
{
// Fire in the furnace.
CreateParticle("Fire", -10 * GetCalcDir() + RandomX(-1, 1), 20 + RandomX(-1, 1), PV_Random(-1, 1), PV_Random(-1, 1), PV_Random(3, 10), Particles_Fire(), 2);
// Smoke from the pipes.
Smoke( -10*GetCalcDir(), -26, 6);
Smoke(-16*GetCalcDir(), -22, 3);
// Furnace sound after some time.
if (time == 30)
Sound("Structures::Furnace::Loop", false, 100, nil, +1);
// Pour after some time.
if (time == 244)
SetMeshMaterial("MetalFlow", 1);
// Molten metal hits cast... Sizzling sound.
if (time == 256)
Sound("Liquids::Sizzle");
// Fire from the pouring exit.
if (Inside(time, 244, 290))
CreateParticle("SphereSpark", 16 * GetCalcDir(), 20, PV_Random(2 * GetCalcDir(), 0), PV_Random(-2, 3), PV_Random(18, 36), Particles_Material(RGB(255, 200, 0)), 2);
if (time == 290)
{
SetMeshMaterial("Metal", 1);
Sound("Structures::Furnace::Loop", false, 100, nil, -1);
Sound("Structures::Furnace::Stop");
return FX_Execute_Kill;
}
return FX_OK;
}
public func OnProductEjection(object product)
{
// Enter produced liquids.
if (product->~IsLiquid())
{
product->Enter(this);
return;
}
// Other products exit the foundry.
product->SetPosition(GetX() + 18 * GetCalcDir(), GetY() + 16);
product->SetSpeed(0, -17);
product->SetR(30 - Random(59));
Sound("Structures::EjectionPop");
return;
}
/*-- Pipeline --*/
public func IsLiquidContainerForMaterial(string liquid)
{
return WildcardMatch("Oil", liquid) || WildcardMatch("Water", liquid) || WildcardMatch("Concrete", liquid);
}
public func GetLiquidContainerMaxFillLevel(liquid_name)
{
if (GetLiquidDef(liquid_name) == Water)
return 600;
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$");
}
/*-- Properties --*/
public func Definition(proplist def)
{
def.PictureTransformation = Trans_Mul(Trans_Translate(2000, 0, 7000), Trans_Rotate(-20, 1, 0, 0), Trans_Rotate(30, 0, 1, 0));
return _inherited(def, ...);
}
local ActMap = {
Default = {
Prototype = Action,
Name = "Default",
Procedure = DFA_NONE,
Directions = 2,
FlipDir = 1,
Length = 1,
Delay = 0,
FacetBase = 1,
NextAction = "Default",
},
};
local Name = "$Name$";
local Description = "$Description$";
local ContainBlast = true;
local BlastIncinerate = 100;
local HitPoints = 100;
local FireproofContainer = true;
local Components = {Rock = 4, Wood = 2};