forked from Mirrors/openclonk
renewed explosion: volume-smoke, Hazard-smoke-trails, a little bit better explosion graphic
parent
7b1f240aaa
commit
fe1fa8e729
Binary file not shown.
After Width: | Height: | Size: 84 KiB |
|
@ -0,0 +1,12 @@
|
|||
[Particle]
|
||||
Name=Blast
|
||||
MaxCount=300
|
||||
InitFn=StdInit
|
||||
ExecFn=StdExec
|
||||
DrawFn=Std
|
||||
Face=0,0,40,40,-20,-20
|
||||
Delay=1
|
||||
AlphaFade=1
|
||||
Repeats=1
|
||||
Reverse=1
|
||||
Additive=1
|
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -0,0 +1,10 @@
|
|||
[Particle]
|
||||
Name=ExploSmoke
|
||||
MaxCount=800
|
||||
InitFn=StdInit
|
||||
ExecFn=StdExec
|
||||
DrawFn=Std
|
||||
Face=0,0,64,64,-32,-32
|
||||
Delay=0
|
||||
Repeats=1
|
||||
AlphaFade=1
|
|
@ -1,12 +1,19 @@
|
|||
/* Explode, BlastObjects und Sichtfenster-Kamera-Wackel-Effekt */
|
||||
/* Everything about the explosion */
|
||||
|
||||
// TODO: many comments are still in German
|
||||
|
||||
// TODO: docs
|
||||
|
||||
#strict 2
|
||||
|
||||
global func Explode(int iLevel, object pObj, id idEffect, string szEffect) {
|
||||
global func Explode(int iLevel, object pObj) {
|
||||
// Viewport wackeln
|
||||
ShakeViewPort(iLevel, 0, GetX(pObj), GetY(pObj));
|
||||
|
||||
// Sound muss vor dem Löschen des Objektes erzeugt werden, damit die Position stimmt
|
||||
var grade = BoundBy((iLevel/10)-1,1,3);
|
||||
Sound(Format("Blast%d", grade), false, pObj);
|
||||
|
||||
// Explosionsparameter
|
||||
if (!pObj) if (!(pObj = this)) return false;
|
||||
var x=GetX(pObj), y=GetY(pObj);
|
||||
|
@ -14,59 +21,72 @@ global func Explode(int iLevel, object pObj, id idEffect, string szEffect) {
|
|||
var container = Contained(pObj);
|
||||
var exploding_id = GetID(pObj);
|
||||
var layer = GetObjectLayer(pObj);
|
||||
|
||||
// Explosionsparameter gesichert: Jetzt das Objekt entfernen, damit es von der Explosion selber nicht betroffen ist
|
||||
RemoveObject(pObj);
|
||||
|
||||
// Und die Explosion im globalen Kontext ausführen
|
||||
// Leider gibt es keine Möglichkeit, auf den globalen Kontext zuzugreifen (außer GameCall, aber das löst die Funktion immer neu auf)
|
||||
// Also zumindest den Objektkontext entfernen
|
||||
exploding_id->DoExplosion(x, y, iLevel, container, cause_plr, idEffect, szEffect, layer);
|
||||
exploding_id->DoExplosion(x, y, iLevel, container, cause_plr, layer);
|
||||
}
|
||||
|
||||
global func DoExplosion(int x, int y, int level, object inobj, int cause_plr, id effect_def, string effect_particle, object layer)
|
||||
{
|
||||
// Container nach ContainBlast
|
||||
var container = inobj;
|
||||
while (container) if (GetDefContainBlast(GetID(container))) break; else container = Contained(container);
|
||||
// Explosion draußen: Explosionseffekte erzeugen
|
||||
if (!container)
|
||||
{
|
||||
// Öl anzünden
|
||||
global func DoExplosion(int x, int y, int level, object inobj, int cause_plr, object layer)
|
||||
{
|
||||
// Container to ContainBlast
|
||||
var container = inobj;
|
||||
while(container)
|
||||
{
|
||||
if(GetDefContainBlast(GetID(container))) break;
|
||||
else container = Contained(container);
|
||||
}
|
||||
|
||||
// Explosion outside: Explosion effects
|
||||
if (!container)
|
||||
{
|
||||
// incinerate oil
|
||||
if (!IncinerateLandscape(x,y))
|
||||
if (!IncinerateLandscape(x,y-10))
|
||||
if (!IncinerateLandscape(x-5,y-5))
|
||||
IncinerateLandscape(x+5,y-5);
|
||||
// Grafikeffekt
|
||||
var blast;
|
||||
if (effect_particle)
|
||||
effect_def = 0;
|
||||
else
|
||||
effect_particle = "Blast";
|
||||
if (effect_def)
|
||||
{
|
||||
if(blast = CreateConstruction(effect_def, x,y+level, cause_plr, level*5))
|
||||
blast->~Activate();
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateParticle(effect_particle, x,y, 0,0, level*10);
|
||||
if (effect_particle == "Blast")
|
||||
if (!CastParticles("FSpark", level/5+1, level, x,y, level*5+10,level*10+10, 0x00ef0000,0xffff1010))
|
||||
if(blast = CreateConstruction(FXB1, x,y+level, cause_plr, level*5))
|
||||
blast->~Activate();
|
||||
}
|
||||
}
|
||||
|
||||
// graphic effects:
|
||||
|
||||
// blast particle
|
||||
CreateParticle("Blast", x,y, 0,0, level*10, RGBa(255,255,255,100));
|
||||
//CastParticles("FSpark", level/5+1, level, x,y, level*5+10,level*10+10, 0x00ef0000,0xffff1010));
|
||||
|
||||
// smoke trails
|
||||
var i=0, count = 3+level/8, angle = Random(360);
|
||||
while(count > 0 && ++i < 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 = 16 * level / 10;
|
||||
CreateSmokeTrail(lvl,angle,x+smokex,y+smokey);
|
||||
count--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Schaden in den Objekten bzw. draußen
|
||||
BlastObjects(x+GetX(),y+GetY(), level, inobj, cause_plr+1, layer);
|
||||
if (inobj != container) BlastObjects(x+GetX(),y+GetY(), level, container, cause_plr+1, layer);
|
||||
|
||||
// Landschaft zerstören. Nach BlastObjects, damit neu freigesprengte Materialien nicht betroffen sind
|
||||
if (!container)
|
||||
{
|
||||
BlastFree(x,y, level, cause_plr+1);
|
||||
}
|
||||
// Fertig!
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ----------------------- Blast objects & shockwaves --------------------- */
|
||||
|
||||
// Objekte beschädigen und wegschleudern
|
||||
global func BlastObjects(int x, int y, int level, object container, int cause_plr_plus_one, object layer)
|
||||
{
|
||||
|
@ -92,7 +112,10 @@ global func BlastObjects(int x, int y, int level, object container, int cause_pl
|
|||
// Objekte am Explosionspunkt beschädigen
|
||||
for (var obj in FindObjects(Find_AtRect(l_x-5, l_y-5, 10,10), Find_NoContainer(), Find_Layer(layer)))
|
||||
if (obj) BlastObject(level, obj, cause_plr_plus_one);
|
||||
// Objekte im Explosionsradius schleudern
|
||||
|
||||
// TODO: -> Shockwave in own global func(?)
|
||||
|
||||
// Objekte im Explosionsradius schleudern
|
||||
var shockwave_objs = FindObjects(Find_Distance(level, l_x,l_y), Find_NoContainer(), Find_Layer(layer),
|
||||
Find_Or(Find_Category(C4D_Object|C4D_Living|C4D_Vehicle), Find_Func("CanBeHitByShockwaves")), Find_Func("BlastObjectsShockwaveCheck",x,y));
|
||||
var cnt = GetLength(shockwave_objs);
|
||||
|
@ -163,40 +186,69 @@ global func BlastObjectsShockwaveCheck(int x, int y)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------- Shake view port --------------------------- */
|
||||
|
||||
global func ShakeViewPort(int iLevel, object pObj, int iOffX, int iOffY) {
|
||||
if(iLevel <= 0) return false;
|
||||
|
||||
var eff=GetEffect("ShakeEffect",pObj);
|
||||
if(eff) {
|
||||
|
||||
if(eff)
|
||||
{
|
||||
EffectVar(0,pObj,eff)+=iLevel;
|
||||
return true;
|
||||
}
|
||||
|
||||
eff=AddEffect("ShakeEffect",pObj,200,1);
|
||||
if (!eff) return false;
|
||||
|
||||
EffectVar(0,pObj,eff)=iLevel;
|
||||
if(iOffX || iOffY) {
|
||||
|
||||
if(iOffX || iOffY)
|
||||
{
|
||||
EffectVar(1,pObj,eff)=iOffX;
|
||||
EffectVar(2,pObj,eff)=iOffY;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
EffectVar(1,pObj,eff)=GetX(pObj);
|
||||
EffectVar(2,pObj,eff)=GetY(pObj);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Dauer des Effektes: sobald iStrength==0
|
||||
// Stärke des Effektes: iStrength=iLevel/(1.5*iTime+3)-iTime^2/400
|
||||
// Variables:
|
||||
// 0 - level
|
||||
// 1 - x-pos
|
||||
// 2 - y-pos
|
||||
|
||||
// Duration of the effect: as soon as iStrength==0
|
||||
// Strength of the effect: iStrength=iLevel/(1.5*iTime+3)-iTime^2/400
|
||||
|
||||
global func FxShakeEffectTimer(object pTarget, int iEffectNumber, int iTime) {
|
||||
var iPlr, iLevel;
|
||||
|
||||
var iStrength;
|
||||
|
||||
var str = EffectVar(0,pTarget,iEffectNumber);
|
||||
var xpos = EffectVar(1,pTarget,iEffectNumber);
|
||||
var ypos = EffectVar(2,pTarget,iEffectNumber);
|
||||
|
||||
|
||||
for(var i=0; i<GetPlayerCount(); i++) {
|
||||
iPlr=GetPlayerByIndex(i);
|
||||
var iPlr=GetPlayerByIndex(i);
|
||||
var distance = Distance(GetX(GetCursor(iPlr)),GetY(GetCursor(iPlr)),xpos,ypos);
|
||||
|
||||
// Schütteleffekt verringert sich je nach Entfernung
|
||||
iLevel=(300*EffectVar(0,pTarget,iEffectNumber))/Max(300,Distance(GetX(GetCursor(iPlr)),GetY(GetCursor(iPlr)),EffectVar(1,pTarget,iEffectNumber),EffectVar(2,pTarget,iEffectNumber)));
|
||||
if((iStrength=iLevel/((3*iTime)/2+3)-iTime**2/400)<=0) continue;
|
||||
var iLevel= (300*str) / Max(300,distance);
|
||||
|
||||
if((iStrength=iLevel/((3*iTime)/2 + 3) - iTime**2/400) <= 0) continue;
|
||||
|
||||
// FIXME: Use GetViewOffset, make this relative, not absolute
|
||||
SetViewOffset(iPlr,Sin(iTime*100,iStrength),Cos(iTime*100,iStrength));
|
||||
}
|
||||
if(EffectVar(0,pTarget,iEffectNumber)/((3*iTime)/2+3)-iTime**2/400<=0) return -1;
|
||||
|
||||
if(EffectVar(0,pTarget,iEffectNumber)/((3*iTime)/2 + 3) - iTime**2/400 <= 0) return -1;
|
||||
}
|
||||
|
||||
global func FxShakeEffectStart(object pTarget, int iEffectNumber) {
|
||||
|
@ -209,3 +261,72 @@ global func FxShakeEffectStop() {
|
|||
SetViewOffset(GetPlayerByIndex(i),0,0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------- Smoke trails ------------------------------ */
|
||||
|
||||
global func CreateSmokeTrail(int iStrength, int iAngle, int iX, int iY, object pObj) {
|
||||
iX += GetX(pObj);
|
||||
iY += GetY(pObj);
|
||||
AddEffect("SmokeTrail", 0, 300, 1, 0, 0, iStrength, iAngle, iX, iY);
|
||||
}
|
||||
|
||||
// Variables:
|
||||
// 0 - Strength
|
||||
// 1 - Current strength
|
||||
// 2 - X-Position
|
||||
// 3 - Y-Position
|
||||
// 4 - Starting-X-Speed
|
||||
// 5 - Starting-Y-Speed
|
||||
global func FxSmokeTrailStart(object pTarget, int iEffectNumber, int iTemp, iStrength, iAngle, iX, iY) {
|
||||
|
||||
if(iTemp)
|
||||
return;
|
||||
|
||||
if(iAngle%90 == 1) iAngle += 1;
|
||||
iStrength = Max(iStrength,5);
|
||||
|
||||
EffectVar(0, pTarget, iEffectNumber) = iStrength;
|
||||
EffectVar(1, pTarget, iEffectNumber) = iStrength;
|
||||
EffectVar(2, pTarget, iEffectNumber) = iX;
|
||||
EffectVar(3, pTarget, iEffectNumber) = iY;
|
||||
EffectVar(4, pTarget, iEffectNumber) = +Sin(iAngle,iStrength*40);
|
||||
EffectVar(5, pTarget, iEffectNumber) = -Cos(iAngle,iStrength*40);
|
||||
}
|
||||
|
||||
global func FxSmokeTrailTimer(object pTarget, int iEffectNumber, int iEffectTime) {
|
||||
var iStrength = EffectVar(0, pTarget, iEffectNumber);
|
||||
var iAStr = EffectVar(1, pTarget, iEffectNumber);
|
||||
var iX = EffectVar(2, pTarget, iEffectNumber);
|
||||
var iY = EffectVar(3, pTarget, iEffectNumber);
|
||||
var iXDir = EffectVar(4, pTarget, iEffectNumber);
|
||||
var iYDir = EffectVar(5, pTarget, iEffectNumber);
|
||||
|
||||
iAStr = Max(1,iAStr-iAStr/5);
|
||||
iAStr--;
|
||||
iYDir += GetGravity()*2/3;
|
||||
|
||||
var xdir = iXDir*iAStr/iStrength;
|
||||
var ydir = iYDir*iAStr/iStrength;
|
||||
|
||||
// new: random
|
||||
iX += RandomX(-3,3);
|
||||
iY += RandomX(-3,3);
|
||||
|
||||
// draw
|
||||
CreateParticle("ExploSmoke",iX,iY,RandomX(-2,2),RandomX(-2,4),150+iAStr*12,RGBa(130,130,130,90));
|
||||
CreateParticle("Blast",iX,iY,0,0,10+iAStr*8,RGBa(255,100,50,150));
|
||||
|
||||
// then calc next position
|
||||
iX += xdir/100;
|
||||
iY += ydir/100;
|
||||
|
||||
if(GBackSemiSolid(iX,iY))
|
||||
return -1;
|
||||
if(iAStr <= 3)
|
||||
return -1;
|
||||
|
||||
EffectVar(1, pTarget, iEffectNumber) = iAStr;
|
||||
EffectVar(2, pTarget, iEffectNumber) = iX;
|
||||
EffectVar(3, pTarget, iEffectNumber) = iY;
|
||||
EffectVar(5, pTarget, iEffectNumber) = iYDir;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue