refactor pump done. Remaining problem: power system (usage)

stable-5.4
Tobias Zwick 2013-05-30 22:11:39 +02:00
parent a6adc2465f
commit 131ec86b98
12 changed files with 399 additions and 452 deletions

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>CanInsertMaterial</title>
<category>Landscape</category>
<subcat>Material</subcat>
<version>5.4 OC</version>
<syntax>
<rtype>bool</rtype>
<params>
<param>
<type>int</type>
<name>material_index</name>
<desc>Material to test to be inserted (see <funclink>Material</funclink>()).</desc>
</param>
<param>
<type>int</type>
<name>x</name>
<desc>X insert position or offset</desc>
<optional />
</param>
<param>
<type>int</type>
<name>y</name>
<desc>Y insert position or offset</desc>
<optional />
</param>
</params>
</syntax>
<desc>Tests if a material pixel at the given position can be inserted.</desc>
<remark>If the target position already contains material of the same density as the inserted material, the engine will search upwards for a proper insertion position.</remark>
<related>
<funclink>Material</funclink>
</related>
</func>
<author>Sven2</author><date>2001-11</date>
</funcs>

View File

@ -1,64 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>InsertMaterial</title>
<category>Landscape</category>
<subcat>Material</subcat>
<version>5.1 OC</version>
<syntax>
<rtype>bool</rtype>
<params>
<param>
<type>int</type>
<name>material_index</name>
<desc>Material to be inserted (see <funclink>Material</funclink>()).</desc>
</param>
<param>
<type>int</type>
<name>x</name>
<desc>X insert position or offset</desc>
<optional />
</param>
<param>
<type>int</type>
<name>y</name>
<desc>Y insert position or offset</desc>
<optional />
</param>
<param>
<type>int</type>
<name>xdir</name>
<desc>horizontal speed of material pixel to be inserted</desc>
<optional />
</param>
<param>
<type>int</type>
<name>ydir</name>
<desc>vertical speed of material pixel to be inserted</desc>
<optional />
</param>
<param>
<type>proplist</type>
<name>out_insertpos</name>
<desc>If a writeable proplist is passed, members x and y are filled with the actual insertion position.</desc>
<optional />
</param>
<param>
<type>bool</type>
<name>query_only</name>
<desc>If set, the material is not actually inserted. Use this if you are only interested if insertion would be possible and where it would take place.</desc>
<optional />
</param>
</params>
</syntax>
<desc>Inserts a material pixel at the given position and given speed.</desc>
<remark>If the target position already contains material of the same density as the inserted material, the engine will search upwards for a proper insertion position. Use the parameter out_insertpos to find out where material was actually inserted.</remark>
<related>
<funclink>Material</funclink>
</related>
</func>
<author>Sven2</author><date>2001-11</date>
</funcs>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>InsertMaterial</title>
<category>Landscape</category>
<subcat>Material</subcat>
<version>5.1 OC</version>
<syntax>
<rtype>bool</rtype>
<params>
<param>
<type>int</type>
<name>material_index</name>
<desc>Material to be inserted (see <funclink>Material</funclink>()).</desc>
</param>
<param>
<type>int</type>
<name>x</name>
<desc>X insert position or offset</desc>
<optional />
</param>
<param>
<type>int</type>
<name>y</name>
<desc>Y insert position or offset</desc>
<optional />
</param>
<param>
<type>int</type>
<name>xdir</name>
<desc>horizontal speed of material pixel to be inserted</desc>
<optional />
</param>
<param>
<type>int</type>
<name>ydir</name>
<desc>vertical speed of material pixel to be inserted</desc>
<optional />
</param>
</params>
</syntax>
<desc>Inserts a material pixel at the given position and given speed.</desc>
<remark>If the target position already contains material of the same density as the inserted material, the engine will search upwards for a proper insertion position.</remark>
<related>
<funclink>Material</funclink>
</related>
</func>
<author>Sven2</author><date>2001-11</date>
</funcs>

