1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
|
/**
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};
|