forked from Mirrors/openclonk
216 lines
5.0 KiB
C
216 lines
5.0 KiB
C
/**
|
|
Windmill
|
|
Crushes seeds into flour using power. It can either use its own power
|
|
generated by the mill or drain power from the network if the wind does
|
|
not supply enough.
|
|
|
|
@authors Ringwaul, Clonkonaut, Maikel
|
|
*/
|
|
|
|
#include Library_Structure
|
|
#include Library_Ownable
|
|
#include Library_Producer
|
|
|
|
local last_power;
|
|
local wheel;
|
|
|
|
func TurnAnimation() { return "Spin"; }
|
|
func MinRevolutionTime() { return 18000; } // in frames
|
|
|
|
protected func Construction()
|
|
{
|
|
SetProperty("MeshTransformation", Trans_Rotate(-30, 0, 1, 0));
|
|
SetAction("Default");
|
|
return _inherited(...);
|
|
}
|
|
|
|
public func IsHammerBuildable() { return true; }
|
|
|
|
protected func Initialize()
|
|
{
|
|
// Create a helper object for the wheel.
|
|
wheel = CreateObject(WindGenerator_Wheel, 0, 0, NO_OWNER);
|
|
wheel->SetParent(this, 150);
|
|
// Start the animation for the wheel.
|
|
PlayAnimation(TurnAnimation(), 5, wheel->Anim_R(GetAnimationLength(TurnAnimation()), 0));
|
|
// Initialize a regular check of the wheel's position and speed, also handles power updates.
|
|
last_power = 0;
|
|
AddTimer("Wind2Turn", 4);
|
|
Wind2Turn();
|
|
// Another timer for the collection zone.
|
|
AddTimer("CollectionZone", 1);
|
|
return _inherited(...);
|
|
}
|
|
|
|
// Timer, check for objects to collect in the designated collection zone.
|
|
public func CollectionZone()
|
|
{
|
|
if (GetCon() < 100)
|
|
return;
|
|
for (var object in FindObjects(Find_InRect(-18 + 21 * GetDir(), 35, 15, 15), Find_OCF(OCF_Collectible), Find_NoContainer(), Find_Layer(GetObjectLayer())))
|
|
Collect(object);
|
|
return;
|
|
}
|
|
|
|
protected func Collection()
|
|
{
|
|
Sound("Objects::Clonk");
|
|
return;
|
|
}
|
|
|
|
/*-- Power Production --*/
|
|
|
|
// Returns the wind weighted over several points.
|
|
private func GetWeightedWind()
|
|
{
|
|
return (
|
|
(10 * GetWind(-150, -30)) +
|
|
(25 * GetWind( -75, -30)) +
|
|
(30 * GetWind( 0, -30)) +
|
|
(25 * GetWind( +75, -30)) +
|
|
(10 * GetWind(+150, -30))
|
|
) / 100;
|
|
}
|
|
|
|
// Turns wind into power and adjusts the power production accordingly.
|
|
public func Wind2Turn()
|
|
{
|
|
// Only produce power if fully constructed.
|
|
if (GetCon() < 100)
|
|
return;
|
|
var current_wind = GetWeightedWind();
|
|
// Determine the current power production.
|
|
var power = 0;
|
|
if (!wheel->Stuck() && !wheel->HasStopped())
|
|
{
|
|
// Produced power ranges from 0 to 80 in steps of 10.
|
|
power = Abs(wheel->GetRDir(MinRevolutionTime() / 90));
|
|
power = BoundBy((10 * power + 60) / 125 * 10, 0, 80);
|
|
|
|
// Make some sounds.
|
|
if (Random(10 + Abs(current_wind)) < 5 && !Random(5))
|
|
Sound(["Hits::Materials::Wood::WoodCreak?","Structures::HingeCreak?"][Random(2)], false, nil, nil, nil, 75);
|
|
}
|
|
// Update the power consumption if the produced power has changed.
|
|
if (last_power != power)
|
|
{
|
|
last_power = power;
|
|
// If in production update the power consumption.
|
|
if (GetEffect("InProduction", this))
|
|
RegisterPowerRequest(this->PowerNeed());
|
|
}
|
|
// Adjust the wheel speed.
|
|
wheel->SetRDir(current_wind * 90, MinRevolutionTime());
|
|
return;
|
|
}
|
|
|
|
// Power need for the production library.
|
|
public func PowerNeed()
|
|
{
|
|
return Max(0, 30 - last_power);
|
|
}
|
|
|
|
|
|
/*-- Production --*/
|
|
|
|
private func IgnoreKnowledge() { return true; }
|
|
|
|
private func IsProduct(id product_id)
|
|
{
|
|
return product_id->~IsWindmillProduct();
|
|
}
|
|
|
|
private func ProductionTime(id product) { return _inherited(product, ...) ?? 290; }
|
|
|
|
public func OnProductionStart(id product)
|
|
{
|
|
AddEffect("InProduction", this, 100, 10, this);
|
|
AddEffect("Crushing", this, 100, 10, this);
|
|
return;
|
|
}
|
|
|
|
public func OnProductionContinued(id product)
|
|
{
|
|
AddEffect("Crushing", this, 100, 10, this);
|
|
return;
|
|
}
|
|
|
|
public func OnProductionHold(id product)
|
|
{
|
|
RemoveEffect("Crushing", this);
|
|
return;
|
|
}
|
|
|
|
public func OnProductionFinish(id product)
|
|
{
|
|
RemoveEffect("InProduction", this);
|
|
RemoveEffect("Crushing", this);
|
|
return;
|
|
}
|
|
|
|
public func FxInProductionTimer(object target, proplist effect, int time)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
public func FxCrushingTimer(object target, proplist effect, int time)
|
|
{
|
|
var dir = GetCalcDir();
|
|
var particles =
|
|
{
|
|
Prototype = Particles_WoodChip(),
|
|
R = 255,
|
|
G = 200,
|
|
B = 100
|
|
};
|
|
CreateParticle("Dust", PV_Random(11 * dir, 13 * dir), 40, PV_Random(-5, 5), PV_Random(-13, -6), PV_Random(36 * 3, 36 * 10), particles, 3);
|
|
|
|
return 1;
|
|
}
|
|
|
|
public func OnProductEjection(object product)
|
|
{
|
|
product->SetPosition(GetX() - 25 * GetCalcDir(), GetY() + 40);
|
|
product->SetSpeed(0, -17);
|
|
product->SetR(30 - Random(59));
|
|
Sound("Structures::EjectionPop");
|
|
return;
|
|
}
|
|
|
|
protected func RejectCollect(id item, object collect)
|
|
{
|
|
if (collect->~IsMillIngredient())
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
|
|
/*-- Properties --*/
|
|
|
|
local ActMap = {
|
|
Default = {
|
|
Prototype = Action,
|
|
Name = "Default",
|
|
Procedure = DFA_NONE,
|
|
Directions = 2,
|
|
//FlipDir = 1,
|
|
Length = 1,
|
|
Delay = 0,
|
|
FacetBase = 1,
|
|
NextAction = "Default",
|
|
},
|
|
};
|
|
|
|
protected func Definition(def)
|
|
{
|
|
SetProperty("PictureTransformation", Trans_Mul(Trans_Translate(2000, 0, 7000), Trans_Rotate(-20, 1, 0, 0), Trans_Rotate(30, 0, 1, 0)), def);
|
|
return _inherited(def, ...);
|
|
}
|
|
|
|
local ContainBlast = true;
|
|
local BlastIncinerate = 100;
|
|
local FireproofContainer = true;
|
|
local HitPoints = 70;
|
|
local Name = "$Name$";
|
|
local Description = "$Description$";
|
|
local Components = {Rock = 6, Wood = 2}; |