improve dynamite box explosion in lava (delay) and igniter handling

stable-6.1 v6.0
Maikel de Vries 2015-03-12 22:21:51 +01:00
parent 5b12d6c240
commit f9e4b0568b
5 changed files with 186 additions and 209 deletions

View File

@ -1,9 +1,9 @@
/*
/**
Dynamite
Author: Newton
A volatile tool that can be pressed into wallsfor accurate
mining, burning a short fuse before exploding.
A volatile tool that can be pressed into walls
for accurate mining, burning a short fuse before exploding.
@author Newton
*/
// time in frames until explosion
@ -83,17 +83,15 @@ public func Fuse()
// returns true if there is a wall in direction in which "clonk" looks
// and puts the offset to the wall into "xo, yo" - looking from the clonk
private func GetWall(angle)
private func GetWall(int angle)
{
var dist = 12;
for(var dist = 12; dist < 18; dist++)
for (var dist = 12; dist < 18; dist++)
{
var x = Sin(angle, dist);
var y = -Cos(angle, dist);
if(GBackSolid(x, y))
{
if (GBackSolid(x, y))
return [Sin(angle, dist-5), -Cos(angle, dist-5)];
}
}
return false;
}
@ -132,18 +130,19 @@ private func Fusing()
var x = Sin(GetR(), 5);
var y = -Cos(GetR(), 5);
if(Contained()!=nil)
if (Contained()!=nil)
{
//If the dynamite is held, sparks come from clonk's center.
x = y = 0;
}
// Effekt
if(GetActTime() < FuseTime() - 20)
// Effect: fire particles.
if (GetActTime() < FuseTime() - 20)
CreateParticle("Fire", x, y, PV_Random(x - 5, x + 5), PV_Random(y - 15, y + 5), PV_Random(10, 40), Particles_Glimmer(), 3);
// Explosion
else if(GetActTime() > FuseTime())
// Explosion: after fusetime is over.
else if (GetActTime() > FuseTime())
DoExplode();
return;
}
public func OnFuseFinished()
@ -153,8 +152,8 @@ public func OnFuseFinished()
public func DoExplode()
{
// Activate all fuses
for(var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this)))
// Activate all fuses.
for (var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this)))
obj->~StartFusing(this);
Explode(26);
}
@ -162,6 +161,9 @@ public func DoExplode()
public func IsChemicalProduct() { return true; }
public func IsGrenadeLauncherAmmo() { return true; }
/*-- Properties --*/
local ActMap = {
Fuse = {
Prototype = Action,

View File

@ -1,51 +1,36 @@
/*--- Fuse ---*/
/**
Dynamite Fuse
Line object that connects the dynamite sticks with the igniter.
@author Newton, Maikel
*/
local fHasMessage;
protected func Initialize ()
protected func Initialize()
{
SetProperty("LineColors", [RGB(100,50,0), RGB(1,1,1)]);
// Put the first to vertices on the actual position
SetVertex(0,0,GetX()); SetVertex(0,1,GetY());
SetVertex(1,0,GetX()); SetVertex(1,1,GetY());
fuse_dir = 0;
SetProperty("LineColors", [RGB(100, 50, 0), RGB(1, 1, 1)]);
// Put the first to vertices on the actual position.
SetVertex(0, 0, GetX()); SetVertex(0, 1, GetY());
SetVertex(1, 0, GetX()); SetVertex(1, 1, GetY());
return;
}
public func SetColorWarning(fOn)
{
if(!fOn)
SetProperty("LineColors", [RGB(100,50,0), RGB(1,1,1)]);
else
SetProperty("LineColors", [RGB(200,100,0), RGB(1,1,1)]);
}
public func IsFuse() { return true; }
public func Connect(pTarget1, pTarget2)
public func Connect(object target1, object target2)
{
SetAction("Connect", pTarget1, pTarget2);
SetAction("Connect", target1, target2);
}
private func GetLineLength()
{
var i = GetVertexNum()-1;
var iDist = 0;
while(i--)
{
// Calculate the length between the vertices
iDist += Distance(GetVertex(i,0),GetVertex(i,1),GetVertex(i+1,0),GetVertex(i+1,1));
}
return iDist;
}
local fuse_vertex;
local fuse_x;
local fuse_y;
local fuse_call;
local fuse_dir;
public func StartFusing(object controler)
{
if(fuse_dir != 0) return RemoveObject();
if(GetActionTarget(0) == controler)
if (GetEffect("IntFusing", this))
return RemoveObject();
var fuse_dir;
var fuse_call;
var fuse_vertex;
if (GetActionTarget(0) == controler)
{
fuse_dir = +1;
fuse_call = GetActionTarget(1);
@ -57,70 +42,88 @@ public func StartFusing(object controler)
fuse_call = GetActionTarget(0);
fuse_vertex = GetVertexNum()-1;
}
fuse_x = GetVertex(fuse_vertex, 0)*10;
fuse_y = GetVertex(fuse_vertex, 1)*10;
AddEffect("IntFusing", this, 1, 1, this);
SetAction("Fusing");
Sound("FuseLoop",false,75,nil,1);
var effect = AddEffect("IntFusing", this, 100, 1, this);
effect.fuse_dir = fuse_dir;
effect.fuse_call = fuse_call;
effect.fuse_vertex = fuse_vertex;
effect.fuse_x = GetVertex(fuse_vertex, VTX_X) * 10;
effect.fuse_y = GetVertex(fuse_vertex, VTX_Y) * 10;
return;
}
func FxIntFusingTimer()
protected func FxIntFusingStart(object target, proplist effect, int temporary)
{
var target_x = GetVertex(fuse_vertex+fuse_dir, 0)*10, target_y = GetVertex(fuse_vertex+fuse_dir, 1)*10;
if (temporary)
return FX_OK;
SetAction("Fusing");
Sound("FuseLoop", false, 75, nil, 1);
return FX_OK;
}
protected func FxIntFusingTimer(object target, proplist effect, int time)
{
var target_x = GetVertex(effect.fuse_vertex + effect.fuse_dir, VTX_X) * 10;
var target_y = GetVertex(effect.fuse_vertex + effect.fuse_dir, VTX_Y)*10;
var speed = 20;
if(Distance(fuse_x, fuse_y, target_x, target_y) < speed)
if (Distance(effect.fuse_x, effect.fuse_y, target_x, target_y) < speed)
{
RemoveVertex(fuse_vertex);
if(fuse_dir == -1) fuse_vertex--;
speed -= Distance(fuse_x, fuse_y, target_x, target_y);
if( (fuse_vertex == 0 && fuse_dir == -1) || (fuse_vertex == GetVertexNum()-1 && fuse_dir == +1))
RemoveVertex(effect.fuse_vertex);
if (effect.fuse_dir == -1)
effect.fuse_vertex--;
speed -= Distance(effect.fuse_x, effect.fuse_y, target_x, target_y);
if ((effect.fuse_vertex == 0 && effect.fuse_dir == -1) || (effect.fuse_vertex == GetVertexNum() - 1 && effect.fuse_dir == +1))
{
if (fuse_call)
fuse_call->~OnFuseFinished(this);
if (fuse_call)
if (effect.fuse_call)
effect.fuse_call->~OnFuseFinished(this);
if (effect.fuse_call)
RemoveObject();
return -1;
return FX_Execute_Kill;
}
fuse_x = GetVertex(fuse_vertex, 0)*10;
fuse_y = GetVertex(fuse_vertex, 1)*10;
target_x = GetVertex(fuse_vertex+fuse_dir, 0)*10;
target_y = GetVertex(fuse_vertex+fuse_dir, 1)*10;
effect.fuse_x = GetVertex(effect.fuse_vertex, VTX_X) * 10;
effect.fuse_y = GetVertex(effect.fuse_vertex, VTX_Y) * 10;
target_x = GetVertex(effect.fuse_vertex + effect.fuse_dir, VTX_X) * 10;
target_y = GetVertex(effect.fuse_vertex + effect.fuse_dir, VTX_Y) * 10;
}
// Move spark position
var iAngle = Angle(fuse_x, fuse_y, target_x, target_y);
fuse_x += Sin(iAngle, speed);
fuse_y +=-Cos(iAngle, speed);
var angle = Angle(effect.fuse_x, effect.fuse_y, target_x, target_y);
effect.fuse_x += Sin(angle, speed);
effect.fuse_y +=-Cos(angle, speed);
CreateParticle("Fire", fuse_x/10-GetX(), fuse_y/10-GetY(), PV_Random(-10, 10), PV_Random(-10, 10), PV_Random(10, 40), Particles_Glimmer(), 3);
SetVertexXY(fuse_vertex, fuse_x/10, fuse_y/10);
CreateParticle("Fire", effect.fuse_x / 10 - GetX(), effect.fuse_y / 10 - GetY(), PV_Random(-10, 10), PV_Random(-10, 10), PV_Random(10, 40), Particles_Glimmer(), 3);
SetVertexXY(effect.fuse_vertex, effect.fuse_x / 10, effect.fuse_y / 10);
return FX_OK;
}
func FxIntFusingStop()
protected func FxIntFusingStop(object target, proplist effect, int reason, bool temporary)
{
Sound("FuseLoop",false,75,nil,-1);
if (temporary)
return FX_OK;
Sound("FuseLoop", false, 75, nil, -1);
return FX_OK;
}
// Only the main dynamite pack is stored.
public func SaveScenarioObject() { return false;}
public func IsFuse() { return true; }
/*-- Properties --*/
local ActMap = {
Connect = {
Connect = {
Prototype = Action,
Name = "Connect",
Length = 0,
Delay = 0,
Procedure = DFA_CONNECT,
NextAction = "Connect",
},
Fusing = {
},
Fusing = {
Prototype = Action,
Name = "Fusing",
Length = 0,
Delay = 0,
Procedure = DFA_NONE,//CONNECT,
Procedure = DFA_NONE,
NextAction = "Fusing",
},
};

View File

@ -1,4 +1,9 @@
/*-- Dynamite Igniter --*/
/**
Dynamite Igniter
Can be used to ignite dynamite from a distance.
@author Newton
*/
#include DynamiteBox
@ -10,67 +15,67 @@ private func Hit()
public func HoldingEnabled() { return true; }
public func GetCarryMode() { return CARRY_BothHands; }
public func GetCarryPhase() { return 250; }
public func GetCarrySpecial(clonk) { if(fIgnite) return "pos_hand2"; }
public func GetCarrySpecial(clonk)
{
if (ignited)
return "pos_hand2";
}
local fIgnite;
local aDynamites;
local aWires;
local ignited;
local dynamite_sticks;
local wires;
public func ControlUse(object clonk, int x, int y)
{
if(clonk->GetAction() != "Walk") return true;
if (clonk->GetAction() != "Walk")
return true;
fIgnite = 1;
ignited = 1;
// The clonk has to stand
// The clonk has to stand.
clonk->SetAction("Stand");
clonk->SetXDir(0);
var iIgniteTime = 35*2;
clonk->PlayAnimation("DoIgnite", 10, Anim_Linear(0, 0, clonk->GetAnimationLength("DoIgnite"), iIgniteTime, ANIM_Hold), Anim_Const(1000));
PlayAnimation("Ignite", 1, Anim_Linear(0, 0, GetAnimationLength("Ignite"), iIgniteTime, ANIM_Hold), Anim_Const(1000));
var ignite_time = 40;
clonk->PlayAnimation("DoIgnite", 10, Anim_Linear(0, 0, clonk->GetAnimationLength("DoIgnite"), ignite_time, ANIM_Hold), Anim_Const(1000));
PlayAnimation("Ignite", 1, Anim_Linear(0, 0, GetAnimationLength("Ignite"), ignite_time, ANIM_Hold), Anim_Const(1000));
ScheduleCall(this, "Ignite", iIgniteTime, 1, clonk);
RemoveEffect("IntLength", this);
ScheduleCall(this, "Ignite", ignite_time, 1, clonk);
return true;
}
local iIgniteNumber;
local pIgniteClonk;
public func Ignite(clonk)
public func Ignite(object clonk)
{
iIgniteNumber = 0;
pIgniteClonk = clonk;
if (aWires[iIgniteNumber])
aWires[iIgniteNumber]->StartFusing(this);
if (wires[0])
wires[0]->StartFusing(this);
else
for (var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this)))
obj->~StartFusing(this);
ScheduleCall(this, "ResetClonk", 35, 1, clonk);
ScheduleCall(this, "ResetClonk", 12, 1, clonk);
return;
}
public func OnFuseFinished()
{
if(Contained() != nil) ResetClonk(Contained());
else RemoveObject();
if (Contained() != nil)
return ResetClonk(Contained());
return RemoveObject();
}
public func ResetClonk(clonk)
public func ResetClonk(object clonk)
{
StopAnimation(GetRootAnimation(1));
// Reset animation
// Reset animation of the clonk.
clonk->StopAnimation(clonk->GetRootAnimation(10));
clonk->SetAction("Walk");
clonk->DetachObject(this);
// Reset animation of the igniter and remove it.
StopAnimation(GetRootAnimation(1));
RemoveObject();
return;
}
// Only the main dynamite box is stored.
@ -80,6 +85,9 @@ public func IsTool() { return true; }
public func IsToolProduct() { return false; }
public func IsAlchemyProduct() { return false; }
/*-- Properties --*/
func Definition(def) {
SetProperty("PictureTransformation",Trans_Mul(Trans_Rotate(-25, 1, 0, 0), Trans_Rotate(40, 0, 1, 0)), def);
}

View File

@ -1,21 +1,32 @@
/*-- Dynamite box --*/
/**
Dynamite box
Contains five dynamite sticks which can be placed and detonated from a distance.
@author Newton
*/
static const DYNA_MaxLength = 500;
static const DYNA_MaxCount = 5;
local count;
local dynamite_sticks;
local wires;
local wire;
public func Initialize()
{
iCount = DYNA_MaxCount;
aDynamites = CreateArray(iCount);
aWires = CreateArray(iCount);
for(var i = 0; i < iCount; i++)
count = DYNA_MaxCount;
dynamite_sticks = [];
wires = [];
for (var i = 0; i < count; i++)
{
aDynamites[i] = nil;
aWires[i] = nil;
dynamite_sticks[i] = nil;
wires[i] = nil;
}
this.PictureTransformation = Trans_Scale(); // Hide it TODO: Remove if the mesh isn't shown if there is a picture set
UpdatePicture();
return;
}
private func Hit()
@ -28,38 +39,27 @@ public func HoldingEnabled() { return true; }
public func GetCarryMode() { return CARRY_BothHands; }
public func GetCarryPhase() { return 450; }
local iCount;
local aDynamites;
local aWires;
local pWire;
public func ControlUse(object clonk, int x, int y)
{
var pDyna = aDynamites[iCount-1] = CreateContents(Dynamite);
if(!pDyna->ControlUse(clonk, x, y, 1))
var dynamite = dynamite_sticks[count - 1] = CreateContents(Dynamite);
if (!dynamite->ControlUse(clonk, x, y, 1))
{
pDyna->RemoveObject();
dynamite->RemoveObject();
return true;
}
if(pWire)
pWire->Connect(aDynamites[iCount], pDyna);
// First? then add Timer
/* else
AddEffect("IntLength", this, 1, 10, this);*/
if(wire)
wire->Connect(dynamite_sticks[count], dynamite);
pWire = CreateObjectAbove(Fuse);
pWire->Connect(pDyna, this);
wire = CreateObject(Fuse);
wire->Connect(dynamite, this);
Sound("Connect");
aWires[iCount-1] = pWire;
wires[count - 1] = wire;
iCount--;
count--;
UpdatePicture();
// Message("%d left", iCount);
if(iCount == 0)
if (count == 0)
{
var pos = clonk->GetItemPos(this);
ChangeDef(Igniter);
@ -76,58 +76,10 @@ private func UpdatePicture()
var s = 400;
var yoffs = 14000;
var xoffs = 22000;
SetGraphics(Format("%d", iCount), Icon_Number, 12, GFXOV_MODE_Picture);
SetGraphics(Format("%d", count), Icon_Number, 12, GFXOV_MODE_Picture);
SetObjDrawTransform(s, 0, xoffs, 0, s, yoffs, 12);
SetGraphics(Format("%d", 6 - iCount), DynamiteBox, 1, GFXOV_MODE_Picture);
}
local fWarning;
local fWarningColor;
func FxIntLengthTimer(pTarget, effect, iTime)
{
var iLength = 0;
var i = GetLength(aWires)-1;
while(i >= 0 && aWires[i])
{
iLength += aWires[i]->GetLineLength();
i--;
}
if(iLength > DYNA_MaxLength*4/5)
{
fWarning = 1;
// Message("Line too long! %d%%", iLength*100/DYNA_MaxLength);
if( (iTime % 5) == 0)
{
var fOn = 1;
if( fWarningColor == 1) fOn = 0;
fWarningColor = fOn;
// for(var i = 0; i < GetLength(aWires); i++)
// if(aWires[i]) aWires[i]->SetColorWarning(fOn);
}
}
else if(fWarning)
{
fWarning = 0;
// for(var i = 0; i < GetLength(aWires); i++)
// if(aWires[i]) aWires[i]->SetColorWarning(0);
}
if(iLength > DYNA_MaxLength)
{
var iMax = GetLength(aWires)-1;
aWires[iMax]->RemoveObject();
aDynamites[iMax]->Reset();
SetLength(aWires, iMax);
SetLength(aDynamites, iMax);
// Message("Line too long,|lost dynamite!|%d left.", iMax);
if(iMax == 0)
{
Contained()->Message("Line broken.");
RemoveObject();
}
}
SetGraphics(Format("%d", 6 - count), DynamiteBox, 1, GFXOV_MODE_Picture);
return;
}
public func OnFuseFinished()
@ -137,31 +89,40 @@ public func OnFuseFinished()
public func DoExplode()
{
// Activate all fuses
for(var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this)))
// Activate all fuses.
for (var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this)))
obj->~StartFusing(this);
// Explode, calc the radius out of the area of a explosion of a single dynamite times the amount of dynamite
// This results to 18, 25, 31, 36, and 40
Explode(Sqrt(18**2*iCount));
Explode(Sqrt(18**2*count));
}
protected func Incineration() { Damage(); }
protected func Incineration()
{
AddEffect("Fuse", this, 100, 1, this);
Sound("Fuse");
return;
}
protected func Damage()
{
// Explode with 1 frame delay to prevent deep script call recursion if lots of dynamite boxes in the same place explode
if (!this.exploding) this.exploding = ScheduleCall(this, this.DoExplode, 1, 1);
Incinerate();
}
func FxIntLengthStop(pTarget, effect, iReason, fTmp)
public func FxFuseTimer(object target, effect, int timer)
{
for(var i = 0; i < GetLength(aWires); i++)
if(aWires[i]) aWires[i]->SetColorWarning(0);
CreateParticle("Fire", 0, 0, PV_Random(-10, 10), PV_Random(-20, 10), PV_Random(10, 40), Particles_Glimmer(), 6);
if (timer > 90)
DoExplode();
return FX_OK;
}
public func IsTool() { return true; }
public func IsChemicalProduct() { return true; }
/*-- Properties --*/
func Definition(def) {
SetProperty("PictureTransformation", Trans_Mul(Trans_Rotate(150, 1, 0, 0), Trans_Rotate(140, 0, 1, 0)), def);
}

View File

@ -1,9 +1,9 @@
/*--
Powder Keg
Author: Ringwaul
A barrel filled with black powder.
--*/
@author Ringwaul
*/
#include Library_CarryHeavy
@ -108,9 +108,9 @@ public func FxFuseTimer(object target, effect, int timer)
}
}
public func IsProjectileTarget(target,shooter)
public func IsProjectileTarget()
{
return 1;
return true;
}
public func Damage()
@ -139,6 +139,9 @@ public func SaveScenarioObject(props)
func IsChemicalProduct() { return true; }
func AlchemyProcessTime() { return 100; }
/*-- Properties --*/
local Collectible = false;
local Touchable = 2;
local Name = "$Name$";