forked from Mirrors/openclonk
added item spawning functionality and better effect for meteor; added alien meteor skin
squashed: -Made meteor particle effect awesome --Slight changes to rotation of Alien meteor and particles -cleaned up alien meteor and merged item spawning functionality into normal meteor -Fixed AlienMeteor spawn chance -Changed AlienMeteor visuals slightly -Made AlienMeteor Particles even better C: -WIP: Alien meteor + particlesControls
parent
38806f4c0b
commit
6257d9d6be
|
@ -163,4 +163,10 @@ private func Hatch()
|
|||
PV_Random(10, 20), particles, 60);
|
||||
RemoveObject();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If spawned via a meteor, use a cool green skin.
|
||||
public func GetMeteorSkin()
|
||||
{
|
||||
return Meteor_Alien;
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
|
@ -0,0 +1,3 @@
|
|||
[Particle]
|
||||
Name=BlueFire
|
||||
Face=0,0,64,64,-32,-32
|
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
|
@ -0,0 +1,3 @@
|
|||
[Particle]
|
||||
Name=BlueFireTrail
|
||||
Face=0,0,256,256,-128,-218
|
|
@ -0,0 +1,14 @@
|
|||
[DefCore]
|
||||
id=Meteor_Alien
|
||||
Version=6,0
|
||||
Category=C4D_Object|C4D_Environment
|
||||
Width=27
|
||||
Height=41
|
||||
Offset=-13,-20
|
||||
Vertices=4
|
||||
VertexX=-7,-7,7,7
|
||||
VertexY=-7,7,-7,7
|
||||
VertexFriction=50,50,50,50
|
||||
Rotate=1
|
||||
NoStabilize=1
|
||||
StretchGrowth=1
|
Binary file not shown.
|
@ -0,0 +1,27 @@
|
|||
material AlienMeteoriteMat: NormalMap
|
||||
{
|
||||
receive_shadows off
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
ambient 1.0 1.0 1.0 1.0
|
||||
diffuse 1.0 1.0 1.0 1.0
|
||||
specular 0.25 0.25 0.25 1.0 12.5
|
||||
emissive 0.0 0.0 0.0 1.0
|
||||
|
||||
texture_unit base
|
||||
{
|
||||
texture meteorite.png
|
||||
tex_address_mode wrap
|
||||
filtering trilinear
|
||||
}
|
||||
|
||||
texture_unit normal
|
||||
{
|
||||
texture meteorite_normals.png
|
||||
tex_address_mode wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
Alien Meteor Skin
|
||||
A new meteorite skin that can f.e. be used when spawning aliens.
|
||||
|
||||
@author Win
|
||||
*/
|
||||
|
||||
#include Meteor
|
||||
|
||||
public func OnAfterLaunch()
|
||||
{
|
||||
// Adjust rotation to point into movement direction.
|
||||
// You can't do this unless you also change the rotation of the trail -Win
|
||||
//SetR(Angle(0, 0, GetXDir(), GetYDir()));
|
||||
// Emits light
|
||||
SetLightRange(400, 100);
|
||||
SetLightColor(RGB(100, 254, 255));
|
||||
// Add particle effects.
|
||||
AddEffect("IntMeteor", this, 100, 1, this);
|
||||
}
|
||||
|
||||
private func FxIntMeteorStart(object target, effect fx, bool temp)
|
||||
{
|
||||
if (temp) return;
|
||||
fx.fire =
|
||||
{
|
||||
R = 255,
|
||||
B = 255,
|
||||
G = 255,
|
||||
Alpha = PV_Linear(255,0),
|
||||
Size = PV_Linear(30,150),
|
||||
Stretch = 1000,
|
||||
Phase = 0,
|
||||
Rotation = PV_Random(-GetR() - 15, -GetR() + 15),
|
||||
DampingX = 1000,
|
||||
DampingY = 1000,
|
||||
BlitMode = GFX_BLIT_Additive,
|
||||
CollisionVertex = 0,
|
||||
OnCollision = PC_Die(),
|
||||
Attach = nil
|
||||
};
|
||||
fx.sparkright =
|
||||
{
|
||||
R = 255,
|
||||
B = 255,
|
||||
G = 255,
|
||||
Alpha = PV_KeyFrames(0, 0, 0, 500, 255, 1000, 0),
|
||||
Size = PV_Linear(20,100),
|
||||
Stretch = 1000,
|
||||
Phase = 0,
|
||||
Rotation = 30,
|
||||
ForceX = 0,
|
||||
ForceY = 0,
|
||||
DampingX = 1000,
|
||||
DampingY = 1000,
|
||||
BlitMode = GFX_BLIT_Additive,
|
||||
CollisionVertex = 0,
|
||||
OnCollision = PC_Die(),
|
||||
Attach = ATTACH_Back | ATTACH_MoveRelative
|
||||
};
|
||||
fx.sparkleft =
|
||||
{
|
||||
Prototype = fx.sparkright,
|
||||
Size = PV_Linear(30,100),
|
||||
Rotation = -30,
|
||||
};
|
||||
fx.trail =
|
||||
{
|
||||
R = 255,
|
||||
B = 255,
|
||||
G = 255,
|
||||
Alpha = PV_Linear(255,0),
|
||||
Size = GetCon()/3,
|
||||
Stretch = 1000,
|
||||
Phase = 0,
|
||||
Rotation = 0,
|
||||
ForceX = 0,
|
||||
ForceY = 0,
|
||||
DampingX = 1000,
|
||||
DampingY = 1000,
|
||||
BlitMode = GFX_BLIT_Additive,
|
||||
CollisionVertex = 0,
|
||||
OnCollision = PC_Die(),
|
||||
Attach = ATTACH_Front | ATTACH_MoveRelative
|
||||
};
|
||||
}
|
||||
|
||||
private func FxIntMeteorTimer(object target, effect fx)
|
||||
{
|
||||
var size = GetCon();
|
||||
// Air drag.
|
||||
var ydir = GetYDir(100);
|
||||
ydir -= size * ydir ** 2 / 11552000; // Magic number.
|
||||
SetYDir(ydir, 100);
|
||||
|
||||
// Fire trail.
|
||||
fx.fire.ForceX = -GetXDir()/2 + RandomX(-5,5);
|
||||
fx.fire.ForceY = -GetYDir()/2;
|
||||
CreateParticle("BlueFireTrail", PV_Random(-1, 1), -15, 0, -GetYDir(), 7, fx.trail, 1);
|
||||
|
||||
CreateParticle("BlueSpark", 10, 15, 100 + GetXDir(), -GetYDir(), 20, fx.sparkright, 1);
|
||||
CreateParticle("BlueSpark", -10, 15, -100 + GetXDir(), -GetYDir(), 20, fx.sparkleft, 1);
|
||||
CreateParticle("BlueFire", PV_Random(-8, 8), PV_Random(-15, -35), 0, 0, 30, fx.fire, 4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-- Proplist --*/
|
||||
|
||||
local Name = "$Name$";
|
|
@ -0,0 +1 @@
|
|||
Name=Alienmeteor
|
|
@ -0,0 +1 @@
|
|||
Name=Alien Meteor
|
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
|
@ -2,65 +2,102 @@
|
|||
Meteor
|
||||
A burning rock falling from the sky, explodes on impact.
|
||||
|
||||
@author Maikel
|
||||
@author Maikel, Zapper
|
||||
*/
|
||||
|
||||
// A meteor can spawn objects on impact.
|
||||
local spawn_id, spawn_amount;
|
||||
|
||||
/*-- Disaster Control --*/
|
||||
|
||||
public func SetChance(int chance)
|
||||
/**
|
||||
Enables meteorites.
|
||||
The meteorites can be set to spawn objects on impact. The amount to spawn will be spawn_amount randomized by 50%.
|
||||
*/
|
||||
public func SetChance(int chance, id spawn_id, int spawn_amount)
|
||||
{
|
||||
if (this != Meteor)
|
||||
return;
|
||||
var effect = GetEffect("IntMeteorControl");
|
||||
spawn_amount = spawn_amount ?? 1;
|
||||
if (GetType(this) != C4V_Def) return FatalError("Must be called as a definition call.");
|
||||
|
||||
var effect = FindMeteoriteEffectFor(spawn_id);
|
||||
if (!effect)
|
||||
effect = AddEffect("IntMeteorControl", nil, 100, 20, nil, Meteor);
|
||||
effect = AddEffect("IntMeteorControl", nil, 100, 20, nil, this, spawn_id, spawn_amount);
|
||||
effect.chance = chance;
|
||||
return;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public func GetChance()
|
||||
/**
|
||||
Returns the chance of meteorites that is currently set. spawn_id can be nil for the normal meteorite.
|
||||
*/
|
||||
public func GetChance(id spawn_id)
|
||||
{
|
||||
if (this != Meteor)
|
||||
return;
|
||||
var effect = GetEffect("IntMeteorControl");
|
||||
if (GetType(this) != C4V_Def) return FatalError("Must be called as a definition call.");
|
||||
var effect = FindMeteoriteEffectFor(spawn_id);
|
||||
if (effect)
|
||||
return effect.chance;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected func FxIntMeteorControlTimer(object target, proplist effect, int time)
|
||||
// Finds the meteorite effect that matches a specific spawn id.
|
||||
private func FindMeteoriteEffectFor(id spawn_id)
|
||||
{
|
||||
if (Random(100) < effect.chance && !Random(10))
|
||||
var i = 0, fx;
|
||||
while (fx = GetEffect("IntMeteorControl", nil, i++))
|
||||
{
|
||||
if (fx.spawn_id == spawn_id) return fx;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
private func FxIntMeteorControlStart(object target, effect fx, temp, id spawn_id, int spawn_amount)
|
||||
{
|
||||
if (temp) return;
|
||||
fx.spawn_id = spawn_id;
|
||||
fx.spawn_amount = spawn_amount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private func FxIntMeteorControlTimer(object target, effect fx, int time)
|
||||
{
|
||||
if (Random(100) < fx.chance && !Random(10))
|
||||
{
|
||||
// Launch a meteor.
|
||||
var meteor = CreateObjectAbove(Meteor);
|
||||
var x = Random(LandscapeWidth());
|
||||
var y = 0;
|
||||
var size = RandomX(60, 90);
|
||||
var xdir = RandomX(-22, 22);
|
||||
var ydir = RandomX(28, 36);
|
||||
meteor->Launch(x, y, size, xdir, ydir);
|
||||
var real_spawn_amount = Max(1, RandomX(fx.spawn_amount / 2, 3 * fx.spawn_amount / 2));
|
||||
LaunchMeteor(x, y, size, xdir, ydir, fx.spawn_id, real_spawn_amount);
|
||||
}
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
// Scenario saving
|
||||
func FxIntMeteorControlSaveScen(obj, fx, props)
|
||||
public func FxIntMeteorControlSaveScen(obj, fx, props)
|
||||
{
|
||||
props->Add("Meteor", "Meteor->SetChance(%d)", fx.chance);
|
||||
props->Add("Meteor", "Meteor->SetChance(%d, %v, %d)", fx.chance, fx.spawn_id, fx.spawn_amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
global func LaunchMeteor(int x, int y, int size, int xdir, int ydir)
|
||||
/**
|
||||
Launches a meteor.
|
||||
The meteor can spawn objects via spawn_id.
|
||||
*/
|
||||
global func LaunchMeteor(int x, int y, int size, int xdir, int ydir, id spawn_id, int spawn_amount)
|
||||
{
|
||||
var meteor = CreateObjectAbove(Meteor);
|
||||
return meteor->Launch(x, y, size, xdir, ydir);
|
||||
var meteor_skin = Meteor;
|
||||
if (spawn_id) meteor_skin = spawn_id->~GetMeteorSkin() ?? meteor_skin;
|
||||
|
||||
var meteor = CreateObject(meteor_skin);
|
||||
return meteor->Launch(x, y, size, xdir, ydir, spawn_id, spawn_amount);
|
||||
}
|
||||
|
||||
/*-- Meteor --*/
|
||||
|
||||
public func Launch(int x, int y, int size, int xdir, int ydir)
|
||||
public func Launch(int x, int y, int size, int xdir, int ydir, id spawn_id, int spawn_amount)
|
||||
{
|
||||
// Launch from indicated position.
|
||||
SetPosition(x, y);
|
||||
|
@ -69,15 +106,27 @@ public func Launch(int x, int y, int size, int xdir, int ydir)
|
|||
// Set the initial velocity.
|
||||
SetXDir(xdir);
|
||||
SetYDir(ydir);
|
||||
// Set random rotation.
|
||||
SetR(Random(360));
|
||||
SetRDir(RandomX(-10, 10));
|
||||
// Remember spawning information.
|
||||
this.spawn_id = spawn_id;
|
||||
this.spawn_amount = spawn_amount ?? 1;
|
||||
// Safety check.
|
||||
if (!IsLaunchable())
|
||||
return false;
|
||||
// Allow for some more effects (overloadable).
|
||||
this->OnAfterLaunch();
|
||||
return true;
|
||||
}
|
||||
|
||||
public func OnAfterLaunch()
|
||||
{
|
||||
// Set random rotation.
|
||||
SetR(Random(360));
|
||||
SetRDir(RandomX(-10, 10));
|
||||
// Emit light
|
||||
SetLightRange(300, 100);
|
||||
SetLightColor(RGB(100, 230, 120));
|
||||
// Set right action.
|
||||
AddEffect("IntMeteor", this, 100, 1, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
private func IsLaunchable()
|
||||
|
@ -90,7 +139,55 @@ private func IsLaunchable()
|
|||
return true;
|
||||
}
|
||||
|
||||
protected func FxIntMeteorTimer()
|
||||
private func FxIntMeteorStart(object target, effect fx, bool temp)
|
||||
{
|
||||
if (temp) return;
|
||||
fx.smoketrail =
|
||||
{
|
||||
R = 255,
|
||||
B = PV_KeyFrames(0, 0,100, 30,0, 100,255, 1000,255),
|
||||
G = PV_KeyFrames(0, 0,150, 30,0, 100,255, 1000,255),
|
||||
|
||||
Alpha = PV_KeyFrames(1000, 0, 0, 30, 255, 1000, 0),
|
||||
Size = PV_Linear(20,60),
|
||||
Stretch = 1000,
|
||||
Phase = PV_Random(0,4),
|
||||
Rotation = PV_Random(-GetR() - 15, -GetR() + 15),
|
||||
DampingX = 1000,
|
||||
DampingY = 1000,
|
||||
BlitMode = 0,
|
||||
CollisionVertex = 0,
|
||||
OnCollision = PC_Stop(),
|
||||
Attach = nil
|
||||
};
|
||||
fx.brighttrail =
|
||||
{
|
||||
Prototype = fx.smoketrail,
|
||||
Alpha = PV_Linear(180,0),
|
||||
Size = PV_Linear(20,30),
|
||||
BlitMode = GFX_BLIT_Additive,
|
||||
};
|
||||
fx.frontburn =
|
||||
{
|
||||
R = 255,
|
||||
B = 50,
|
||||
G = 190,
|
||||
|
||||
Alpha = PV_KeyFrames(0, 0, 0, 500, 25, 1000, 0),
|
||||
Size = PV_Linear(4,5),
|
||||
Stretch = 1000,
|
||||
Phase = PV_Random(0,4),
|
||||
Rotation = PV_Random(-GetR() - 15, -GetR() + 15),
|
||||
DampingX = 1000,
|
||||
DampingY = 1000,
|
||||
BlitMode = GFX_BLIT_Additive,
|
||||
CollisionVertex = 0,
|
||||
OnCollision = PC_Stop(),
|
||||
Attach = ATTACH_Front | ATTACH_MoveRelative
|
||||
};
|
||||
}
|
||||
|
||||
protected func FxIntMeteorTimer(object target, effect fx, bool temp)
|
||||
{
|
||||
var size = GetCon();
|
||||
// Air drag.
|
||||
|
@ -98,10 +195,12 @@ protected func FxIntMeteorTimer()
|
|||
ydir -= size * ydir ** 2 / 11552000; // Magic number.
|
||||
SetYDir(ydir, 100);
|
||||
// Smoke trail.
|
||||
CreateParticle("Smoke", PV_Random(-2, 2), PV_Random(-2, 2), PV_Random(-3, 3), PV_Random(-3, 3), 30 + Random(60), Particles_SmokeTrail(), 5);
|
||||
// Fire trail.
|
||||
CreateParticle("MagicSpark", 0, 0, PV_Random(-20, 20), PV_Random(-20, 20), 16, Particles_SparkFire(), 4);
|
||||
CreateParticle("Fire", PV_Random(-size / 8, size / 8), PV_Random(-size / 8, size / 8), PV_Random(-1, 1), PV_Random(-1, 1), 30, Particles_FireTrail(), 6 + size / 10);
|
||||
CreateParticle("SmokeThick", 0, 0, PV_Random(-3, 3), PV_Random(-3, 3), 200, fx.smoketrail, 5);
|
||||
// Flash
|
||||
CreateParticle("SmokeThick", 0, -4, PV_Random(-3, 3), PV_Random(-3, 3), 3, fx.brighttrail, 2);
|
||||
// left and right burn
|
||||
CreateParticle("FireDense", PV_Random(-5, 5), 15, PV_Random(-5, -20), PV_Random(-15, -30), 20, fx.frontburn, 30);
|
||||
CreateParticle("FireDense", PV_Random(-5, 5), 15, PV_Random(5, 20), PV_Random(-15, -30), 20, fx.frontburn, 30);
|
||||
// Sound.
|
||||
|
||||
// Burning and friction decrease size.
|
||||
|
@ -111,6 +210,13 @@ protected func FxIntMeteorTimer()
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Scenario saving
|
||||
func FxIntMeteorSaveScen(obj, fx, props)
|
||||
{
|
||||
props->AddCall("Meteor", obj, "AddEffect", "\"IntMeteor\"", obj, 100, 1, obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected func Hit(int xdir, int ydir)
|
||||
{
|
||||
var size = 10 + GetCon();
|
||||
|
@ -125,17 +231,26 @@ protected func Hit(int xdir, int ydir)
|
|||
// Explode meteor, explode size scales with the energy of the meteor.
|
||||
var dam = size * speed2 / 500;
|
||||
dam = BoundBy(size/2, 5, 30);
|
||||
Explode(dam);
|
||||
// Blow up a dummy object so that the explosion can happen before we spawn items.
|
||||
var dummy = CreateObject(Dummy, 0, 0, GetController());
|
||||
dummy->Explode(dam);
|
||||
|
||||
// Fling around some objects?
|
||||
if (spawn_id)
|
||||
{
|
||||
for (var i = 0; i < spawn_amount; ++i)
|
||||
{
|
||||
var angle = Angle(0, 0, -xdir, -ydir) + RandomX(-45, 45);
|
||||
var force = BoundBy(GetCon() / 2, 10, 50) + RandomX(-10, 10);
|
||||
var item = CreateObject(spawn_id, 0, 0, GetOwner());
|
||||
item->SetSpeed(Sin(angle, force), -Cos(angle, force));
|
||||
}
|
||||
}
|
||||
|
||||
RemoveObject();
|
||||
return;
|
||||
}
|
||||
|
||||
// Scenario saving
|
||||
func FxIntMeteorSaveScen(obj, fx, props)
|
||||
{
|
||||
props->AddCall("Meteor", obj, "AddEffect", "\"IntMeteor\"", obj, 100, 1, obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-- Proplist --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
|
|
Loading…
Reference in New Issue