openclonk/planet/Objects.ocd/Items.ocd/Resources.ocd/Diamond.ocd/Socket.ocd/Script.c

199 lines
4.5 KiB
C

/**
Diamond Socket
Contains a valuable diamond that can be freed using a pickaxe.
*/
local Name = "$Name$";
local Description = "$Description$";
local attached_mesh;
local last_free;
local mat_color;
public func Place(int amount, proplist area)
{
area = area ?? Shape->LandscapeRectangle();
var failsafe = amount * 100;
while((amount > 0) && (--failsafe > 0))
{
// select cluster
var c_size = Min(5 + RandomX(-1, 1), amount);
// look for random in-earth position
var failsafe2 = 500;
var pt = {};
while (--failsafe2)
{
if (!area->GetRandomPoint(pt)) break;
if(!GBackSolid(pt.x, pt.y)) continue;
// must be diggable
var mat = GetMaterial(pt.x, pt.y);
if(!GetMaterialVal("DigFree","Material",mat)) continue;
break;
}
if(failsafe2 <= 0) continue;
// color of cluster
var hsl = HSL(Random(255), 50, 150);
var r2 = (hsl >> 16) & 0xff;
var g2 = (hsl >> 8) & 0xff;
var b2 = (hsl >> 0) & 0xff;
// we have a position now!
failsafe2 = 50;
var i = 0;
while ((i < c_size) && (--failsafe2 > 0))
{
var mx = pt.x + RandomX(-20, 20);
var my = pt.y + RandomX(-20, 20);
if (!GBackSolid(mx, my)) continue;
var mat = GetMaterial(mx, my);
if (!GetMaterialVal("DigFree","Material",mat)) continue;
if (FindObject(Find_Distance(8, mx, my), Find_ID(this))) continue;
++i;
var socket = CreateObject(this, mx, my, NO_OWNER);
socket->Set(r2, g2, b2);
}
amount -= i;
}
}
public func Construction()
{
var tex = GetTexture(0, 0);
if (tex)
{
mat_color = GetAverageTextureColor(tex);
}
else
{
mat_color = RGB(100, 50, 5);
}
last_free = false;
var contents = CreateContents(Diamond);
contents->SetObjectBlitMode(GFX_BLIT_Mod2);
this.MeshTransformation = Trans_Rotate(90, 1, 0, 0);
attached_mesh = AttachMesh(contents, "main", "main", Trans_Mul(Trans_Rotate(Random(360), 1, 0, 0)));
SetR(Random(360));
this.Visibility = VIS_None;
AddTimer("CheckFree", 100 + Random(10));
// Random color for now. The Place() function will create groups of the same color.
Set(Random(255), Random(255), Random(255));
}
public func Set(int r, int g, int b)
{
var contents = Contents(0);
if (contents)
contents->SetClrModulation(RGB(r, g, b), 0);
}
public func DugOut(object clonk)
{
// For instant appearance
return CheckFree(true);
}
private func CheckFree(bool by_dig_free)
{
if (GBackSolid() == last_free)
{
last_free = !last_free;
if (!last_free)
{
this.Visibility = VIS_None;
if (!Contents()) return RemoveObject();
}
else
{
// Look what's appearing behind the dust!
DugOutDust();
// One shiny burst because MuchSparkle is a bit thin sometims
var particles =
{
Size = PV_Step(5, 5),
Stretch = PV_Step(2),
BlitMode = GFX_BLIT_Additive,
Alpha = PV_Linear(255, 0),
Rotation = Random(360)
};
CreateParticle("StarSpark", 0, 0, 0, 0, 10, particles);
// And some extra sparkling in the future
AddEffect("MuchSparkle", this, 1, 1, this);
this.Visibility = VIS_All;
// Also, some sound (delayed for audibility on visibility change)
if (by_dig_free) ScheduleCall(this, Global.Sound, 1,1, "Objects::DiamondDigOut");
}
}
if (!Random(20))
Sparkle();
if (last_free && !Random(3))
Sparkle();
return true;
}
private func FxMuchSparkleTimer(target, fx, time)
{
if (time > Random(90)) return -1;
if (Random(3)) return;
Sparkle();
}
private func Sparkle()
{
var r = Random(360);
var particles =
{
Size = PV_Step(1, 1, 0),
Stretch = PV_Step(2),
BlitMode = GFX_BLIT_Additive,
Alpha = PV_Linear(255, 0),
Rotation = r
};
var x = RandomX(-3, 3);
var y = RandomX(-3, 3);
CreateParticle("StarSpark", x, y, 0, 0, 10 + Random(20), particles);
CreateParticle("StarSpark", x, y, 0, 0, 10 + Random(20), {Prototype = particles, Rotation = r + 90});
}
private func DugOutDust()
{
var particles =
{
Prototype = Particles_Colored(Particles_Dust(), mat_color),
ForceY = PV_Gravity(100),
DampingX = 750, DampingY = 750,
Size = PV_KeyFrames(0, 0, 2, 100, 10, 1000, 4),
Alpha = PV_KeyFrames(0, 0, 0, 100, 100, 1000, 0),
OnCollision = PC_Die()
};
CreateParticle("Dust", 0, 0, PV_Random(-40, 40), PV_Random(-40, 40), PV_Random(10, 60), particles, 40 + Random(20));
}
public func OnHitByPickaxe()
{
var c = Contents();
if(!c) return;
if(Random(3)) return;
Sound("Hits::Materials::Rock::RockHit*");
DetachMesh(attached_mesh);
c->Exit(0, 0, 0, RandomX(-3, 3), RandomX(-3, -1), RandomX(-20, 20));
}
public func CanBeHitByPickaxe()
{
return !!Contents();
}