1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
/*
Effect.c
Contains functions for (visual) effects that require particles or definitions from Objects.ocd to be loaded.
@author
*/
/*
Creates a visual explosion effect at a position.
smoothness (in percent) determines how round the effect will look like
*/
global func ExplosionEffect(int level, int x, int y, int smoothness, bool silent, int damage_level)
{
// Zero-size explosion doesn't affect anything
if (level <= 0) return;
if (!silent) //Does object use it's own explosion sound effect?
{
// Select sound according to level: from 1 to 3, add the * to allow alternatives.
var grade = BoundBy(level / 10 - 1, 1, 3);
if (GBackLiquid(x, y))
SoundAt(Format("Fire::BlastLiquid%d*",grade), x, y);
else
SoundAt(Format("Fire::Blast%d*", grade), x, y);
}
// possibly init particle definitions?
if (!ExplosionParticles_Blast)
ExplosionParticles_Init();
smoothness = smoothness ?? 0;
var level_pow = level ** 2;
var level_pow_fraction = Max(level_pow / 25, 5 * level);
var wilderness_level = level * (100 - smoothness) / 100;
var smoothness_level = level * smoothness / 100;
var smoke_size = PV_KeyFrames(0, 180, level, 1000, level * 2);
var blast_size = PV_KeyFrames(0, 0, 0, 260, level * 2, 1000, level);
var blast_smooth_size = PV_KeyFrames(0, 0, 0, 250, PV_Random(level, level * 2), 1000, level);
var star_size = PV_KeyFrames(0, 0, 0, 500, level * 2, 1000, 0);
var shockwave_size = PV_Linear(0, level * 4);
CreateParticle("SmokeDirty", PV_Random(x - 10,x + 10), PV_Random(y - 10, y + 10), 0, PV_Random(-2, 0), PV_Random(50, 100), {Prototype = ExplosionParticles_Smoke, Size = smoke_size}, Max(2, wilderness_level / 10));
CreateParticle("SmokeDirty", PV_Random(x - 5, x + 5), PV_Random(y - 5, y + 5), PV_Random(-1, 1), PV_Random(-1, 1), PV_Random(20, 40), {Prototype = ExplosionParticles_BlastSmoothBackground, Size = blast_smooth_size}, smoothness_level / 5);
CreateParticle("SmokeDirty", PV_Random(x - 5, x + 5), PV_Random(y - 5, y + 5), PV_Random(-1, 1), PV_Random(-1, 1), PV_Random(20, 40), {Prototype = ExplosionParticles_BlastSmooth, Size = blast_smooth_size}, smoothness_level / 5);
CreateParticle("Dust", PV_Random(x - 5, x + 5), PV_Random(y - 5, y + 5), 0, 0, PV_Random(18, 25), {Prototype = ExplosionParticles_Blast, Size = blast_size}, smoothness_level / 5);
CreateParticle("StarFlash", PV_Random(x - 6, x + 6), PV_Random(y - 6, y + 6), PV_Random(-wilderness_level/4, wilderness_level/4), PV_Random(-wilderness_level/4, wilderness_level/4), PV_Random(10, 12), {Prototype = ExplosionParticles_Star, Size = star_size}, wilderness_level / 3);
CreateParticle("Shockwave", x, y, 0, 0, 15, {Prototype = ExplosionParticles_Shockwave, Size = shockwave_size}, nil);
// cast either some sparks on land or bubbles under water
if(GBackLiquid(x, y) && Global.CastBubbles)
{
Global->CastBubbles(level * 7 / 10, level, x, y);
}
else
{
CreateParticle("Magic", PV_Random(x - 5, x + 5), PV_Random(y - 5, y + 5), PV_Random(-level_pow_fraction, level_pow_fraction), PV_Random(-level_pow_fraction, level_pow_fraction), PV_Random(25, 70), ExplosionParticles_Glimmer, level);
}
// very wild explosion? Smoke trails!
var smoke_trail_count = wilderness_level / 10;
var angle = Random(360);
var failsafe = 0; // against infinite loops
while (smoke_trail_count > 0 && (++failsafe < smoke_trail_count * 10))
{
angle += RandomX(40, 80);
var smokex = Sin(angle, RandomX(level / 4, level / 2));
var smokey = -Cos(angle, RandomX(level / 4, level / 2));
if (GBackSolid(x + smokex, y + smokey))
continue;
var lvl = 2 * wilderness_level;
CreateSmokeTrail(lvl, angle, x + smokex, y + smokey);
smoke_trail_count--;
}
// Temporary light effect
if (level > 5)
Global->CreateLight(x, y, level, Fx_Light.LGT_Blast);
return;
}
/**
Creates a raindrop effect upon the the calling object.
@par duration The duration of the effect. Default nil = unlimited.
@par interval The interval in which the raindrops are created. Default 10.
@material The material of which the drops are created. Default "Water".
@strength Specifies how many drops are created in a call.
@return The created effect.
*/
global func AddRainDropEffect(int duration, int interval, string material, int strength, int offset_x, int offset_y)
{
if (!this || GetType(this) != C4V_C4Object)
FatalError(Format("AddRainDropEffect needs to be called from object context, not from %v", this));
return this->CreateEffect(FxRainDrop, 1, interval ?? 10, duration, material, strength, [offset_x, offset_y]);
}
static const FxRainDrop = new Effect
{
duration = nil,
material = nil,
strength = nil,
offset = [0, 0],
particle_cache = {},
Construction = func(int duration, string material, int strength, array offset)
{
this.duration = duration;
this.material = material ?? "Water";
this.strength = strength ?? 1;
this.offset = offset ?? [0, 0];
},
Timer = func(int time)
{
if (!this.Target || (this.duration != nil && time > this.duration))
return FX_Execute_Kill;
if (this.Target->GBackSemiSolid(this.offset[0], this.offset[1]))
return FX_OK;
var con = this.Target->GetCon();
var wdt = this.Target->GetDefWidth() * con / 500;
var hgt = this.Target->GetDefHeight() * con / 700;
var particle_name;
var color = Cloud->GetMaterialColor(this.material);
if (this.particle_cache.color != color)
{
this.particle_cache.color = color;
this.particle_cache.particle = Particles_Rain(color);
this.particle_cache.particle.Size = 5;
}
if (this.material == "Lava" || this.material == "DuroLava")
particle_name = "RaindropLava";
else
particle_name = "Raindrop";
this.Target->CreateParticle(
particle_name,
PV_Random(this.offset[0] - wdt, this.offset[0] + wdt),
PV_Random(this.offset[1] - hgt, this.offset[1] + hgt),
PV_Random(-5, 5),
PV_Random(10, 30),
PV_Random(200, 300),
this.particle_cache.particle,
this.strength
);
this.Target->~OnRainDropCreated(this);
return FX_OK;
}
};
|