forked from Mirrors/openclonk
217 lines
5.1 KiB
C
217 lines
5.1 KiB
C
/*--
|
|
Helpers.c
|
|
Authors:
|
|
|
|
Some useful helper functions.
|
|
--*/
|
|
|
|
// the shortest direction (left/right) to turn from one angle to another
|
|
// (for example for homing projectiles or aiming)
|
|
global func GetTurnDirection(int from, int to)
|
|
{
|
|
var dir;
|
|
/*if(to < from)*/dir=to-from;
|
|
//else dir=from-to;
|
|
|
|
var dif=360-from+to;
|
|
var dif2=360-to+from;
|
|
if(dif < 180)dir=+dif;
|
|
else
|
|
if(dif2 < 180)dir=-dif2;
|
|
|
|
return dir;
|
|
}
|
|
|
|
global func MessageWindow(string msg, int for_plr, id icon, string caption)
|
|
{
|
|
// Get icon.
|
|
if (!icon)
|
|
icon = GetID();
|
|
// Get caption.
|
|
if (!caption)
|
|
caption = GetName();
|
|
// Create msg window (menu).
|
|
var cursor = GetCursor(for_plr);
|
|
if (!cursor->CreateMenu(icon, cursor, 0, caption, 0, 2))
|
|
return false;
|
|
cursor->AddMenuItem(caption, nil, nil, 0, 0, msg);
|
|
return true;
|
|
}
|
|
|
|
global func RemoveAll(p)
|
|
{
|
|
var cnt;
|
|
if (GetType(p) == C4V_PropList) p = Find_ID(p); // RemoveAll(ID) shortcut
|
|
for (var obj in FindObjects(p, ...))
|
|
{
|
|
if (obj)
|
|
{
|
|
obj->RemoveObject();
|
|
cnt++;
|
|
}
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
global func SetBit(int old_val, int bit_nr, bool bit)
|
|
{
|
|
if (GetBit(old_val, bit_nr) != (bit != 0))
|
|
return ToggleBit(old_val, bit_nr);
|
|
return old_val;
|
|
}
|
|
|
|
global func GetBit(int value, int bit_nr)
|
|
{
|
|
return (value & (1 << bit_nr)) != 0;
|
|
}
|
|
|
|
global func ToggleBit(int old_val, int bit_nr)
|
|
{
|
|
return old_val ^ (1 << bit_nr);
|
|
}
|
|
|
|
global func DrawParticleLine (string particle, int x0, int y0, int x1, int y1, int prtdist, int a, int b0, int b1, int ydir)
|
|
{
|
|
// Right parameters?
|
|
if (!prtdist)
|
|
return 0;
|
|
// Calculate required number of particles.
|
|
var prtnum = Max(Distance(x0, y0, x1, y1) / prtdist, 2);
|
|
var i = prtnum;
|
|
// Create particles.
|
|
while (i >= 0)
|
|
{
|
|
var i1, i2, b;
|
|
i2 = i * 256 / prtnum;
|
|
i1 = 256 - i2;
|
|
|
|
b = ((b0 & 16711935) * i1 + (b1 & 16711935) * i2) >> 8 & 16711935
|
|
| ((b0 >> 8 & 16711935) * i1 + (b1 >> 8 & 16711935) * i2) & -16711936;
|
|
if (!b && (b0 | b1))
|
|
b++;
|
|
CreateParticle(particle, x0 + (x1 - x0) * i / prtnum, y0 + (y1 - y0) * i-- / prtnum, 0, ydir, a, b);
|
|
}
|
|
// Succes, return number of created particles.
|
|
return prtnum;
|
|
}
|
|
|
|
// Searches for an object, which can be obtained with the Acquire command.
|
|
global func GetAvailableObject (id def, object obj)
|
|
{
|
|
var crit = Find_And(Find_OCF(OCF_Available),
|
|
Find_InRect(-500, -250, 1000, 500),
|
|
Find_ID(def),
|
|
Find_OCF(OCF_Fullcon),
|
|
Find_Not(Find_OCF(OCF_OnFire)),
|
|
Find_Func("GetAvailableObjectCheck", GetOwner()),
|
|
Find_Not(Find_Container(obj)));
|
|
if (!obj)
|
|
SetLength(crit, GetLength(crit) - 1);
|
|
return FindObject(crit, Sort_Distance());
|
|
}
|
|
|
|
global func GetAvailableObjectCheck(int plr)
|
|
{
|
|
// Object is not connected to anything (for line construction kits)
|
|
if (FindObject (Find_ActionTarget(this), Find_Procedure(DFA_CONNECT)))
|
|
return false;
|
|
// Not chosen by another friendly clonk
|
|
var eff =GetEffect("IntNotAvailable", this);
|
|
if (eff && !Hostile(plr, eff.clonk->GetOwner()))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// Sets the MaxEnergy value of an object and does the necessary callbacks.
|
|
global func SetMaxEnergy(int value)
|
|
{
|
|
if (!this)
|
|
return;
|
|
value *= 1000;
|
|
var old_maxenergy = this.MaxEnergy;
|
|
this.MaxEnergy = value;
|
|
// Change current energy percentage wise and implicit callback.
|
|
DoEnergy(GetEnergy() * (value - old_maxenergy) / old_maxenergy);
|
|
return;
|
|
}
|
|
|
|
// Returns the MaxEnergy value of an object.
|
|
global func GetMaxEnergy()
|
|
{
|
|
if (!this)
|
|
return;
|
|
return this.MaxEnergy / 1000;
|
|
}
|
|
|
|
// Sets the MaxBreath value of an object and does the necessary callbacks.
|
|
global func SetMaxBreath(int value)
|
|
{
|
|
if (!this)
|
|
return;
|
|
var old_maxbreath = this.MaxBreath;
|
|
this.MaxBreath = value;
|
|
// Change current breath percentage wise and implicit callback.
|
|
DoBreath(GetBreath() * (value - old_maxbreath) / old_maxbreath);
|
|
return;
|
|
}
|
|
|
|
// Returns the MaxBreath value of an object.
|
|
global func GetMaxBreath()
|
|
{
|
|
if (!this)
|
|
return;
|
|
return this.MaxBreath;
|
|
}
|
|
|
|
// Makes an object gain Con until it is FullCon
|
|
global func StartGrowth(int value)
|
|
{
|
|
return AddEffect("IntGrowth", this, 1, 35, nil, nil, value);
|
|
}
|
|
|
|
global func StopGrowth()
|
|
{
|
|
return RemoveEffect("IntGrowth", this);
|
|
}
|
|
|
|
global func FxIntGrowthStart(object obj, effect, int temporary, int value)
|
|
{
|
|
if (!temporary) effect.growth = value;
|
|
}
|
|
|
|
global func FxIntGrowthTimer(object obj, effect)
|
|
{
|
|
if (obj->OnFire()) return;
|
|
obj->DoCon(effect.growth, 1000);
|
|
var done = obj->GetCon(1000) >= 1000;
|
|
return -done;
|
|
}
|
|
|
|
global func StonyObjectHit(int x, int y)
|
|
{
|
|
// Failsafe
|
|
if (!this) return false;
|
|
var xdir = GetXDir(), ydir = GetYDir();
|
|
if(x) x = x / Abs(x);
|
|
if(y) y = y / Abs(y);
|
|
// Check for solid in hit direction
|
|
var i = 0;
|
|
var average_obj_size = Distance(0,0, GetObjWidth(), GetObjHeight()) / 2 + 2;
|
|
while(!GBackSolid(x*i, y*i) && i < average_obj_size) i++;
|
|
// To catch some high speed cases: if no solid found, check directly beneath
|
|
if (!GBackSolid(x*i, y*i))
|
|
{
|
|
x = 0;
|
|
y = 1;
|
|
i = 0;
|
|
while(!GBackSolid(x*i, y*i) && i < average_obj_size) i++;
|
|
}
|
|
// Check if digfree
|
|
if (!GetMaterialVal("DigFree", "Material", GetMaterial(x*i, y*i)) && GBackSolid(x*i, y*i))
|
|
return Sound("RockHit?");
|
|
// Else play standard sound
|
|
if (Distance(0,0,xdir,ydir) > 10)
|
|
return Sound("SoftTouch?");
|
|
else
|
|
return Sound("SoftHit?");
|
|
} |