2010-12-31 12:20:54 +00:00
|
|
|
/*--
|
|
|
|
Pump
|
2013-04-28 11:57:25 +00:00
|
|
|
Author: Maikel, ST-DDT, Sven2
|
2010-12-31 12:20:54 +00:00
|
|
|
|
|
|
|
Pumps liquids using drain and source pipes.
|
|
|
|
--*/
|
|
|
|
|
2012-05-10 19:20:06 +00:00
|
|
|
#include Library_Structure
|
2012-02-18 21:50:18 +00:00
|
|
|
#include Library_Ownable
|
2010-12-31 12:20:54 +00:00
|
|
|
#include Library_PowerConsumer
|
2013-04-28 11:57:25 +00:00
|
|
|
#include Library_PowerProducer
|
2010-12-31 12:20:54 +00:00
|
|
|
|
2013-04-28 11:57:25 +00:00
|
|
|
local current_pump_power; // Current power needed for pumping. Negative if power is being produced.
|
2010-12-31 12:20:54 +00:00
|
|
|
|
|
|
|
// This object is a liquid pump, thus pipes can be connected.
|
|
|
|
public func IsLiquidPump() { return true; }
|
|
|
|
|
2012-04-16 15:31:38 +00:00
|
|
|
public func Construction(object creator)
|
2010-12-31 12:20:54 +00:00
|
|
|
{
|
2012-04-16 15:31:38 +00:00
|
|
|
return _inherited(creator, ...);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected func Initialize()
|
|
|
|
{
|
2012-03-10 19:45:18 +00:00
|
|
|
turned_on = true;
|
2012-10-25 18:14:13 +00:00
|
|
|
SetAction("Wait");
|
|
|
|
CheckCurrentState();
|
2010-12-31 12:20:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-10 19:45:18 +00:00
|
|
|
/*-- Interaction --*/
|
|
|
|
|
|
|
|
local turned_on;
|
|
|
|
|
|
|
|
public func IsInteractable() { return GetCon() >= 100; }
|
|
|
|
|
|
|
|
public func GetInteractionMetaInfo(object clonk)
|
|
|
|
{
|
|
|
|
if (turned_on)
|
2013-05-23 15:50:15 +00:00
|
|
|
return { Description = "$MsgTurnOff$", IconName = nil, IconID = Icon_Stop };
|
|
|
|
return { Description = "$MsgTurnOn$", IconName = nil, IconID = Icon_Play };
|
2012-03-10 19:45:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// On interaction the pump can be turned on or off.
|
|
|
|
public func Interact(object clonk)
|
|
|
|
{
|
2012-10-25 18:14:13 +00:00
|
|
|
turned_on = !turned_on;
|
|
|
|
CheckCurrentState();
|
2012-03-10 19:45:18 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-12-31 12:20:54 +00:00
|
|
|
/*-- Pipe connection --*/
|
|
|
|
|
|
|
|
local source_pipe;
|
|
|
|
local drain_pipe;
|
|
|
|
|
|
|
|
// Set-Getters for source and drain pipe.
|
|
|
|
public func GetSource() { return source_pipe; }
|
|
|
|
public func SetDrain(object pipe) { drain_pipe = pipe; }
|
|
|
|
public func GetDrain() { return drain_pipe; }
|
|
|
|
|
2012-10-25 18:14:13 +00:00
|
|
|
public func SetSource(object pipe)
|
|
|
|
{
|
|
|
|
source_pipe = pipe;
|
|
|
|
CheckCurrentState();
|
|
|
|
}
|
|
|
|
|
2012-02-18 21:50:18 +00:00
|
|
|
func QueryWaivePowerRequest()
|
|
|
|
{
|
2012-10-25 18:14:13 +00:00
|
|
|
// has less priority than other objects, but not too low
|
|
|
|
return 10;
|
2012-02-18 21:50:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func OnNotEnoughPower()
|
|
|
|
{
|
2013-04-28 11:57:25 +00:00
|
|
|
// assert: current action is "Pump" or "PumpWaitLiquid"
|
|
|
|
SetActionKeepPhase("PumpWaitPower");
|
2012-02-18 21:50:18 +00:00
|
|
|
return _inherited(...);
|
|
|
|
}
|
|
|
|
|
|
|
|
func OnEnoughPower()
|
|
|
|
{
|
2013-04-28 11:57:25 +00:00
|
|
|
// assert: current action is either PumpWaitPower or Wait
|
|
|
|
SetActionKeepPhase("Pump");
|
2012-02-18 21:50:18 +00:00
|
|
|
return _inherited(...);
|
|
|
|
}
|
|
|
|
|
2013-04-28 11:57:25 +00:00
|
|
|
func PumpWaitPowerStart() { return AddTimer(this.PumpingWaitForPower, 60); }
|
|
|
|
func PumpWaitPowerStop() { return RemoveTimer(this.PumpingWaitForPower); }
|
|
|
|
|
|
|
|
func PumpingWaitForPower()
|
|
|
|
{
|
|
|
|
// Waiting for power: Check pump height, because we might become a producer
|
|
|
|
if (!source_pipe) return CheckCurrentState();
|
|
|
|
if (last_source_y != (source_pipe->GetConnectedObject(this) ?? this)->GetY() || last_drain_y != GetDrainObject()->GetY()) UpdatePumpHeight(true);
|
|
|
|
}
|
|
|
|
|
2011-10-11 22:32:46 +00:00
|
|
|
local aMaterials=["", 0]; //contained liquids
|
2012-03-10 17:23:48 +00:00
|
|
|
local pumpable_materials; // materials that can be pumped
|
2013-04-28 11:57:25 +00:00
|
|
|
local last_source_y, last_drain_y;
|
|
|
|
local pump_amount; // mat amount pumped since last height check
|
|
|
|
|
|
|
|
protected func PumpingWaitForLiquid()
|
|
|
|
{
|
|
|
|
// Pump is ready; check for liquids to pump
|
|
|
|
if (!source_pipe) return CheckCurrentState();
|
|
|
|
if(!HasLiquidToPump()) return;
|
|
|
|
// Check stuck drain
|
|
|
|
if (aMaterials[1] && (aMaterials[0] != "")) if (!InsertMaterial(Material(aMaterials[0]), 0,0,0,0, nil, true)) return;
|
|
|
|
// OK; let's pump
|
|
|
|
SetActionKeepPhase("Pump");
|
|
|
|
UpdatePumpHeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
private func GetDrainObject()
|
|
|
|
{
|
|
|
|
if (drain_pipe) return drain_pipe->GetConnectedObject(this) ?? this;
|
|
|
|
return this;
|
|
|
|
}
|
2011-10-11 22:32:46 +00:00
|
|
|
|
2010-12-31 12:20:54 +00:00
|
|
|
protected func Pumping()
|
|
|
|
{
|
2012-10-25 18:14:13 +00:00
|
|
|
// at this point we can assert that we have power
|
|
|
|
|
|
|
|
// something went wrong in the meantime?
|
|
|
|
// let the central function handle that
|
2010-12-31 12:20:54 +00:00
|
|
|
if (!source_pipe)
|
2012-10-25 18:14:13 +00:00
|
|
|
return CheckCurrentState();
|
|
|
|
|
2013-04-28 11:57:25 +00:00
|
|
|
// nothing to pump right now?
|
|
|
|
if(!HasLiquidToPump())
|
|
|
|
{
|
|
|
|
UnmakePowerActuator();
|
|
|
|
SetActionKeepPhase("PumpWaitLiquid");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recheck pump height
|
|
|
|
if (pump_amount > 200 || last_source_y != (source_pipe->GetConnectedObject(this) ?? this)->GetY() || last_drain_y != GetDrainObject()->GetY())
|
|
|
|
{
|
|
|
|
UpdatePumpHeight(true);
|
|
|
|
if (GetAction() != "Pump") return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var pump_ok = true;
|
2012-10-25 18:14:13 +00:00
|
|
|
|
|
|
|
// is empty?
|
2011-10-11 22:32:46 +00:00
|
|
|
if ((aMaterials[1] == 0) || (aMaterials[0] == ""))
|
|
|
|
{
|
2012-10-25 18:14:13 +00:00
|
|
|
// get new materials
|
2012-03-10 17:23:48 +00:00
|
|
|
aMaterials = source_pipe->GetLiquid(pumpable_materials, 5, this, true);
|
2012-10-25 18:14:13 +00:00
|
|
|
// no material to pump?
|
2011-10-11 22:32:46 +00:00
|
|
|
if ((aMaterials[0] == "") || (aMaterials[1] == 0))
|
2013-04-28 11:57:25 +00:00
|
|
|
pump_ok = false;
|
2013-04-28 12:02:57 +00:00
|
|
|
else
|
|
|
|
pump_amount += aMaterials[1];
|
2011-10-11 22:32:46 +00:00
|
|
|
}
|
2013-04-28 11:57:25 +00:00
|
|
|
if (pump_ok)
|
|
|
|
{
|
|
|
|
if (drain_pipe)
|
|
|
|
{
|
|
|
|
var pumped = BoundBy(drain_pipe->PutLiquid(aMaterials[0], aMaterials[1], this), 0, aMaterials[1]);
|
|
|
|
aMaterials[1] -= pumped;
|
|
|
|
// Drain is stuck?
|
|
|
|
if (!pumped) pump_ok = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var i = Max(0, aMaterials[1]), itMaterial = Material(aMaterials[0]);
|
|
|
|
while (i)
|
|
|
|
if (InsertMaterial(itMaterial))
|
|
|
|
i--;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Drain is stuck.
|
|
|
|
pump_ok = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
aMaterials[1] = i;
|
|
|
|
if (!i) aMaterials[0] = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!pump_ok)
|
2011-10-11 22:32:46 +00:00
|
|
|
{
|
2013-04-28 11:57:25 +00:00
|
|
|
// Couldn't pump. Probably drain stuck.
|
|
|
|
UnmakePowerActuator();
|
|
|
|
SetActionKeepPhase("PumpWaitLiquid");
|
2011-10-11 22:32:46 +00:00
|
|
|
}
|
2012-10-25 18:14:13 +00:00
|
|
|
// maybe add the possebility to empty pump (invaild mats?)
|
2013-04-28 11:57:25 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get current height the pump has to push liquids upwards (input.y - output.y)
|
|
|
|
func GetPumpHeight()
|
|
|
|
{
|
|
|
|
var src = source_pipe->GetConnectedObject(this) ?? this, dst = GetDrainObject();
|
|
|
|
var out_pos = {X=dst->GetX(), Y=dst->GetY()};
|
|
|
|
dst->InsertMaterial(Material("Water"), 0,0,0,0, out_pos, true); // TODO assumes water material is loaded
|
|
|
|
var src_x = src->GetX(), src_y = src->GetY();
|
|
|
|
if (Global->GBackLiquid(src_x, src_y))
|
|
|
|
{
|
|
|
|
var src_mat = Global->GetMaterial(src_x, src_y);
|
|
|
|
while (src_y>0 && src_mat == Global->GetMaterial(src_x, src_y-1)) --src_y;
|
|
|
|
}
|
|
|
|
return src_y - out_pos.Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recheck power usage/production for current pump height
|
|
|
|
func UpdatePumpHeight(bool unmake_actuator)
|
|
|
|
{
|
|
|
|
pump_amount = 0;
|
|
|
|
last_source_y = (source_pipe->GetConnectedObject(this) ?? this)->GetY();
|
|
|
|
last_drain_y = GetDrainObject()->GetY();
|
|
|
|
var new_power = PumpHeight2Power(GetPumpHeight());
|
|
|
|
if (unmake_actuator)
|
|
|
|
UnmakePowerActuator();
|
|
|
|
else
|
|
|
|
if (new_power == current_pump_power) return true;
|
|
|
|
return MakePowerActuator(new_power);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Makes this a power consumer or producer and sets appropriate waiting actions
|
|
|
|
func MakePowerActuator(int new_power)
|
|
|
|
{
|
|
|
|
if (new_power > 0)
|
|
|
|
{
|
|
|
|
SetActionKeepPhase("PumpWaitPower");
|
|
|
|
MakePowerConsumer(new_power);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetActionKeepPhase("Pump");
|
|
|
|
if (new_power < 0) MakePowerProducer(-new_power);
|
|
|
|
}
|
|
|
|
current_pump_power = new_power;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
func UnmakePowerActuator()
|
|
|
|
{
|
|
|
|
if (current_pump_power > 0)
|
|
|
|
UnmakePowerConsumer();
|
|
|
|
else if (current_pump_power < 0)
|
|
|
|
MakePowerProducer(0);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transform pump height (input.y - output.y) to required power
|
|
|
|
func PumpHeight2Power(int pump_height)
|
|
|
|
{
|
|
|
|
return BoundBy((pump_height + 35)/30*10, -150,150);
|
2010-12-31 12:20:54 +00:00
|
|
|
}
|
|
|
|
|
2012-10-25 18:14:13 +00:00
|
|
|
func CheckCurrentState()
|
|
|
|
{
|
|
|
|
if(turned_on)
|
|
|
|
{
|
|
|
|
var has_source_pipe = !!source_pipe;
|
|
|
|
var is_fullcon = GetCon() >= 100;
|
|
|
|
|
|
|
|
if(GetAction() == "Wait") // waiting: not consuming power
|
|
|
|
{
|
|
|
|
if(has_source_pipe && is_fullcon)
|
|
|
|
{
|
2013-04-28 11:57:25 +00:00
|
|
|
UpdatePumpHeight();
|
2012-10-25 18:14:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else return; // waiting and no source pipe, keep waiting
|
|
|
|
}
|
|
|
|
else // not waiting: consuming power
|
|
|
|
{
|
|
|
|
if(!has_source_pipe || !is_fullcon)
|
|
|
|
{
|
2013-04-28 11:57:25 +00:00
|
|
|
UnmakePowerActuator();
|
2012-10-25 18:14:13 +00:00
|
|
|
SetAction("Wait");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// this point should not be reached
|
|
|
|
}
|
|
|
|
else // turned off
|
|
|
|
{
|
2013-04-28 11:57:25 +00:00
|
|
|
if(GetAction() != "Wait") // consuming power (except in PumpWaitLiquid condition)
|
2012-10-25 18:14:13 +00:00
|
|
|
{
|
2013-04-28 11:57:25 +00:00
|
|
|
UnmakePowerActuator();
|
2012-10-25 18:14:13 +00:00
|
|
|
SetAction("Wait");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else // already waiting
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
FatalError("Not every case handled in Pump::CheckCurrentState");
|
|
|
|
}
|
|
|
|
|
2010-12-31 12:20:54 +00:00
|
|
|
// Returns whether the pump can pump some liquid.
|
2012-10-25 18:14:13 +00:00
|
|
|
private func HasLiquidToPump()
|
2010-12-31 12:20:54 +00:00
|
|
|
{
|
|
|
|
// If there is no source pipe, return false.
|
|
|
|
if (!source_pipe)
|
|
|
|
return false;
|
|
|
|
// If there is nothing to pump at the source return false.
|
|
|
|
var source = source_pipe->GetConnectedObject(this);
|
|
|
|
if (!source)
|
|
|
|
return false;
|
|
|
|
if (!source->GBackLiquid())
|
|
|
|
return false;
|
|
|
|
// TODO: Account for pumping into buildings.
|
|
|
|
// Pumping is okay.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-03-10 17:23:48 +00:00
|
|
|
/**
|
|
|
|
Set name or wildcard string of materials this pump can pump
|
|
|
|
@param to_val: Material that can be pumped. 0 or "*" for any material.
|
|
|
|
*/
|
|
|
|
public func SetPumpableMaterials(string to_val)
|
|
|
|
{
|
|
|
|
pumpable_materials = to_val;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-12-31 12:20:54 +00:00
|
|
|
local Name = "$Name$";
|
2012-04-15 11:13:14 +00:00
|
|
|
local Description = "$Description$";
|
2012-04-28 14:17:38 +00:00
|
|
|
local BlastIncinerate = 50;
|
2012-05-10 19:20:06 +00:00
|
|
|
local HitPoints = 70;
|
2012-10-25 18:14:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
"Pump": the pump is currently working and consuming power
|
|
|
|
"WillPump": the pump wants to work as soon as there is power
|
|
|
|
"Wait": the pump has been turned off or some other need is not fulfilled (f.e. connected pipe)
|
|
|
|
*/
|
2010-12-31 12:20:54 +00:00
|
|
|
local ActMap = {
|
|
|
|
Pump = {
|
|
|
|
Prototype = Action,
|
|
|
|
Name = "Pump",
|
|
|
|
Procedure = DFA_NONE,
|
2012-08-07 18:54:47 +00:00
|
|
|
Length = 30,
|
2010-12-31 12:20:54 +00:00
|
|
|
Delay = 3,
|
2012-04-16 15:31:38 +00:00
|
|
|
Directions = 2,
|
|
|
|
FlipDir = 1,
|
2010-12-31 12:20:54 +00:00
|
|
|
X = 0,
|
|
|
|
Y = 0,
|
|
|
|
Wdt = 28,
|
|
|
|
Hgt = 32,
|
|
|
|
NextAction = "Pump",
|
2012-10-25 18:14:13 +00:00
|
|
|
StartCall = "CheckCurrentState",
|
2011-10-11 22:32:46 +00:00
|
|
|
PhaseCall = "Pumping"
|
2010-12-31 12:20:54 +00:00
|
|
|
},
|
|
|
|
Wait = {
|
|
|
|
Prototype = Action,
|
|
|
|
Name = "Wait",
|
|
|
|
Procedure = DFA_NONE,
|
|
|
|
Length = 1,
|
2012-10-25 18:14:13 +00:00
|
|
|
Delay = 60,
|
2012-04-16 15:31:38 +00:00
|
|
|
Directions = 2,
|
|
|
|
FlipDir = 1,
|
2010-12-31 12:20:54 +00:00
|
|
|
X = 0,
|
|
|
|
Y = 0,
|
|
|
|
Wdt = 28,
|
|
|
|
Hgt = 32,
|
|
|
|
NextAction = "Wait",
|
2012-10-25 18:14:13 +00:00
|
|
|
StartCall = "CheckCurrentState"
|
|
|
|
},
|
2013-04-28 11:57:25 +00:00
|
|
|
PumpWaitPower = {
|
2012-10-25 18:14:13 +00:00
|
|
|
Prototype = Action,
|
2013-04-28 11:57:25 +00:00
|
|
|
Name = "PumpWaitPower",
|
2012-10-25 18:14:13 +00:00
|
|
|
Procedure = DFA_NONE,
|
2013-04-28 11:57:25 +00:00
|
|
|
Length = 30,
|
|
|
|
Delay = 0,
|
2012-10-25 18:14:13 +00:00
|
|
|
Directions = 2,
|
|
|
|
FlipDir = 1,
|
|
|
|
X = 0,
|
|
|
|
Y = 0,
|
|
|
|
Wdt = 28,
|
|
|
|
Hgt = 32,
|
2013-04-28 11:57:25 +00:00
|
|
|
StartCall = "PumpWaitPowerStart",
|
|
|
|
AbortCall = "PumpWaitPowerStop",
|
|
|
|
NextAction = "PumpWaitPower"
|
|
|
|
},
|
|
|
|
PumpWaitLiquid = { // Pump waiting for liquid: Move slowly to indicate we're turned on
|
|
|
|
Prototype = Action,
|
|
|
|
Name = "PumpWaitLiquid",
|
|
|
|
Procedure = DFA_NONE,
|
|
|
|
Length = 30,
|
|
|
|
Delay = 10,
|
|
|
|
Directions = 2,
|
|
|
|
FlipDir = 1,
|
|
|
|
X = 0,
|
|
|
|
Y = 0,
|
|
|
|
Wdt = 28,
|
|
|
|
Hgt = 32,
|
|
|
|
NextAction = "PumpWaitLiquid",
|
|
|
|
PhaseCall = "PumpingWaitForLiquid"
|
2011-10-11 22:32:46 +00:00
|
|
|
}
|
2011-01-02 21:43:54 +00:00
|
|
|
};
|
2013-04-28 11:57:25 +00:00
|
|
|
|
|
|
|
// Set action while retaining phase from last action
|
|
|
|
func SetActionKeepPhase(string act)
|
|
|
|
{
|
|
|
|
var phase = GetPhase();
|
|
|
|
if (!SetAction(act)) return false;
|
|
|
|
SetPhase(phase);
|
|
|
|
return true;
|
|
|
|
}
|