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 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 @author Newton
for accurate mining, burning a short fuse before exploding.
*/ */
// time in frames until explosion // 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 // 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 // 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; var dist = 12;
for(var dist = 12; dist < 18; dist++) for (var dist = 12; dist < 18; dist++)
{ {
var x = Sin(angle, dist); var x = Sin(angle, dist);
var y = -Cos(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 [Sin(angle, dist-5), -Cos(angle, dist-5)];
}
} }
return false; return false;
} }
@ -132,18 +130,19 @@ private func Fusing()
var x = Sin(GetR(), 5); var x = Sin(GetR(), 5);
var y = -Cos(GetR(), 5); var y = -Cos(GetR(), 5);
if(Contained()!=nil) if (Contained()!=nil)
{ {
//If the dynamite is held, sparks come from clonk's center. //If the dynamite is held, sparks come from clonk's center.
x = y = 0; x = y = 0;
} }
// Effekt // Effect: fire particles.
if(GetActTime() < FuseTime() - 20) 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); CreateParticle("Fire", x, y, PV_Random(x - 5, x + 5), PV_Random(y - 15, y + 5), PV_Random(10, 40), Particles_Glimmer(), 3);
// Explosion // Explosion: after fusetime is over.
else if(GetActTime() > FuseTime()) else if (GetActTime() > FuseTime())
DoExplode(); DoExplode();
return;
} }
public func OnFuseFinished() public func OnFuseFinished()
@ -153,8 +152,8 @@ public func OnFuseFinished()
public func DoExplode() public func DoExplode()
{ {
// Activate all fuses // Activate all fuses.
for(var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this))) for (var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this)))
obj->~StartFusing(this); obj->~StartFusing(this);
Explode(26); Explode(26);
} }
@ -162,6 +161,9 @@ public func DoExplode()
public func IsChemicalProduct() { return true; } public func IsChemicalProduct() { return true; }
public func IsGrenadeLauncherAmmo() { return true; } public func IsGrenadeLauncherAmmo() { return true; }
/*-- Properties --*/
local ActMap = { local ActMap = {
Fuse = { Fuse = {
Prototype = Action, 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)]); SetProperty("LineColors", [RGB(100, 50, 0), RGB(1, 1, 1)]);
// Put the first to vertices on the actual position // Put the first to vertices on the actual position.
SetVertex(0,0,GetX()); SetVertex(0,1,GetY()); SetVertex(0, 0, GetX()); SetVertex(0, 1, GetY());
SetVertex(1,0,GetX()); SetVertex(1,1,GetY()); SetVertex(1, 0, GetX()); SetVertex(1, 1, GetY());
fuse_dir = 0; return;
} }
public func SetColorWarning(fOn) public func IsFuse() { return true; }
{
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 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) public func StartFusing(object controler)
{ {
if(fuse_dir != 0) return RemoveObject(); if (GetEffect("IntFusing", this))
if(GetActionTarget(0) == controler) return RemoveObject();
var fuse_dir;
var fuse_call;
var fuse_vertex;
if (GetActionTarget(0) == controler)
{ {
fuse_dir = +1; fuse_dir = +1;
fuse_call = GetActionTarget(1); fuse_call = GetActionTarget(1);
@ -57,70 +42,88 @@ public func StartFusing(object controler)
fuse_call = GetActionTarget(0); fuse_call = GetActionTarget(0);
fuse_vertex = GetVertexNum()-1; fuse_vertex = GetVertexNum()-1;
} }
fuse_x = GetVertex(fuse_vertex, 0)*10; var effect = AddEffect("IntFusing", this, 100, 1, this);
fuse_y = GetVertex(fuse_vertex, 1)*10; effect.fuse_dir = fuse_dir;
AddEffect("IntFusing", this, 1, 1, this); effect.fuse_call = fuse_call;
SetAction("Fusing"); effect.fuse_vertex = fuse_vertex;
Sound("FuseLoop",false,75,nil,1); 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; 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); RemoveVertex(effect.fuse_vertex);
if(fuse_dir == -1) fuse_vertex--; if (effect.fuse_dir == -1)
speed -= Distance(fuse_x, fuse_y, target_x, target_y); effect.fuse_vertex--;
if( (fuse_vertex == 0 && fuse_dir == -1) || (fuse_vertex == GetVertexNum()-1 && fuse_dir == +1)) 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) if (effect.fuse_call)
fuse_call->~OnFuseFinished(this); effect.fuse_call->~OnFuseFinished(this);
if (fuse_call) if (effect.fuse_call)
RemoveObject(); RemoveObject();
return -1; return FX_Execute_Kill;
} }
fuse_x = GetVertex(fuse_vertex, 0)*10; effect.fuse_x = GetVertex(effect.fuse_vertex, VTX_X) * 10;
fuse_y = GetVertex(fuse_vertex, 1)*10; effect.fuse_y = GetVertex(effect.fuse_vertex, VTX_Y) * 10;
target_x = GetVertex(fuse_vertex+fuse_dir, 0)*10; target_x = GetVertex(effect.fuse_vertex + effect.fuse_dir, VTX_X) * 10;
target_y = GetVertex(fuse_vertex+fuse_dir, 1)*10; target_y = GetVertex(effect.fuse_vertex + effect.fuse_dir, VTX_Y) * 10;
} }
// Move spark position // Move spark position
var iAngle = Angle(fuse_x, fuse_y, target_x, target_y); var angle = Angle(effect.fuse_x, effect.fuse_y, target_x, target_y);
fuse_x += Sin(iAngle, speed); effect.fuse_x += Sin(angle, speed);
fuse_y +=-Cos(iAngle, 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); 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(fuse_vertex, fuse_x/10, fuse_y/10); 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. // Only the main dynamite pack is stored.
public func SaveScenarioObject() { return false;} public func SaveScenarioObject() { return false;}
public func IsFuse() { return true; }
/*-- Properties --*/
local ActMap = { local ActMap = {
Connect = { Connect = {
Prototype = Action, Prototype = Action,
Name = "Connect", Name = "Connect",
Length = 0, Length = 0,
Delay = 0, Delay = 0,
Procedure = DFA_CONNECT, Procedure = DFA_CONNECT,
NextAction = "Connect", NextAction = "Connect",
}, },
Fusing = { Fusing = {
Prototype = Action, Prototype = Action,
Name = "Fusing", Name = "Fusing",
Length = 0, Length = 0,
Delay = 0, Delay = 0,
Procedure = DFA_NONE,//CONNECT, Procedure = DFA_NONE,
NextAction = "Fusing", 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 #include DynamiteBox
@ -10,67 +15,67 @@ private func Hit()
public func HoldingEnabled() { return true; } public func HoldingEnabled() { return true; }
public func GetCarryMode() { return CARRY_BothHands; } public func GetCarryMode() { return CARRY_BothHands; }
public func GetCarryPhase() { return 250; } 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 ignited;
local aDynamites; local dynamite_sticks;
local aWires; local wires;
public func ControlUse(object clonk, int x, int y) 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->SetAction("Stand");
clonk->SetXDir(0); clonk->SetXDir(0);
var iIgniteTime = 35*2; var ignite_time = 40;
clonk->PlayAnimation("DoIgnite", 10, Anim_Linear(0, 0, clonk->GetAnimationLength("DoIgnite"), iIgniteTime, ANIM_Hold), Anim_Const(1000)); 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"), iIgniteTime, 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); ScheduleCall(this, "Ignite", ignite_time, 1, clonk);
RemoveEffect("IntLength", this);
return true; return true;
} }
local iIgniteNumber;
local pIgniteClonk;
public func Ignite(clonk) public func Ignite(object clonk)
{ {
iIgniteNumber = 0; if (wires[0])
wires[0]->StartFusing(this);
pIgniteClonk = clonk;
if (aWires[iIgniteNumber])
aWires[iIgniteNumber]->StartFusing(this);
else else
for (var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this))) for (var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this)))
obj->~StartFusing(this); obj->~StartFusing(this);
ScheduleCall(this, "ResetClonk", 35, 1, clonk); ScheduleCall(this, "ResetClonk", 12, 1, clonk);
return;
} }
public func OnFuseFinished() public func OnFuseFinished()
{ {
if(Contained() != nil) ResetClonk(Contained()); if (Contained() != nil)
else RemoveObject(); return ResetClonk(Contained());
return RemoveObject();
} }
public func ResetClonk(clonk) public func ResetClonk(object clonk)
{ {
StopAnimation(GetRootAnimation(1)); // Reset animation of the clonk.
// Reset animation
clonk->StopAnimation(clonk->GetRootAnimation(10)); clonk->StopAnimation(clonk->GetRootAnimation(10));
clonk->SetAction("Walk"); clonk->SetAction("Walk");
clonk->DetachObject(this); clonk->DetachObject(this);
// Reset animation of the igniter and remove it.
StopAnimation(GetRootAnimation(1));
RemoveObject(); RemoveObject();
return;
} }
// Only the main dynamite box is stored. // Only the main dynamite box is stored.
@ -80,6 +85,9 @@ public func IsTool() { return true; }
public func IsToolProduct() { return false; } public func IsToolProduct() { return false; }
public func IsAlchemyProduct() { return false; } public func IsAlchemyProduct() { return false; }
/*-- Properties --*/
func Definition(def) { func Definition(def) {
SetProperty("PictureTransformation",Trans_Mul(Trans_Rotate(-25, 1, 0, 0), Trans_Rotate(40, 0, 1, 0)), 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_MaxLength = 500;
static const DYNA_MaxCount = 5; static const DYNA_MaxCount = 5;
local count;
local dynamite_sticks;
local wires;
local wire;
public func Initialize() public func Initialize()
{ {
iCount = DYNA_MaxCount; count = DYNA_MaxCount;
aDynamites = CreateArray(iCount); dynamite_sticks = [];
aWires = CreateArray(iCount); wires = [];
for(var i = 0; i < iCount; i++) for (var i = 0; i < count; i++)
{ {
aDynamites[i] = nil; dynamite_sticks[i] = nil;
aWires[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 this.PictureTransformation = Trans_Scale(); // Hide it TODO: Remove if the mesh isn't shown if there is a picture set
UpdatePicture(); UpdatePicture();
return;
} }
private func Hit() private func Hit()
@ -28,38 +39,27 @@ public func HoldingEnabled() { return true; }
public func GetCarryMode() { return CARRY_BothHands; } public func GetCarryMode() { return CARRY_BothHands; }
public func GetCarryPhase() { return 450; } public func GetCarryPhase() { return 450; }
local iCount;
local aDynamites;
local aWires;
local pWire;
public func ControlUse(object clonk, int x, int y) public func ControlUse(object clonk, int x, int y)
{ {
var pDyna = aDynamites[iCount-1] = CreateContents(Dynamite); var dynamite = dynamite_sticks[count - 1] = CreateContents(Dynamite);
if(!pDyna->ControlUse(clonk, x, y, 1)) if (!dynamite->ControlUse(clonk, x, y, 1))
{ {
pDyna->RemoveObject(); dynamite->RemoveObject();
return true; return true;
} }
if(pWire) if(wire)
pWire->Connect(aDynamites[iCount], pDyna); wire->Connect(dynamite_sticks[count], dynamite);
// First? then add Timer
/* else
AddEffect("IntLength", this, 1, 10, this);*/
pWire = CreateObjectAbove(Fuse); wire = CreateObject(Fuse);
pWire->Connect(pDyna, this); wire->Connect(dynamite, this);
Sound("Connect"); Sound("Connect");
aWires[iCount-1] = pWire; wires[count - 1] = wire;
iCount--; count--;
UpdatePicture(); UpdatePicture();
// Message("%d left", iCount); if (count == 0)
if(iCount == 0)
{ {
var pos = clonk->GetItemPos(this); var pos = clonk->GetItemPos(this);
ChangeDef(Igniter); ChangeDef(Igniter);
@ -76,58 +76,10 @@ private func UpdatePicture()
var s = 400; var s = 400;
var yoffs = 14000; var yoffs = 14000;
var xoffs = 22000; var xoffs = 22000;
SetGraphics(Format("%d", count), Icon_Number, 12, GFXOV_MODE_Picture);
SetGraphics(Format("%d", iCount), Icon_Number, 12, GFXOV_MODE_Picture);
SetObjDrawTransform(s, 0, xoffs, 0, s, yoffs, 12); SetObjDrawTransform(s, 0, xoffs, 0, s, yoffs, 12);
SetGraphics(Format("%d", 6 - count), DynamiteBox, 1, GFXOV_MODE_Picture);
SetGraphics(Format("%d", 6 - iCount), DynamiteBox, 1, GFXOV_MODE_Picture); return;
}
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();
}
}
} }
public func OnFuseFinished() public func OnFuseFinished()
@ -137,31 +89,40 @@ public func OnFuseFinished()
public func DoExplode() public func DoExplode()
{ {
// Activate all fuses // Activate all fuses.
for(var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this))) for (var obj in FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this)))
obj->~StartFusing(this); obj->~StartFusing(this);
// Explode, calc the radius out of the area of a explosion of a single dynamite times the amount of dynamite // 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 // 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() protected func Damage()
{ {
// Explode with 1 frame delay to prevent deep script call recursion if lots of dynamite boxes in the same place explode Incinerate();
if (!this.exploding) this.exploding = ScheduleCall(this, this.DoExplode, 1, 1);
} }
func FxIntLengthStop(pTarget, effect, iReason, fTmp) public func FxFuseTimer(object target, effect, int timer)
{ {
for(var i = 0; i < GetLength(aWires); i++) CreateParticle("Fire", 0, 0, PV_Random(-10, 10), PV_Random(-20, 10), PV_Random(10, 40), Particles_Glimmer(), 6);
if(aWires[i]) aWires[i]->SetColorWarning(0); if (timer > 90)
DoExplode();
return FX_OK;
} }
public func IsTool() { return true; } public func IsTool() { return true; }
public func IsChemicalProduct() { return true; } public func IsChemicalProduct() { return true; }
/*-- Properties --*/
func Definition(def) { func Definition(def) {
SetProperty("PictureTransformation", Trans_Mul(Trans_Rotate(150, 1, 0, 0), Trans_Rotate(140, 0, 1, 0)), 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 Powder Keg
Author: Ringwaul
A barrel filled with black powder. A barrel filled with black powder.
--*/
@author Ringwaul
*/
#include Library_CarryHeavy #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() public func Damage()
@ -139,6 +139,9 @@ public func SaveScenarioObject(props)
func IsChemicalProduct() { return true; } func IsChemicalProduct() { return true; }
func AlchemyProcessTime() { return 100; } func AlchemyProcessTime() { return 100; }
/*-- Properties --*/
local Collectible = false; local Collectible = false;
local Touchable = 2; local Touchable = 2;
local Name = "$Name$"; local Name = "$Name$";