View File

@ -85,8 +85,8 @@ global func FxDryTimeTimer(object pTarget, effect, int timer)
InsertMaterial(Material("Water"),Random(LandscapeWidth()-60)+30,1,Random(7)-3,100+Random(100));
return 1;
}
for(var i=0; i<6+Random(4);i++)
ExtractLiquid(310+Random(50),430+Random(10));
ExtractLiquidAmount(310+Random(50),430+Random(10),6+Random(4));
if(!GBackLiquid(335,430))
{
AddEffect("Rain",nil,100,2);

View File

@ -108,8 +108,7 @@ protected func FxIntLiquidDrainStart(object target, proplist effect, int tempora
protected func FxIntLiquidDrainTimer(object target, proplist effect)
{
for (var i = 0; i < effect.Strength / 2; i++)
ExtractLiquid(AbsX(effect.X), AbsY(effect.Y));
ExtractLiquidAmount(AbsX(effect.X), AbsY(effect.Y),effect.Strength / 2);
return 1;
}

View File

@ -28,12 +28,7 @@ private func Melt()
private func Freeze()
{
DoCon(1);
var i=2;
while(i>0)
{
ExtractLiquid();
i=--i;
}
ExtractMaterialAmount(0,0,Material("Water"),2);
}
local Collectible = 1;

View File

@ -1,6 +1,18 @@
/*-- Pipe line --*/
/*-- Pipe line
//Author: ST-DDT
Author: ST-DDT
--*/
local Name = "$Name$";
local ActMap = {
Connect = {
Prototype = Action,
Name = "Connect",
Procedure = DFA_CONNECT,
NextAction = "Connect"
}
};
protected func Initialize()
{
@ -11,19 +23,19 @@ protected func Initialize()
return;
}
// Returns true if this object is a functioning pipe.
/** Returns true if this object is a functioning pipe. */
public func IsPipeLine()
{
return GetAction() == "Connect";
}
// Returns whether this pipe is connected to an object.
/** Returns whether this pipe is connected to an object. */
public func IsConnectedTo(object obj)
{
return GetActionTarget(0) == obj || GetActionTarget(1) == obj;
}
// Returns the object which is connected to obj through this pipe.
/** Returns the object which is connected to obj through this pipe. */
public func GetConnectedObject(object obj)
{
if (GetActionTarget(0) == obj)
@ -50,62 +62,3 @@ private func BreakMessage()
line_end->Message("$TxtPipeBroke$");
return;
}
local ActMap = {
Connect = {
Prototype = Action,
Name = "Connect",
Procedure = DFA_CONNECT,
NextAction = "Connect"
}
};
/**
Extract liquid from barrel
@param sznMaterial: Material to extract; Wildcardsupport
@param inMaxAmount: Max Amount of Material being extracted
@param pnTarget: Object which extracts the liquid
@return [irMaterial,irAmount]
-irMaterial: Material being extracted
-irAmount: Amount being extracted
*/
public func GetLiquid(string sznMaterial, int inMaxAmount, object pnTarget, bool bWildcard)
{
var pConnected = GetConnectedObject(pnTarget);
if (!pConnected)
return ["", 0];
var aMat = pConnected->~LiquidOutput(sznMaterial, inMaxAmount, pnTarget, this, bWildcard);
//Bad script? Not needed.
if (GetType(aMat) != C4V_Array)
return [-1, 0];
//Verify data
if ((aMat[0] == "") || (GetLength(aMat) == 1))
aMat[1] = 0;
//Nothing is nothing
if (aMat[1] <= 0)
{
aMat[0] = "";
aMat[1] = 0;
} //Bad script end
return aMat;
}
/**
Insert liquid to barrel
@param sznMaterial: Material to insert
@param inMaxAmount: Max Amount of Material being inserted
@param pnSource: Object which inserts the liquid
@return inAmount: The inserted amount
*/
public func PutLiquid(string sznMaterial, int inMaxAmount, object pnSource)
{
var pConnected = GetConnectedObject(pnSource);
if (!pConnected)
return 0;
if (sznMaterial == "")
return 0;
return BoundBy(pConnected->~LiquidInput(sznMaterial, inMaxAmount, pnSource, this), 0, inMaxAmount);
}
local Name = "$Name$";

View File

@ -1,6 +1,13 @@
/*-- Pipe --*/
/*-- Pipe
//Author: ST-DDT
Author: ST-DDT
--*/
local Name = "$Name$";
local Description = "$Description$";
local UsageHelp = "$UsageHelp$";
local Collectible = 1;
local Rebuy = true;
protected func Hit()
{
@ -11,17 +18,13 @@ public func IsToolProduct() { return true; }
/*-- Line connection --*/
// Called with double dig: will connect power line to building at the clonk's position.
/** Will connect power line to building at the clonk's position. */
protected func ControlUse(object clonk, int x, int y)
{
// Is this already connected to a liquid pump?
if (FindObject(Find_PipeLine()))
if (FindObject(Find_Func("IsConnectedTo",this)))
return false;
// Only use if clonk is walking.
if (!clonk->IsWalking())
return true;
// Clonk should stand still.
clonk->SetComDir(COMD_Stop);
// Is there an object which accepts power lines?
var liquid_pump = FindObject(Find_AtPoint(), Find_Func("IsLiquidPump"));
// No liquid pump, display message.
@ -30,96 +33,33 @@ protected func ControlUse(object clonk, int x, int y)
clonk->Message("$MsgNoNewPipe$");
return true;
}
// already two pipes connected
if(liquid_pump->GetSource() && liquid_pump->GetDrain())
{
clonk->Message("MsgHasPipes");
return true;
}
// Create and connect pipe.
var pipe;
var pipe = CreateObject(PipeLine, 0, 0, NO_OWNER);
pipe->SetActionTargets(this, liquid_pump);
Sound("Connect");
// If liquid pump has no source yet, create one.
if (!liquid_pump->GetSource())
{
pipe = CreateObject(PipeLine, 0, 0, NO_OWNER);
pipe->SetActionTargets(this, liquid_pump);
liquid_pump->SetSource(pipe);
Sound("Connect");
clonk->Message("$MsgCreatedSource$");
return true;
}
// Otherwise if liquid pump has no drain, create one.
if (!liquid_pump->GetDrain())
else
{
pipe = CreateObject(PipeLine, 0, 0, NO_OWNER);
pipe->SetActionTargets(this, liquid_pump);
liquid_pump->SetDrain(pipe);
Sound("Connect");
clonk->Message("$MsgCreatedDrain$");
return true;
}
// Otherwise do nothing and notify player.
clonk->Message("MsgHasPipes");
return true;
}
// Finds all pipe lines connected to obj (can be nil in local calls).
private func Find_PipeLine(object obj)
{
if (!obj)
obj = this;
return [C4FO_Func, "IsConnectedTo", obj];
}
/**
Extract liquid from this
@param sznMaterial: Material to extract. 0 or "*" for any material.
@param inMaxAmount: Max Amount of Material being extracted
@param pnPump: Object which extracts the liquid
@param pnPipe: Pipe which extracts the liquid (connected to pnPump)
@param bnWildcard: Usefull to extract random liquids; use '*' for sznMaterial for all Materials
@return [irMaterial,irAmount]
-irMaterial: Material being extracted
-irAmount: Amount being extracted
*/
public func LiquidOutput(string sznMaterial, int inMaxAmount, object pnPump, object pnPipe, bool bnWildcard)
{
var itMaterial;
//Search liquid to pump
if (bnWildcard)
{
itMaterial = GetMaterial();
//nothing?
if (itMaterial == -1)
return ["", 0];
//no liquid?
if (GetMaterialVal("Density", "Material", itMaterial) != 25)
return ["", 0];
//wrong liquid?
if (sznMaterial)
if (!WildcardMatch(MaterialName(itMaterial),sznMaterial))
return ["", 0];
sznMaterial = MaterialName(itMaterial);
}
else
itMaterial = Material(sznMaterial);
if (GetMaterial() != itMaterial)
return ["", 0];
var itFound = ExtractMaterialAmount(0, 0, itMaterial, 5);
return [sznMaterial, itFound];
}
/**
Insert liquid to this
@param sznMaterial: Material to insert
@param inMaxAmount: Max Amount of Material being inserted
@param pnPump: Object which inserts the liquid
@param pnPipe: Pipe which inserts the liquid (connected to pnPump)
@return irAmount: The inserted amount
*/
public func LiquidInput(string sznMaterial, int inMaxAmount, object pnPump, object pnPipe)
{
var i=Max(0,inMaxAmount),itMaterial=Material(sznMaterial), n_inserted;
while (i--) if (InsertMaterial(itMaterial)) ++n_inserted; else break;
return n_inserted;
}
local Name = "$Name$";
local Description = "$Description$";
local UsageHelp = "$UsageHelp$";
local Collectible = 1;
local Rebuy = true;

View File

@ -1,8 +1,12 @@
/*--
Pump
Author: Maikel, ST-DDT, Sven2
Author: Maikel, ST-DDT, Sven2, Newton
Pumps liquids using drain and source pipes. Features include:
+ switch on and off
+ consume/produce a variable amount of power depending on the height of
source and drain
Pumps liquids using drain and source pipes.
--*/
#include Library_Structure
@ -10,37 +14,97 @@
#include Library_PowerConsumer
#include Library_PowerProducer
local Name = "$Name$";
local Description = "$Description$";
local BlastIncinerate = 50;
local HitPoints = 70;
/*
States
"Wait": turned off or source pipe not connected
"WaitForPower": turned on but no power (does consume power)
"WaitForLiquid": turned on but no liquid (does not consume power)
"Pump": currently working and consuming/producing power
*/
local ActMap = {
Pump = {
Prototype = Action,
Name = "Pump",
Length = 30,
Delay = 3,
NextAction = "Pump",
StartCall = "CheckState",
PhaseCall = "Pumping"
},
Wait = {
Prototype = Action,
Name = "Wait",
Delay = 90,
NextAction = "Wait",
EndCall = "CheckState"
},
WaitForPower = {
Prototype = Action,
Name = "WaitForPower",
Delay = 150,
NextAction = "WaitForPower",
EndCall = "CheckState"
},
WaitForLiquid = {
Prototype = Action,
Name = "WaitForLiquid",
Delay = 30,
NextAction = "WaitForLiquid",
EndCall = "CheckState"
}
};
local animation; // animation handle
local switched_on; // the pump can be switched on and off with interact
local powered; // whether the pump is powered (either has enough power as consumer or even produces power)
local stored_material_index; //contained liquid
local stored_material_amount;
local source_pipe;
local drain_pipe;
/** This object is a liquid pump, thus pipes can be connected. */
local current_animation; // Current animation handle
public func IsLiquidPump() { return true; }
// Rotate at a 45 degree angle towards viewer and add a litte bit of Random
SetProperty("MeshTransformation",Trans_Rotate(RandomX(0,3)*90+45+RandomX(-5,5),0,1,0));
public func Definition(def)
func Definition(def)
{
SetProperty("MeshTransformation",Trans_Rotate(45,0,1,0));
// for title image
SetProperty("PictureTransformation",Trans_Rotate(50,0,1,0),def);
// for building preview
SetProperty("MeshTransformation",Trans_Rotate(50,0,1,0),def);
}
protected func Initialize()
func Construction()
{
turned_on = true;
// Rotate at a 45 degree angle towards viewer and add a litte bit of Random
this.MeshTransformation = Trans_Rotate(50 + RandomX(-10,10),0,1,0);
}
func Initialize()
{
switched_on = true;
var start = 0;
var end = GetAnimationLength("pump");
current_animation = PlayAnimation("pump", 5, Anim_Linear(0, start, end, 90, ANIM_Loop), Anim_Const(1));
SetActionKeepPhase("Wait");
AddTimer("CheckTimer");
return;
animation = PlayAnimation("pump", 5, Anim_Linear(GetAnimationPosition(animation), start, end, 35, ANIM_Loop), Anim_Const(1000));
SetState("Wait");
}
/*-- Interaction --*/
local turned_on;
public func IsInteractable() { return GetCon() >= 100; }
public func GetInteractionMetaInfo(object clonk)
{
if (turned_on)
if (switched_on)
return { Description = "$MsgTurnOff$", IconName = nil, IconID = Icon_Stop };
else
return { Description = "$MsgTurnOn$", IconName = nil, IconID = Icon_Play };
@ -49,13 +113,7 @@ public func GetInteractionMetaInfo(object clonk)
/** Turn on or off. */
public func Interact(object clonk)
{
turned_on = !turned_on;
if(!turned_on) {
SetAction("Wait");
}
else {
SetAction("Pump");
}
switched_on = !switched_on;
CheckState();
return true;
@ -63,16 +121,13 @@ public func Interact(object clonk)
/*-- 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; }
public func SetSource(object pipe)
{
Log("source pipe connected");
source_pipe = pipe;
CheckState();
}
@ -87,38 +142,20 @@ func QueryWaivePowerRequest()
func OnNotEnoughPower()
{
// assert: current action is "Pump" or "PumpWaitLiquid"
SetAction("PumpWaitPower");
Log("not enough power");
powered = false;
CheckState();
return _inherited(...);
}
func OnEnoughPower()
{
// assert: current action is either PumpWaitPower or Wait
SetAction("Pump");
Log("enough power");
powered = true;
CheckState();
return _inherited(...);
}
local aMaterials=["", 0]; //contained liquids
local pumpable_materials; // materials that can be pumped
local pump_amount; // mat amount pumped since last height check
/** PhaseCall of PumpWaitLiquid */
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
SetAction("Pump");
}
/** Returns object to which the liquid is pumped */
private func GetDrainObject()
{
@ -133,110 +170,133 @@ private func GetSourceObject()
return this;
}
/** Returns amount of pixels to pump per 30 frames */
public func GetPumpSpeed()
{
return 50;
}
/** PhaseCall of Pump: Pump the liquid from the source to the drain pipe */
protected func Pumping()
{
// at this point we can assert that we have power
// something went wrong in the meantime?
// let the central function handle that
if (!source_pipe)
return CheckState();
// nothing to pump right now?
if(!HasLiquidToPump())
{
SetAction("PumpWaitLiquid");
return;
}
// let the central function handle that on next check
if (!source_pipe) return;
var pump_ok = true;
// is empty?
if ((aMaterials[1] == 0) || (aMaterials[0] == ""))
// is empty? -> try to get liquid
if (!stored_material_amount)
{
// get new materials
aMaterials = source_pipe->GetLiquid(pumpable_materials, 5, this, true);
// no material to pump?
if ((aMaterials[0] == "") || (aMaterials[1] == 0))
pump_ok = false;
else
pump_amount += aMaterials[1];
// get new materials
var aMat = GetSourceObject()->ExtractLiquidAmount(0,0, GetPumpSpeed()/10);
// no material to pump?
if (aMat)
{
stored_material_index = aMat[0];
stored_material_amount = aMat[1];
}
else
{
pump_ok = false;
}
}
if (pump_ok)
{
if (drain_pipe)
var i = stored_material_amount;
while (i > 0)
{
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;
if (GetDrainObject()->InsertMaterial(stored_material_index))
{
i--;
}
// Drain is stuck.
else
{
pump_ok = false;
break;
}
}
stored_material_amount = i;
if (stored_material_amount <= 0)
stored_material_index = nil;
if(!pump_ok) {Log("cant drain liquid");}
}
else { Log("cant get liquid"); }
if(!pump_ok)
{
SetState("WaitForLiquid");
}
}
/** Re check state and change the state if needed */
func CheckState()
{
var is_fullcon = GetCon() >= 100;
var can_pump = source_pipe && is_fullcon && switched_on;
Message("@0");
// can't pump at all -> wait
if (!can_pump)
{
SetState("Wait");
}
else
{
// can pump but has no liquid -> wait for liquid
if (!HasLiquidToPump())
{
SetState("WaitForLiquid");
}
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)
{
// Couldn't pump. Probably drain stuck.
SetAction("PumpWaitLiquid");
}
// maybe add the possibility to empty pump (invaild mats?)
return;
}
func CheckState()
{
if(turned_on)
{
var is_fullcon = GetCon() >= 100;
if(GetAction() == "Wait") // waiting: not consuming power
{
if(source_pipe && is_fullcon)
// can pump, has liquid but has no power -> wait for power
if (!powered)
{
SetAction("Pump");
SetState("WaitForPower");
}
}
else // not waiting: consuming power
{
if(!source_pipe || !is_fullcon)
// otherwise, pump! :-)
else
{
SetAction("Wait");
SetState("Pump");
}
// regularly update the power usage while pumping or waiting for power
UpdatePowerUsage();
}
}
UpdatePowerUsage();
}
/** Get current height the pump has to push liquids upwards (input.y - output.y) */
private func GetPumpHeight()
{
var target = {X=GetDrainObject()->GetX(), Y=GetDrainObject()->GetY()};
var source = {X=GetSourceObject()->GetX(), Y=GetSourceObject()->GetY()};
// compare each the surfaces of the bodies of liquid pumped
// find Y position of surface of liquid that is pumped to target
if (Global->GBackLiquid(source.X, source.Y))
var source_y = 0;
if (GetSourceObject()->GBackLiquid())
{
var src_mat = Global->GetMaterial(source.X, source.Y);
while (source.Y > 0 && src_mat == Global->GetMaterial(source.X, source.Y-1))
--source.Y;
var src_mat = GetSourceObject()->GetMaterial();
while (src_mat == GetSourceObject()->GetMaterial(0, source_y-1))
--source_y;
}
return source.Y - target.Y;
// same for target
var target_y = 0;
if (GetDrainObject()->GBackLiquid())
{
var src_mat = GetDrainObject()->GetMaterial();
while (src_mat == GetDrainObject()->GetMaterial(0, target_y-1))
--target_y;
}
return (GetSourceObject()->GetY() + source_y) - (GetDrainObject()->GetY() + target_y);
}
/** Recheck power usage/production for current pump height
@ -260,13 +320,15 @@ private func UpdatePowerUsage()
UnmakePowerConsumer();
MakePowerProducer(-new_power);
}
Message("@%d",new_power);
}
/** Return whether the pump should be using power in the current state */
private func IsUsingPower()
{
// does also not consume power if waiting (for source pipe)
return turned_on && GetAction() != "Wait" && GetAction() != "PumpWaitLiquid";
return switched_on && GetAction() != "Wait" && GetAction() != "WaitForLiquid";
}
/** Transform pump height (input.y - output.y) to required power */
@ -277,105 +339,55 @@ private func PumpHeight2Power(int pump_height)
// max power consumed/produced
var max_power = 150;
return BoundBy((pump_height + power_offset)/30*10, -max_power,max_power);
return BoundBy((pump_height + power_offset)/15*5, -max_power,max_power);
}
/** Returns whether there is liquid at the source pipe to pump */
private func HasLiquidToPump()
{
// also return false if there is no source (pipe) connected
if (!source_pipe)
return false;
var source = source_pipe->GetConnectedObject(this);
if (!source)
return false;
if (!source->GBackLiquid())
// source
if(!GetSourceObject()->GBackLiquid())
return false;
// TODO: Account for pumping into buildings.
// target (test with the very popular liquid "water"
if(!GetDrainObject()->CanInsertMaterial(Material("Water"),0,0))
return false;
return true;
}
/**
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)
/** Set the state of the pump, retaining the animation position and updating the power usage */
func SetState(string act)
{
pumpable_materials = to_val;
return true;
}
if(act == GetAction()) return;
local Name = "$Name$";
local Description = "$Description$";
local BlastIncinerate = 50;
local HitPoints = 70;
Log("setting state %s",act);
/*
States
"Wait": turned off or source pipe not connected
"Pump": currently working and consuming/producing power
"PumpWaitLiquid": waiting for liquid to pump
"PumpWaitPower": waiting for power
*/
local ActMap = {
Pump = {
Prototype = Action,
Name = "Pump",
Procedure = DFA_NONE,
Length = 30,
Delay = 3,
NextAction = "Pump",
PhaseCall = "Pumping"
},
Wait = {
Prototype = Action,
Name = "Wait",
Procedure = DFA_NONE,
Length = 1,
Delay = 60,
NextAction = "Wait",
},
PumpWaitPower = {
Prototype = Action,
Name = "PumpWaitPower",
Procedure = DFA_NONE,
Length = 30,
Delay = 0,
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,
NextAction = "PumpWaitLiquid",
PhaseCall = "PumpingWaitForLiquid"
var start = 0;
var end = GetAnimationLength("pump");
if (act == "Pump")
{
SetAnimationPosition(animation, Anim_Linear(GetAnimationPosition(animation), start, end, 35, ANIM_Loop));
}
};
// Set action while retaining phase from last action
func SetActionKeepPhase(string act)
{
Log("action ist:%s", act);
// Action for being off
if (act == "PumpWaitPower" || act == "Wait")
else if(act == "WaitForLiquid")
{
SetAnimationPosition(current_animation, Anim_Const(GetAnimationPosition(current_animation)));
}
else if (act == "PumpWaitLiquid")
{
var start = 0;
var end = GetAnimationLength("pump");
SetAnimationPosition(current_animation, Anim_Linear(GetAnimationPosition(current_animation), start, end, 300, ANIM_Loop));
SetAnimationPosition(animation, Anim_Linear(GetAnimationPosition(animation), start, end, 350, ANIM_Loop));
}
else
else
{
var start = 0;
var end = GetAnimationLength("pump");
SetAnimationPosition(current_animation, Anim_Linear(GetAnimationPosition(current_animation), start, end, 90, ANIM_Loop));
}
SetAnimationPosition(animation, Anim_Const(GetAnimationPosition(animation)));
}
// deactivate power usage on wait
if (act == "Wait")
{
UnmakePowerProducer();
UnmakePowerConsumer();
Message("@OFF");
}
// finally, set the action
SetAction(act);
}

View File

@ -1,4 +1,4 @@
Name=Pumpe
Description=Die Pumpe kann beliebige Flüssigkeiten von A nach B pumpen.
Description=Die Pumpe kann beliebige Flüssigkeiten von A nach B pumpen. Pumpt sie Flüssigkeiten abwärts, erzeugt sie dabei sogar ein wenig Strom.
MsgTurnOff=Pumpe abschalten
MsgTurnOn=Pumpe anschalten

View File

@ -1,4 +1,4 @@
Name=Pump
Description=The pump can transport liquid from A to B.
Description=The pump can transport liquid from A to B. If it pumps liquids downwards, it even generates a bit of power.
MsgTurnOff=Turn off pump
MsgTurnOn=Turn on pump

View File

@ -51,24 +51,42 @@ global func FindPosInMat(string sMat, int iXStart, int iYStart, int iWidth, int
return 0; // No location found.
}
// Removes a material pixel from the specified location, if the material is a liquid.
// \par x X coordinate. Offset if called in object context.
// \par y Y coordinate. Offset if called in object context.
// \returns The material index of the removed pixel, or -1 if no liquid was found.
/** Removes a material pixel from the specified location, if the material is a liquid.
@param x X coordinate
@param y Y coordinate
@return The material index of the removed pixel, or -1 if no liquid was found. */
global func ExtractLiquid(int x, int y)
{
var mat = GetMaterial(x, y);
var density = GetMaterialVal("Density", "Material", mat);
if (density < C4M_Liquid || density >= C4M_Solid)
return -1;
ExtractMaterialAmount(x, y, mat, 1);
return mat;
var result = ExtractLiquidAmount(x, y, 1);
if(!result) return -1;
return result[0];
}
// Removes a material pixel from the specified location, if the material is flammable.
// \par x X coordinate. Offset if called in object context.
// \par y Y coordinate. Offset if called in object context.
// \returns \c true if material was removed, \c false otherwise.
/** Tries to remove amount material pixels from the specified location if the material is a liquid.
@param x X coordinate
@param y Y coordinate
@param amount amount of liquid that should be extracted
@return an array with the first position being the material index being extracted and the second the
actual amount of pixels extracted OR nil if there was no liquid at all */
global func ExtractLiquidAmount(int x, int y, int amount)
{
var mat = GetMaterial(x, y);
if(mat == -1)
return nil;
var density = GetMaterialVal("Density", "Material", mat);
if (density < C4M_Liquid || density >= C4M_Solid)
return nil;
var amount = ExtractMaterialAmount(x, y, mat, amount);
if (amount <= 0)
return nil;
return [mat, amount];
}
/** Removes a material pixel from the specified location, if the material is flammable
@param x X coordinate. Offset if called in object context.
@param y Y coordinate. Offset if called in object context.
@return true if material was removed, false otherwise. */
global func FlameConsumeMaterial(int x, int y)
{
var mat = GetMaterial(x, y);

View File

@ -332,20 +332,21 @@ static bool FnSmoke(C4PropList * _this, long tx, long ty, long level, long dwClr
return true;
}
static bool FnInsertMaterial(C4PropList * _this, long mat, long x, long y, long vx, long vy, C4PropList *insert_position, bool query_only)
static bool FnInsertMaterial(C4PropList * _this, long mat, long x, long y, long vx, long vy)
{
if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
int32_t insert_x=x, insert_y=y;
if (!::Landscape.InsertMaterial(mat,&insert_x,&insert_y,vx,vy,query_only)) return false;
// output insertion position if desired
if (insert_position && !insert_position->IsFrozen())
{
insert_position->SetProperty(P_X, C4VInt(insert_x));
insert_position->SetProperty(P_Y, C4VInt(insert_y));
}
return true;
return ::Landscape.InsertMaterial(mat,&insert_x,&insert_y,vx,vy);
}
static bool FnCanInsertMaterial(C4PropList * _this, long mat, long x, long y)
{
if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); }
int32_t insert_x=x, insert_y=y;
return ::Landscape.InsertMaterial(mat,&insert_x,&insert_y,0,0,true);
}
static long FnGetMaterialCount(C4PropList * _this, long iMaterial, bool fReal)
{
if (!MatValid(iMaterial)) return -1;
@ -2349,6 +2350,7 @@ void InitGameFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "Material", FnMaterial);
AddFunc(pEngine, "BlastFree", FnBlastFree);
AddFunc(pEngine, "InsertMaterial", FnInsertMaterial);
AddFunc(pEngine, "CanInsertMaterial", FnCanInsertMaterial);
AddFunc(pEngine, "LandscapeWidth", FnLandscapeWidth);
AddFunc(pEngine, "LandscapeHeight", FnLandscapeHeight);
AddFunc(pEngine, "SetSeason", FnSetSeason);