2017-06-02 15:14:52 +00:00
/**
Fire . c
The fire effect ported from the engine . Functions to be used as documented in the docs .
@ author Zapper , Maikel
*/
2011-03-12 18:29:25 +00:00
2015-10-07 21:26:03 +00:00
static const FIRE_LIGHT_COLOR = 0xc86400 ;
2012-04-28 14:17:38 +00:00
2011-03-12 18:29:25 +00:00
// fire drawing modes
2012-05-01 18:50:21 +00:00
static const C4Fx_FireMode_Default = 0 ; // determine mode by category
static const C4Fx_FireMode_LivingVeg = 2 ; // C4D_Living and C4D_StaticBack
static const C4Fx_FireMode_StructVeh = 1 ; // C4D_Structure and C4D_Vehicle
static const C4Fx_FireMode_Object = 3 ; // other (C4D_Object and no bit set (magic))
static const C4Fx_FireMode_Last = 3 ; // largest valid fire mode
2011-03-12 18:29:25 +00:00
2012-04-28 14:17:38 +00:00
// Returns whether the object is burning.
2017-10-20 22:10:42 +00:00
// documented in /docs/sdk/script/fn
2011-03-12 18:29:25 +00:00
global func OnFire ( )
{
2012-05-01 18:50:21 +00:00
if ( ! this )
return false ;
2011-03-12 18:29:25 +00:00
var effect ;
2012-05-01 18:50:21 +00:00
if ( ! ( effect = GetEffect ( " Fire " , this ) ) )
return false ;
2011-03-12 18:29:25 +00:00
return effect . strength ;
}
2012-04-28 14:17:38 +00:00
// Extinguishes the calling object with specified strength.
2017-10-20 22:10:42 +00:00
// documented in /docs/sdk/script/fn
2012-06-05 20:51:09 +00:00
global func Extinguish ( strength /* strength between 0 and 100 */ )
2011-03-12 18:29:25 +00:00
{
2012-05-01 18:50:21 +00:00
if ( ! this )
return false ;
if ( strength = = nil )
strength = 100 ;
else if ( ! strength )
return false ;
2011-03-12 18:29:25 +00:00
2012-05-01 18:50:21 +00:00
var effect = GetEffect ( " Fire " , this ) ;
if ( ! effect )
return false ;
2011-03-16 09:12:09 +00:00
effect . strength = BoundBy ( effect . strength - strength , 0 , 100 ) ;
2012-05-01 18:50:21 +00:00
if ( effect . strength = = 0 )
RemoveEffect ( nil , this , effect ) ;
2011-03-16 09:12:09 +00:00
return true ;
2011-03-12 18:29:25 +00:00
}
2012-04-28 14:17:38 +00:00
// Incinerates the calling object with specified strength.
2017-10-20 22:10:42 +00:00
// documented in /docs/sdk/script/fn
2012-06-05 20:51:09 +00:00
global func Incinerate (
strength /* strength between 0 and 100 */
, int caused_by /* the player that caused the incineration */
, blasted /* whether the object was incinerated by an explosion */
, incinerating_object /* the object that caused the incineration */ )
2011-03-12 18:29:25 +00:00
{
2012-05-01 18:50:21 +00:00
if ( ! this )
return false ;
if ( strength = = nil )
strength = 100 ;
else if ( ! strength )
return false ;
2011-03-12 18:29:25 +00:00
2012-05-01 18:50:21 +00:00
var effect = GetEffect ( " Fire " , this ) ;
if ( effect )
{
effect . strength = BoundBy ( effect . strength + strength , 0 , 100 ) ;
return true ;
}
else
2015-09-15 02:31:51 +00:00
{
effect = AddEffect ( " Fire " , this , 100 , 4 , this , nil , caused_by , ! ! blasted , incinerating_object , strength ) ;
return ! ! effect ;
}
2011-03-12 18:29:25 +00:00
}
2012-04-28 14:17:38 +00:00
// Called if the object is submerged in incendiary material (for example in lava).
2011-03-12 18:29:25 +00:00
global func OnInIncendiaryMaterial ( )
{
2017-11-21 17:16:45 +00:00
if ( this - > IsInFireproofContainer ( ) )
return ;
2015-08-16 21:14:16 +00:00
this - > DoEnergy ( - 7 , false , FX_Call_EngFire , NO_OWNER ) ;
2016-05-27 20:19:41 +00:00
// The object might have removed itself.
if ( ! this ) return true ;
2015-08-16 21:14:16 +00:00
return this - > Incinerate ( 15 , NO_OWNER ) ;
2011-03-12 18:29:25 +00:00
}
2017-11-21 17:16:45 +00:00
global func IsInFireproofContainer ( )
{
if ( ! this ) return false ;
if ( this - > Contained ( ) )
{
if ( this - > Contained ( ) . FireproofContainer )
return true ;
return this - > Contained ( ) - > IsInFireproofContainer ( ) ;
}
return false ;
}
2012-04-03 00:55:55 +00:00
// Makes the calling object non flammable.
global func MakeNonFlammable ( )
{
if ( ! this )
return ;
return AddEffect ( " IntNonFlammable " , this , 300 ) ;
2012-04-28 14:17:38 +00:00
}
/*-- Fire Effects --*/
2012-04-03 00:55:55 +00:00
global func FxIntNonFlammableEffect ( string new_name )
{
// Block fire effects.
if ( WildcardMatch ( new_name , " *Fire* " ) )
return - 1 ;
// All other effects are okay.
return 0 ;
}
2015-03-22 09:22:15 +00:00
2012-05-01 18:50:21 +00:00
global func FxFireStart ( object target , proplist effect , int temp , int caused_by , bool blasted , object incinerating_object , strength )
2011-03-12 18:29:25 +00:00
{
// safety
if ( ! target ) return - 1 ;
// temp readd
2011-10-13 22:03:55 +00:00
if ( temp ) return 1 ;
2011-03-12 18:29:25 +00:00
// fail if already on fire
//if (target->OnFire()) return -1;
2012-04-22 13:15:04 +00:00
// Fail if target is dead and has NoBurnDecay, to prevent eternal fires.
2012-04-28 14:17:38 +00:00
if ( target - > GetCategory ( ) & C4D_Living & & ! target - > GetAlive ( ) & & target . NoBurnDecay )
2012-04-22 13:15:04 +00:00
return - 1 ;
2011-03-12 18:29:25 +00:00
// structures must eject contents now, because DoCon is not guaranteed to be executed!
// In extinguishing material
2012-04-28 14:17:38 +00:00
var fire_caused = true ;
var burn_to = target . BurnTo ;
2011-03-12 18:29:25 +00:00
var mat ;
2012-04-28 14:17:38 +00:00
if ( MaterialName ( mat = GetMaterial ( target - > GetX ( ) , target - > GetY ( ) ) ) )
2012-05-01 18:50:21 +00:00
if ( GetMaterialVal ( " Extinguisher " , " [Material] " , mat ) )
2011-03-12 18:29:25 +00:00
{
// blasts should changedef in water, too!
2012-05-01 18:50:21 +00:00
if ( blasted )
if ( burn_to ! = nil )
target - > ChangeDef ( burn_to ) ;
2011-03-12 18:29:25 +00:00
// no fire caused
fire_caused = false ;
}
// BurnTurnTo
2012-05-01 18:50:21 +00:00
if ( fire_caused )
if ( burn_to ! = nil )
target - > ChangeDef ( burn_to ) ;
2011-03-12 18:29:25 +00:00
// eject contents
var obj ;
2012-04-28 14:17:38 +00:00
if ( ! target - > GetDefCoreVal ( " IncompleteActivity " , " DefCore " ) & & ! target . NoBurnDecay )
2011-03-12 18:29:25 +00:00
{
2012-05-01 18:50:21 +00:00
for ( var i = target - > ContentsCount ( ) ; obj = target - > Contents ( - - i ) ; )
2011-03-12 18:29:25 +00:00
{
2012-05-01 18:50:21 +00:00
if ( target - > Contained ( ) )
obj - > Enter ( target - > Contained ( ) ) ;
else
obj - > Exit ( ) ;
}
2011-03-12 18:29:25 +00:00
// Detach attached objects
2012-05-01 18:50:21 +00:00
for ( obj in FindObjects ( Find_ActionTarget ( target ) ) )
2011-03-12 18:29:25 +00:00
{
2012-05-01 18:50:21 +00:00
if ( obj - > GetProcedure ( ) = = " ATTACH " )
2012-04-12 09:48:23 +00:00
obj - > SetAction ( nil ) ;
2011-03-12 18:29:25 +00:00
}
}
// fire caused?
if ( ! fire_caused )
{
2012-05-01 18:50:21 +00:00
// if object was blasted but not incinerated (i.e., inside extinguisher), do a script callback
if ( blasted )
target - > ~ IncinerationEx ( caused_by ) ;
2011-03-12 18:29:25 +00:00
return - 1 ;
}
// determine fire appearance
var fire_mode ;
2012-05-01 18:50:21 +00:00
if ( ! ( fire_mode = target - > ~ GetFireMode ( ) ) )
2011-03-12 18:29:25 +00:00
{
// set default fire modes
var cat = target - > GetCategory ( ) ;
2015-02-17 19:55:09 +00:00
if ( cat & ( C4D_Living | C4D_StaticBack ) ) // Tiere, Bäume
2011-03-12 18:29:25 +00:00
fire_mode = C4Fx_FireMode_LivingVeg ;
2015-02-17 19:55:09 +00:00
else if ( cat & ( C4D_Structure | C4D_Vehicle ) ) // Gebäude und Fahrzeuge sind unten meist kantig
2011-03-12 18:29:25 +00:00
fire_mode = C4Fx_FireMode_StructVeh ;
else
fire_mode = C4Fx_FireMode_Object ;
}
else if ( ! Inside ( fire_mode , 1 , C4Fx_FireMode_Last ) )
{
DebugLog ( " Warning: FireMode %d of object %s (%i) is invalid! " , fire_mode , target - > GetName ( ) , target - > GetID ( ) ) ;
fire_mode = C4Fx_FireMode_Object ;
}
// store causes in effect vars
effect . strength = strength ;
effect . mode = fire_mode ;
effect . caused_by = caused_by ; // used in C4Object::GetFireCause and timer! <- fixme?
effect . blasted = blasted ;
effect . incinerating_obj = incinerating_object ;
2015-03-22 09:22:15 +00:00
// store fire particles
effect . smoke =
{
R = 255 ,
G = 255 ,
B = 255 ,
CollisionVertex = 1000 ,
OnCollision = PC_Stop ( ) ,
ForceX = PV_Wind ( 50 ) ,
DampingX = PV_Linear ( 900 , 999 ) ,
ForceY = - 7 ,
DampingY = PV_Linear ( 1000 , PV_Random ( 650 , 750 ) ) ,
Rotation = PV_Random ( 0 , 359 ) ,
Phase = PV_Random ( 0 , 3 )
} ;
effect . chaoticspark =
{
Size = PV_Linear ( 1 , 0 ) ,
ForceX = PV_KeyFrames ( 10 , 0 , PV_Random ( - 6 , 6 ) , 333 , PV_Random ( - 6 , - 6 ) , 666 , PV_Random ( 6 , 6 ) , 1000 , PV_Random ( - 6 , 6 ) ) ,
ForceY = PV_KeyFrames ( 10 , 0 , PV_Random ( - 8 , 5 ) , 333 , PV_Random ( - 8 , 5 ) , 666 , PV_Random ( - 10 , 10 ) , 1000 , PV_Random ( - 10 , 15 ) ) ,
Stretch = PV_Speed ( 1000 , 500 ) ,
Rotation = PV_Direction ( ) ,
CollisionVertex = 0 ,
OnCollision = PC_Die ( ) ,
R = 255 ,
G = PV_Linear ( 255 , 200 ) ,
B = PV_Random ( 0 , 100 ) ,
DampingX = 950 ,
DampingY = 950 ,
Alpha = PV_Random ( 40 , 140 ) ,
BlitMode = GFX_BLIT_Additive
} ;
effect . redfiredense =
{
R = PV_Random ( 0 , 255 ) ,
G = 0 ,
B = 0 ,
Alpha = 120 ,
Rotation = PV_Random ( 0 , 359 ) ,
Phase = PV_Random ( 0 , 3 ) ,
OnCollision = 0
} ;
effect . flameborder =
{
R = 255 ,
G = PV_Linear ( 255 , 0 ) ,
B = 0 ,
Phase = PV_Random ( 0 , 4 ) ,
OnCollision = PC_Die ( ) ,
OnCollision = 0 ,
Alpha = PV_KeyFrames ( 0 , 0 , 0 , 100 , 80 , 600 , 80 , 1000 , 1 )
} ;
effect . sharpflame =
{
R = 255 ,
G = PV_KeyFrames ( 0 , 0 , 255 , 666 , 0 , 627 , 0 ) ,
B = 0 ,
Rotation = PV_Random ( - 5 , 5 ) ,
Phase = PV_Random ( 0 , 5 ) ,
OnCollision = 0 ,
BlitMode = GFX_BLIT_Additive
} ;
// Optimization: Only for living beings the flame actually follows the object. That means for all other objects, the flames can be rendered as one batch.
if ( target - > GetOCF ( ) & OCF_Alive )
{
effect . sharpflame . Attach = ATTACH_MoveRelative ;
effect . flameborder . Attach = ATTACH_MoveRelative ;
}
// Prepare some more values.
EffectCall ( target , effect , " UpdateEffectProperties " ) ;
// Reduce checks, smoke and a few other particles if there are other burning objects around.
effect . FreqReduction = 1 ;
for ( var nearby in FindObjects ( Find_Distance ( effect . height ) ) )
if ( nearby - > OnFire ( ) )
+ + effect . FreqReduction ;
effect . FreqReduction = effect . Interval * BoundBy ( effect . FreqReduction / 3 , 1 , 6 ) ;
2011-03-12 18:29:25 +00:00
// Set values
2015-03-22 09:22:15 +00:00
if ( ( 4 * effect . width * effect . height ) > 500 )
2015-12-13 21:14:55 +00:00
target - > Sound ( " Fire::Inflame " , false , 100 ) ;
2012-05-12 12:42:20 +00:00
if ( target - > GetMass ( ) > = 100 )
2015-12-13 21:14:55 +00:00
if ( target - > Sound ( " Fire::Fire " , false , 100 , nil , 1 ) )
2012-05-12 12:42:20 +00:00
effect . fire_sound = true ;
2011-03-16 09:12:09 +00:00
// callback
target - > ~ Incineration ( effect . caused_by ) ;
2011-03-12 18:29:25 +00:00
// Done, success
return FX_OK ;
}
2015-03-22 09:22:15 +00:00
global func FxFireUpdateEffectProperties ( object target , proplist effect )
{
effect . width = target - > GetObjWidth ( ) / 2 ;
effect . height = target - > GetObjHeight ( ) / 2 ;
effect . fire_width = effect . width * effect . strength / 100 + 1 ;
effect . fire_height = effect . height * effect . strength / 100 + 2 ;
effect . pspeed = - effect . fire_height / 2 ;
effect . redfiredense . Size = PV_KeyFrames ( 0 , 0 , 1 , 500 , PV_Random ( effect . fire_width / 10 , effect . fire_width / 6 ) , 1000 , 1 ) ;
var smokesize = effect . fire_width * 2 ;
if ( smokesize > 60 ) smokesize = 50 ;
effect . smoke . Size = PV_Linear ( smokesize , smokesize * 5 ) ;
effect . smoke . Alpha = PV_KeyFrames ( 0 , 0 , 1 , 50 , effect . strength , 1000 , 0 ) ;
var stretch = 500 * effect . fire_height / effect . fire_width ;
effect . maxhgt = effect . fire_height - effect . fire_width * stretch / 1500 ;
var sharpbottom = 0 ;
if ( GetCategory ( ) & C4D_Structure | | GetCategory ( ) & C4D_Vehicle ) sharpbottom + + ;
effect . flameborder . Stretch = stretch ;
effect . flameborder . Size = PV_KeyFrames ( 0 , 0 , effect . fire_width * ( 1 + sharpbottom ) , 500 , effect . fire_width * 2 , 1000 , effect . fire_width ) ;
effect . border_active = ( effect . strength > 49 ) & & ( effect . fire_height > 10 ) ;
effect . sharpflame . Size = PV_KeyFrames ( 0 , 0 , effect . fire_width * ( 2 + sharpbottom ) , 500 , effect . fire_width * 3 , 1000 , effect . fire_width * 2 ) ;
effect . sharpflame . Alpha = PV_KeyFrames ( 0 , 0 , 0 , 350 , 190 * effect . strength / 100 , 700 , 190 * effect . strength / 100 , 1000 , 0 ) ;
effect . sharpflame . Stretch = stretch ;
}
2012-05-12 12:42:20 +00:00
global func FxFireTimer ( object target , proplist effect , int time )
2011-03-12 18:29:25 +00:00
{
// safety
if ( ! target ) return FX_Execute_Kill ;
2011-03-16 09:12:09 +00:00
2011-03-12 18:29:25 +00:00
// get cause
2011-03-12 19:49:36 +00:00
//if(!GetPlayerName(effect.caused_by)) effect.caused_by=NO_OWNER;;
2011-03-12 18:29:25 +00:00
// strength changes over time
2015-03-22 09:22:15 +00:00
if ( ( effect . strength < 100 ) & & ( time % 8 = = 0 ) )
2011-03-12 18:29:25 +00:00
{
2012-05-01 18:50:21 +00:00
if ( effect . strength < 50 )
{
if ( time % 8 = = 0 )
2015-03-22 09:22:15 +00:00
{
2012-05-01 18:50:21 +00:00
effect . strength = Max ( effect . strength - 1 , 0 ) ;
2015-03-22 09:22:15 +00:00
if ( effect . strength < = 0 )
return FX_Execute_Kill ;
}
2012-05-01 18:50:21 +00:00
}
else
2015-03-22 09:22:15 +00:00
{
effect . strength = Min ( 100 , effect . strength + 2 ) ;
if ( effect . strength > 49 )
{
effect . smoke . R = 127 ;
effect . smoke . G = 127 ;
effect . smoke . B = 127 ;
}
}
// update particle properties that depend on the effect strength
EffectCall ( target , effect , " UpdateEffectProperties " ) ;
2011-03-12 18:29:25 +00:00
}
2015-03-22 09:22:15 +00:00
2011-03-12 18:29:25 +00:00
// target is in liquid?
2015-03-22 09:22:15 +00:00
if ( time % ( 20 + effect . FreqReduction ) = = 0 )
2012-05-01 18:50:21 +00:00
{
2016-06-03 20:07:17 +00:00
// Extinguish when in water-like materials.
2018-04-09 09:53:55 +00:00
var mat = GetMaterial ( ) ;
if ( mat )
2016-06-03 20:07:17 +00:00
{
2012-05-01 18:50:21 +00:00
if ( GetMaterialVal ( " Extinguisher " , " Material " , mat ) )
2015-03-22 09:22:15 +00:00
{
var steam =
{
Size = PV_Linear ( effect . width * 2 , effect . width * 4 ) ,
Alpha = PV_Linear ( 87 , 0 ) ,
R = 255 ,
G = 255 ,
B = 255 ,
Rotation = PV_Random ( 0 , 359 )
} ;
CreateParticle ( " Dust " , 0 , - 5 , 0 , 0 , 180 , steam , 2 ) ;
2011-03-12 18:29:25 +00:00
return FX_Execute_Kill ;
2015-03-22 09:22:15 +00:00
}
2016-06-03 20:07:17 +00:00
}
// Incinerate landscape if possible.
target - > IncinerateLandscape ( 0 , 0 , effect . caused_by ) ;
2015-03-22 09:22:15 +00:00
2011-03-12 18:29:25 +00:00
// check spreading of fire
2012-05-01 18:50:21 +00:00
if ( effect . strength > 10 )
2011-03-12 18:29:25 +00:00
{
2012-04-22 11:08:54 +00:00
var container = target - > Contained ( ) , inc_objs ;
2012-10-23 22:42:05 +00:00
// If contained do not incinerate anything. This would mostly affect inventory items and burns the Clonk too easily while lacking feedback.
2012-04-22 11:08:54 +00:00
if ( container )
{
2012-10-23 22:42:05 +00:00
inc_objs = [ ] ;
2012-04-22 11:08:54 +00:00
}
2012-10-23 22:42:05 +00:00
// Or if not contained incinerate all objects outside the burning object.
// Do not incinerate inventory objects, since this, too, would mostly affect Clonks and losing one's bow in a fight without noticing it is nothing but annoying to the player.
2012-04-22 11:08:54 +00:00
else
{
2015-03-22 09:22:15 +00:00
inc_objs = FindObjects ( Find_AtRect ( - effect . width / 2 , - effect . height / 2 , effect . width , effect . height ) , Find_Exclude ( target ) , Find_Layer ( target - > GetObjectLayer ( ) ) , Find_NoContainer ( ) ) ;
2012-04-22 11:08:54 +00:00
}
// Loop through the selected set of objects and check contact incinerate.
for ( var obj in inc_objs )
{
2015-02-17 19:55:09 +00:00
// Check if the obj still exists, an object could be have been removed in this loop.
if ( ! obj )
2015-03-22 09:22:15 +00:00
continue ;
2015-02-17 19:55:09 +00:00
2012-05-01 18:50:21 +00:00
if ( obj - > GetCategory ( ) & C4D_Living )
if ( ! obj - > GetAlive ( ) )
continue ;
2012-04-22 11:08:54 +00:00
2012-04-28 14:17:38 +00:00
var inf = obj . ContactIncinerate ;
2012-05-01 18:50:21 +00:00
if ( ! inf )
continue ;
var amount = ( effect . strength / 3 ) / Max ( 1 , inf ) ;
2012-04-22 11:08:54 +00:00
2012-05-01 18:50:21 +00:00
if ( ! amount )
continue ;
2012-10-23 22:42:05 +00:00
var old_fire_value = obj - > OnFire ( ) ;
2018-06-23 08:02:16 +00:00
if ( old_fire_value < 100 ) // only if the object was not already fully ablaze
2012-10-23 22:42:05 +00:00
{
// incinerate the other object a bit
2018-06-23 08:02:16 +00:00
if ( obj - > Incinerate ( Max ( 10 , amount ) , effect . caused_by , false , effect . incinerating_obj ) )
{
// Incinerating other objects weakens the own fire.
// This is done in order to make fires spread slower especially as a chain reaction.
var min = Min ( 10 , effect . strength ) ;
if ( effect . strength > 50 ) min = 50 ;
effect . strength = BoundBy ( effect . strength - amount / 2 , min , 100 ) ;
}
2012-10-23 22:42:05 +00:00
}
2012-04-22 11:08:54 +00:00
}
2011-03-12 18:29:25 +00:00
}
}
// causes on object
//target->ExecFire(effect_number, caused_by);
2012-05-01 18:50:21 +00:00
if ( target - > GetAlive ( ) )
2011-03-12 18:29:25 +00:00
{
2012-04-10 21:28:41 +00:00
target - > DoEnergy ( - effect . strength * 4 , true , FX_Call_EngFire , effect . caused_by ) ;
2011-03-12 18:29:25 +00:00
}
else
{
2015-03-22 09:22:15 +00:00
if ( ( time * 10 ) % 120 < = effect . strength )
2011-03-12 18:29:25 +00:00
{
2014-04-06 15:15:13 +00:00
target - > DoDamage ( 2 , FX_Call_DmgFire , effect . caused_by ) ;
2018-03-14 15:38:33 +00:00
if ( target & & ! Random ( 2 ) & & ! target . NoBurnDecay )
2015-03-22 09:22:15 +00:00
{
2012-05-01 18:50:21 +00:00
target - > DoCon ( - 1 ) ;
2015-03-23 18:50:29 +00:00
if ( target )
EffectCall ( target , effect , " UpdateEffectProperties " ) ;
2015-03-22 09:22:15 +00:00
}
2011-03-12 18:29:25 +00:00
}
}
2012-05-01 18:50:21 +00:00
if ( ! target )
return FX_Execute_Kill ;
if ( target - > Contained ( ) )
return FX_OK ;
2015-03-22 09:22:15 +00:00
// Fire particles
// Fire denses, smoke, chaotic sparks
if ( time % effect . FreqReduction = = 0 )
2011-03-12 18:29:25 +00:00
{
2015-03-22 09:22:15 +00:00
// A few red fire particles popping up in the higher area. Does not affect very small flames.
if ( effect . fire_width + effect . fire_height > 40 )
{
if ( ! Random ( 2 ) ) CreateParticle ( " FireDense " , PV_Random ( - effect . fire_width , effect . pspeed ) , PV_Random ( effect . pspeed , effect . fire_height ) , PV_Random ( - 3 , 3 ) , effect . pspeed , effect . fire_height / 2 + 6 , effect . redfiredense ) ;
if ( ! Random ( 2 ) ) CreateParticle ( " FireDense " , PV_Random ( effect . fire_width / 2 , effect . fire_width ) , PV_Random ( effect . pspeed , effect . fire_height ) , PV_Random ( - 3 , 3 ) , effect . pspeed , effect . fire_height / 2 + 6 , effect . redfiredense ) ;
}
// Smoke
CreateParticle ( " SmokeThick " , PV_Random ( - effect . fire_width , effect . fire_width ) , - effect . fire_height , 0 , - 6 , 300 , effect . smoke ) ;
// Chaotic particles
if ( ! Random ( 3 ) & & effect . FreqReduction < 14 )
CreateParticle ( " Magic " , PV_Random ( - effect . fire_width , effect . fire_width ) , PV_Random ( - effect . fire_height , effect . fire_height ) , PV_Random ( 25 , - 25 ) , PV_Random ( - 25 , 12 ) , 50 , effect . chaoticspark ) ;
2011-03-12 19:49:36 +00:00
2015-03-22 09:22:15 +00:00
// Flameborders and sharp flames
2013-11-28 22:30:11 +00:00
2015-03-22 09:22:15 +00:00
// Flame borders
if ( effect . border_active )
{
CreateParticle ( " FireBorder " , 0 , effect . maxhgt , 0 , effect . pspeed , 30 , effect . flameborder ) ;
}
2013-11-28 22:30:11 +00:00
2015-03-22 09:22:15 +00:00
// Sharp flames
CreateParticle ( " FireSharp " , 0 , effect . maxhgt , 0 , effect . pspeed , 30 , effect . sharpflame ) ;
}
2011-03-12 18:29:25 +00:00
return FX_OK ;
}
2012-05-12 12:42:20 +00:00
global func FxFireStop ( object target , proplist effect , int reason , bool temp )
2011-03-12 18:29:25 +00:00
{
// safety
2012-05-01 18:50:21 +00:00
if ( ! target )
return false ;
2011-03-12 18:29:25 +00:00
// only if real removal is done
if ( temp )
{
return true ;
}
// stop sound
2012-05-12 12:42:20 +00:00
if ( effect . fire_sound )
2015-12-13 21:14:55 +00:00
target - > Sound ( " Fire::Fire " , false , 100 , nil , - 1 ) ;
2013-03-27 20:33:33 +00:00
// callback
target - > ~ Extinguishing ( ) ;
2011-03-12 18:29:25 +00:00
// done, success
return true ;
}
global func FxFireInfo ( object target , effect )
{
return Format ( " Is on %d%% fire. " , effect . strength ) ; // todo: <--
2012-05-06 13:37:43 +00:00
}