Explode: DoShockwave

Added the global function DoShockwave. Updated documentation. Changed the way explosions deal damage: Every object at the center of the explosion gets full damage. Every object inside the explosion radius gets half damage.

(cherry picked from commit 22298a6d1389b5344ebe7aea56f3c371b5ad845f)

Conflicts:
	planet/System.ocg/Explode.c
shapetextures
Mark 2015-09-13 00:22:28 +02:00
parent 15056b823f
commit 722a5ad448
2 changed files with 115 additions and 59 deletions

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>DoShockwave</title>
<category>Objects</category>
<version>7.0 OC</version>
<syntax>
<rtype>nil</rtype>
<params>
<param>
<type>int</type>
<name>x</name>
<desc>X coordinate</desc>
</param>
<param>
<type>int</type>
<name>y</name>
<desc>Y coordinate</desc>
</param>
<param>
<type>int</type>
<name>radius</name>
<desc>Radius and strength of the shock wave.</desc>
</param>
<param>
<type>int</type>
<name>caused_by</name>
<optional />
<desc>Number of the player who has caused the shock wave. If not specified, the the controller of the calling object is considered to have caused the damage in local calls.</desc>
</param>
</params>
</syntax>
<desc>Flings all objects at the specified position in the specified radius. Has no visual effect. The x and y coordinates are always global coordinates.</desc>
<examples>
<example>
<code>DoShockwave(<funclink>GetX</funclink>(), <funclink>GetY</funclink>(), 35);</code>
<text>The calling object causes a shock wave that extends 35 pixels.</text>
</example>
</examples>
<related>
<funclink>Explode</funclink>
</related>
</func>
<author>Marky</author><date>2015-07</date>
</funcs>

View File

@ -283,15 +283,52 @@ global func BlastObjects(int x, int y, int level, object container, int cause_pl
else
{
// Object is outside.
var at_rect = Find_AtRect(l_x - 5, l_y - 5, 10, 10);
// Damage objects at point of explosion.
for (var obj in FindObjects(Find_AtRect(l_x - 5, l_y - 5, 10,10), Find_NoContainer(), Find_Layer(layer), Find_Exclude(no_blast)))
for (var obj in FindObjects(at_rect, Find_NoContainer(), Find_Layer(layer), Find_Exclude(no_blast)))
if (obj) obj->BlastObject(damage_level, cause_plr);
// TODO: -> Shockwave in own global func(?)
// Damage objects in radius.
for (var obj in FindObjects(Find_Distance(level, l_x, l_y), Find_Not(at_rect), Find_NoContainer(), Find_Layer(layer), Find_Exclude(no_blast)))
if (obj) obj->BlastObject(damage_level / 2, cause_plr);
DoShockwave(x, y, level, cause_plr, layer);
}
// Done.
return true;
}
global func BlastObject(int level, int caused_by)
{
var self = this;
if (caused_by == nil)
caused_by = GetController();
DoDamage(level, FX_Call_DmgBlast, caused_by);
if (!self) return;
if (GetAlive())
DoEnergy(-level, false, FX_Call_EngBlast, caused_by);
if (!self) return;
if (this.BlastIncinerate && GetDamage() >= this.BlastIncinerate)
Incinerate(level, caused_by);
return;
}
global func DoShockwave(int x, int y, int level, int cause_plr, object layer)
{
// Coordinates are always supplied globally, convert to local coordinates.
var l_x = x - GetX(), l_y = y - GetY();
// caused by: if not specified, controller of calling object
if (cause_plr == nil)
if (this)
cause_plr = GetController();
// Hurl objects in explosion radius.
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));
Find_Or(Find_Category(C4D_Object|C4D_Living|C4D_Vehicle), Find_Func("CanBeHitByShockwaves")), Find_Func("DoShockwaveCheck", x, y));
var cnt = GetLength(shockwave_objs);
if (cnt)
{
@ -301,18 +338,10 @@ global func BlastObjects(int x, int y, int level, object container, int cause_pl
for (var obj in shockwave_objs)
if (obj) // Test obj, cause OnShockwaveHit could have removed objects.
{
// Object has special reaction on shockwave?
if (obj->~OnShockwaveHit(level, x, y, cause_plr, damage_level))
continue;
// Living beings are hurt more.
var cat = obj->GetCategory();
if (cat & C4D_Living)
{
obj->DoEnergy(damage_level / -2, false, FX_Call_EngBlast, cause_plr);
if (!obj) continue;
obj->DoDamage(damage_level / 2, FX_Call_DmgBlast, cause_plr);
if (!obj) continue;
}
// Object has special reaction on shockwave?
if (obj->~OnShockwaveHit(level, x, y, cause_plr))
continue;
// Killtracing for projectiles.
if (cat & C4D_Object)
obj->SetController(cause_plr);
@ -344,29 +373,8 @@ global func BlastObjects(int x, int y, int level, object container, int cause_pl
}
}
}
// Done.
return true;
}
global func BlastObject(int level, int caused_by)
{
var self = this;
if (caused_by == nil)
caused_by = GetController();
DoDamage(level, FX_Call_DmgBlast, caused_by);
if (!self) return;
if (GetAlive())
DoEnergy(-level/3, false, FX_Call_EngBlast, caused_by);
if (!self) return;
if (this.BlastIncinerate && GetDamage() >= this.BlastIncinerate)
Incinerate(level, caused_by);
return;
}
global func BlastObjectsShockwaveCheck(int x, int y)
global func DoShockwaveCheck(int x, int y)
{
var def = GetID();
// Some special cases, which won't go into FindObjects.