renewed explosion: volume-smoke, Hazard-smoke-trails, a little bit better explosion graphic

stable-5.2
Tobias Zwick 2009-07-14 18:50:05 +02:00
parent 7b1f240aaa
commit fe1fa8e729
5 changed files with 188 additions and 45 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -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

View File

@ -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

View File

@ -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;
}