openclonk/planet/Objects.ocd/HUD.ocd/ProgressBar.ocd/RingProgressBar.ocd/Script.c

206 lines
3.5 KiB
C

/**
RingProgressBar
Shows progress.
additional data the bar takes through the "data" parameter:
radius: radius of the bar in pixels, the amount of points is dynamically adjusted
amount: number of segments in the ring, usually calculates form radius
*/
local Name = "$Name$";
local Description = "$Description$";
local maximum, current, timeout_time;
local my_angle;
local ring;
local ActMap=
{
Attach =
{
Prototype = Action,
Name="Attach",
Procedure=DFA_ATTACH,
NextAction="Be",
Length=1,
FacetBase=1,
AbortCall = "AttachTargetLost"
}
};
func Init(to, max, cur, timeout, offset, visibility, data)
{
maximum = max;
current = cur;
timeout_time = timeout;
ring = [];
if(timeout_time)
{
var e = AddEffect("TimeOut", this, 1, BoundBy(timeout_time/2, 5, 35), this);
e.t = timeout_time;
}
var radius = data.radius ?? 20;
var amount = data.amount ?? BoundBy(radius, 8, 30);
ring[0] = this;
for(var i = 1; i < amount; ++i)
ring[i] = CreateObject(GetID(), 0, 0, GetOwner());
var cnt = 0;
for(var obj in ring)
{
obj->Set(to, radius, ((cnt * 360) / amount), offset, visibility);
++cnt;
}
AddEffect("LifeCheck", to, 1, 0, this);
Update();
}
func FxLifeCheckStop(target, effect, cause, temp)
{
if(temp) return;
if(this)
this->RemoveObject();
}
func FxTimeOutTimer(target, effect, time)
{
effect.t -= effect.Interval;
if(effect.t > 0) return 1;
Close();
return -1;
}
func Update()
{
var l = GetLength(ring);
var p = (current * 100) / maximum;
var last_colored = (l * p) / 100;
for(var i = 0; i < l; ++i)
{
var obj = ring[i];
if(i > last_colored)
{
obj->SetClrModulation(RGBa(10, 10, 10, 200));
continue;
}
var p = (i * 100) / l;
var charge = (255 * p) / 100;
var r = 255, g = 255;
if(p > 50) r = BoundBy(255 - charge * 2, 0, 255);
if(p < 50) g = BoundBy(charge * 2, 0, 255);
obj->SetClrModulation(RGBa(r, g, 1, 200));
}
}
func Close()
{
RemoveObject();
}
func Destruction()
{
if(GetType(ring) == C4V_Array)
for(var i = GetLength(ring) - 1; i > 0; --i) // off-by-one on purpose
{
var obj = ring[i];
if(obj)
obj->RemoveObject();
}
}
func SetValue(int to)
{
current = BoundBy(to, 0, maximum);;
var e = GetEffect("TimeOut", this);
if(e)
e.t = timeout_time;
Update();
}
func DoValue(int change)
{
SetValue(current + change);
}
func Initialize()
{
}
func SetParallax(f)
{
f = f ?? true;
for(var obj in ring)
{
if(f)
{
obj->SetCategory(obj->GetCategory() | C4D_Parallax);
obj.Parallaxity = [0, 0];
}
else
{
obj->SetCategory(obj->GetCategory() & ~C4D_Parallax);
obj.Parallaxity = nil;
}
}
return true;
}
func SetPlane(int to)
{
if(to == nil) return;
for(var obj in ring)
{
obj.Plane = to;
}
return true;
}
func MakeHUDElement()
{
for(var obj in ring)
{
obj->SetCategory(C4D_StaticBack | C4D_IgnoreFoW | C4D_Foreground | C4D_Parallax);
}
SetParallax();
}
func AttachTargetLost()
{
return RemoveObject();
}
func Rotate (num r, num xoff, num yoff) {
var fsin=Sin(r, 1000), fcos=Cos(r, 1000);
// set matrix values
SetObjDrawTransform (
+fcos, +fsin, (1000-fcos)*xoff - fsin*yoff,
-fsin, +fcos, (1000-fcos)*yoff + fsin*xoff
);
}
func Set(to, distance, angle, offset, visibility)
{
SetAction("Attach", to);
var x = -Sin(angle, distance) - offset.x;
var y = +Cos(angle, distance) - offset.y;
SetPosition(GetX() - x, GetY() - y + 8); // for good position in first frame
SetVertexXY(0, x + to->GetVertex(0, VTX_X), y + to->GetVertex(0, VTX_Y));
my_angle = -angle;
Rotate(my_angle, 0, 0);
this.Visibility = visibility;
}