openclonk/planet/System.ocg/Commits.c

367 lines
8.5 KiB
C

/*--
Commits.c
Authors: flgr, Joern, Tyron, Newton, Ringwaul, Sven2, Maikel
Useful user committed functions, this should really be organized into more sensible categories.
--*/
// Returns the offset to x.
global func AbsX(int x)
{
return x - GetX();
}
// Returns the offset to y.
global func AbsY(int y)
{
return y - GetY();
}
// Supports negative values, and can deliver random values between two bounds.
global func RandomX(int start, int end)
{
var swap;
// Values swapped: reswap them.
if (start > end)
{
swap = start;
start = end;
end = swap;
}
// Return random factor.
return Random(end - start + 1) + start;
}
// Tangens.
global func Tan(int angle, int radius, int prec)
{
return radius * Sin(angle, radius * 100, prec) / Cos(angle, radius * 100, prec);
}
global func Normalize(int angle, int start, int precision)
{
if (!precision)
precision = 1;
var end = precision * 360 + start;
while (angle < start)
angle += precision * 360;
while (angle >= end)
angle -= precision * 360;
return angle;
}
// Does not set the speed of an object. But you can set two components of the velocity vector with this function.
global func SetSpeed(int x_dir, int y_dir, int prec)
{
SetXDir(x_dir, prec);
SetYDir(y_dir, prec);
return;
}
// Sets an objects's speed and its direction, doesn't it?
global func SetVelocity(int angle, int speed, int precAng, int precSpd)
{
if(!precAng) precAng = 1;
var x_dir = Sin(angle, speed, precAng);
var y_dir = -Cos(angle, speed, precAng);
SetXDir(x_dir, precSpd);
SetYDir(y_dir, precSpd);
return;
}
// Sets the completion of this to new_con.
global func SetCon(int new_con)
{
return DoCon(new_con - GetCon());
}
// Adds value to the account of iPlayer.
global func DoWealth(int plr, int value)
{
return SetWealth(plr, value + GetWealth(plr));
}
// Sets both the X and Y-coordinate of one vertex.
global func SetVertexXY(int index, int x, int y)
{
// Set vertices.
SetVertex(index, VTX_X, x);
SetVertex(index, VTX_Y, y);
return;
}
// Returns the number of stuck vertices. (of this)
global func VerticesStuck()
{
var vertices = 0;
// Loop through vertices.
for (var i = -1; i < GetVertexNum(); i++)
// Solid?
if (GBackSolid(GetVertex(i, VTX_X), GetVertex(i, VTX_Y)))
// Count vertices.
vertices++;
return vertices;
}
// Creates amount objects of type id inside the indicated rectangle(optional) in the indicated material.
// Returns the number of iterations needed, or -1 when the placement failed.
global func PlaceObjects(id id, int amount, string mat_str, int x, int y, int wdt, int hgt, bool onsf, bool nostuck)
{
var i, j;
var rndx, rndy, obj;
var mtype, mat;
var func, objhgt = id->GetDefCoreVal("Height", "DefCore");
mat = Material(mat_str);
// Some failsavety.
if (mat == -1)
if (mat_str != "GBackSolid" && mat_str != "GBackSemiSolid" && mat_str != "GBackLiquid" && mat_str != "GBackSky")
return -1;
// Optional parameters wdt and hgt.
if (!wdt)
wdt = LandscapeWidth() - x - GetX();
if (!hgt)
hgt = LandscapeHeight() - y - GetY();
// Cycle-saving method.
if (mat != -1)
while (i < amount)
{
// If there's isn't any or not enough of the given material, break before it gets an endless loop.
if (j++ > 20000)
return -1;
// Destinated rectangle.
rndx = x + Random(wdt);
rndy = y + Random(hgt);
// Positioning.
if (GetMaterial(rndx, rndy) == mat)
{
// On-surface option.
if (onsf)
while (GBackSemiSolid(rndx, rndy) && rndy >= y)
rndy--;
if (rndy < y)
continue;
// Create and verify stuckness.
obj = CreateObject(id, rndx, rndy + objhgt / 2, NO_OWNER);
obj->SetR(Random(360));
if (obj->Stuck() || nostuck)
i++;
else
obj->RemoveObject();
}
}
if (mat == -1)
while (i < amount)
{
// If there's isn't any or not enough of the given material, break before it gets an endless loop.
if (j++ > 20000)
return -1;
// Destinated rectangle.
rndx = x + Random(wdt);
rndy = y + Random(hgt);
// Positioning.
if (eval(Format("%s(%d,%d)", mat_str, rndx, rndy)))
{
// On-surface Option.
if (onsf)
while (GBackSemiSolid(rndx, rndy) && rndy >= y)
rndy--;
if (rndy < y)
continue;
// Create and verify stuckness.
obj = CreateObject(id, rndx, rndy + objhgt / 2, NO_OWNER);
obj->SetR(Random(360));
if (obj->Stuck() || nostuck)
i++;
else
obj->RemoveObject();
}
}
return j;
}
global func CastObjects(id def, int am, int lev, int x, int y, int angs, int angw)
{
if (!angw)
angw = 360;
for (var i = 0; i < am; i++)
{
var obj = CreateObject(def , x, y, NO_OWNER);
var ang = angs - 90 + RandomX(-angw / 2, angw / 2);
var xdir = Cos(ang, lev) + RandomX(-3, 3);
obj->SetR(Random(360));
obj->SetXDir(xdir);
obj->SetYDir(Sin(ang, lev) + RandomX(-3, 3));
if(xdir != 0) obj->SetRDir((10 + Random(21)) * (xdir / Abs(xdir)));
else
obj->SetRDir(-10 + Random(21));
}
return;
}
global func CastPXS(string mat, int am, int lev, int x, int y, int angs, int angw)
{
if (!angw)
angw = 360;
for (var i = 0; i < am; i++)
{
var ang = angs - 90 + RandomX(-angw / 2, angw / 2);
InsertMaterial(Material(mat), x, y, Cos(ang, lev) + RandomX(-3, 3), Sin(ang, lev) + RandomX(-3, 3));
}
return;
}
global func CheckVisibility(int plr)
{
var visible = this["Visibility"];
if (GetType(visible) == C4V_Array)
visible = visible[0];
// Not visible at all.
if (visible == VIS_None)
return false;
// Visible for all.
if (visible == VIS_All)
return true;
// Object is owned by the indicated player.
if (GetOwner() == plr)
{
if (visible & VIS_Owner)
return true;
}
// Object belongs to a player, hostile to plr.
else if (Hostile(GetOwner(), plr))
{
if (visible & VIS_Enemies)
return true;
}
// Object belongs to a player, friendly to plr.
else
{
if (visible & VIS_Allies)
return true;
}
if (visible & VIS_Select)
if (this["Visibility"][1 + plr / 32] & 1 << plr)
return true;
return false;
}
global func MaterialDepthCheck(int x, int y, string mat, int depth)
{
var travelled;
var xval = x;
var yval = y;
//If depth is equal to zero, the function will always measure the depth of the material.
//If depth is not equal to zero, the function will return true if the material is as deep or deeper than depth (in pixels).
if (depth == nil)
depth = LandscapeHeight();
while (travelled != depth)
{
if (GetMaterial(xval, yval) == Material(mat))
{
travelled++;
yval++;
}
if (GetMaterial(xval, yval) != Material(mat))
return travelled; // Returns depth of material.
}
if (travelled == depth)
return true;
return false;
}
global func LaunchProjectile(int angle, int dist, int speed, int x, int y, bool rel_x)
{
// dist: Distance object travels on angle. Offset from calling object.
// x: X offset from container's center
// y: Y offset from container's center
// rel_x: if true, makes the X offset relative to container direction. (x=+30 will become x=-30 when Clonk turns left. This way offset always stays in front of a Clonk.)
var x_offset = Sin(angle, dist);
var y_offset = -Cos(angle, dist);
if (Contained() != nil && rel_x == true)
if (Contained()->GetDir() == 0)
x = -x;
if (Contained() != nil)
{
Exit(x_offset + x, y_offset + y, angle);
SetVelocity(angle, speed);
return true;
}
if (Contained() == nil)
{
SetPosition(GetX() + x_offset + x, GetY() + y_offset + y);
SetR(angle);
SetVelocity(angle, speed);
return true;
}
return false;
}
global func ComDirLike(int comdir1, int comdir2)
{
if (comdir1 == comdir2)
return true;
if (comdir1 == COMD_Stop || comdir2 == COMD_Stop)
return false;
if (comdir1 == COMD_None || comdir2 == COMD_None)
return false;
if (comdir1 % 8 + 1 == comdir2)
return true;
if (comdir1 == comdir2 % 8 + 1)
return true;
return false;
}
global func SetObjAlpha(int by_alpha)
{
var clr_mod = GetClrModulation();
if (!clr_mod)
clr_mod = by_alpha << 24;
else
clr_mod = clr_mod & 16777215 | by_alpha << 24;
return SetClrModulation(clr_mod);
}
global func FindPosInMat(string sMat, int iXStart, int iYStart, int iWidth, int iHeight, int iSize)
{
var iX, iY;
var iMaterial = Material(sMat);
for(var i = 0; i < 500; i++)
{
iX = AbsX(iXStart+Random(iWidth));
iY = AbsY(iYStart+Random(iHeight));
if(GetMaterial(iX,iY)==iMaterial &&
GetMaterial(iX+iSize,iY+iSize)==iMaterial &&
GetMaterial(iX+iSize,iY-iSize)==iMaterial &&
GetMaterial(iX-iSize,iY-iSize)==iMaterial &&
GetMaterial(iX-iSize,iY+iSize)==iMaterial
) {
return [iX, iY]; // Location found.
}
}
return 0; // No location found.
}