forked from Mirrors/openclonk
make windbag burst more gradual and slightly depend on mass (#1297)
parent
e2a42de2f2
commit
7ff5478142
|
@ -1,172 +1,223 @@
|
|||
/*--
|
||||
Windbag (aka Jar of Winds)
|
||||
Author: MimmoO
|
||||
/**
|
||||
Windbag
|
||||
Automatically collects air when it is full which can be released into a blast.
|
||||
|
||||
Collect air until you're full, then release it with a blast.
|
||||
--*/
|
||||
@author MimmoO, Maikel
|
||||
*/
|
||||
|
||||
local Amount;
|
||||
local MaxCap;
|
||||
local sound;
|
||||
local fill_amount;
|
||||
|
||||
func Hit()
|
||||
{
|
||||
Sound("GeneralHit?");
|
||||
}
|
||||
|
||||
public func GetCarryMode(clonk) { return CARRY_Musket; }
|
||||
public func GetCarryTransform()
|
||||
{
|
||||
return Trans_Mul(Trans_Rotate(220,0,0,1),Trans_Rotate(-30,1,0,0),Trans_Rotate(26,0,1,0));
|
||||
}
|
||||
public func GetCarryPhase() { return 600; }
|
||||
|
||||
public func FxJarReloadTimer(object target, effect, int time)
|
||||
{
|
||||
target->Load();
|
||||
}
|
||||
|
||||
public func DoFullLoad()
|
||||
{
|
||||
Amount = MaxCap;
|
||||
return;
|
||||
}
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
MaxCap = 60; //Changes duration and power
|
||||
SetR(-45);
|
||||
AddEffect("JarReload",this,100,2,this);
|
||||
sound=false;
|
||||
AddEffect("IntReload", this, 100, 1, this);
|
||||
return;
|
||||
}
|
||||
|
||||
protected func ControlUse(object pClonk, iX, iY)
|
||||
protected func Hit()
|
||||
{
|
||||
if (pClonk->GetProcedure() == "ATTACH")
|
||||
return true;
|
||||
if(!GetEffect("JarReload",this))
|
||||
{
|
||||
if(!GBackLiquid())
|
||||
{
|
||||
FireWeapon(pClonk, iX, iY);
|
||||
Amount=0;
|
||||
AddEffect("JarReload",this,100,1,this);
|
||||
Sound("WindCharge",false,nil,nil,1);
|
||||
sound=true;
|
||||
}
|
||||
Sound("GeneralHit?");
|
||||
return;
|
||||
}
|
||||
|
||||
public func GetCarryMode(clonk) { return CARRY_Musket; }
|
||||
|
||||
public func GetCarryTransform()
|
||||
{
|
||||
return Trans_Mul(Trans_Rotate(220, 0, 0, 1), Trans_Rotate(-30, 1, 0, 0), Trans_Rotate(26, 0, 1, 0));
|
||||
}
|
||||
|
||||
public func GetCarryPhase() { return 600; }
|
||||
|
||||
public func IsInventorProduct() { return true; }
|
||||
|
||||
|
||||
/*-- Usage --*/
|
||||
|
||||
protected func ControlUse(object clonk, x, y)
|
||||
{
|
||||
if (clonk->GetProcedure() == "ATTACH")
|
||||
return true;
|
||||
if (!GetEffect("IntReload", this) && !GetEffect("IntBurstWind", this))
|
||||
{
|
||||
if (!GBackLiquid())
|
||||
BlastWind(clonk, x, y);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pClonk->Message("Reloading!");
|
||||
return true;
|
||||
}
|
||||
// ChargeSoundStop();
|
||||
clonk->Message("$MsgReloading$");
|
||||
return true;
|
||||
}
|
||||
|
||||
protected func Load()
|
||||
|
||||
/*-- Loading --*/
|
||||
|
||||
public func DoFullLoad()
|
||||
{
|
||||
fill_amount = MaxIntake;
|
||||
return;
|
||||
}
|
||||
|
||||
if(Amount <= MaxCap)
|
||||
public func FxIntReloadStart(object target, proplist effect, int temp)
|
||||
{
|
||||
if (temp)
|
||||
return FX_OK;
|
||||
effect.Interval = 1;
|
||||
effect.sound = false;
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
public func FxIntReloadTimer(object target, proplist effect, int time)
|
||||
{
|
||||
if (fill_amount > MaxIntake)
|
||||
return FX_Execute_Kill;
|
||||
|
||||
if (GBackSolid(0,0) || GBackLiquid(0,0))
|
||||
{
|
||||
var R=RandomX(-25,25);
|
||||
var D=RandomX(19,50);
|
||||
var A=Random(360);
|
||||
var SX=Sin(A + R,D);
|
||||
var SY=Cos(A + R,D);
|
||||
|
||||
if(!GBackSolid(SX,SY) && !GBackLiquid(SX,SY) && !GBackSolid(0,0) && !GBackLiquid(0,0)) //when on a random spot in front is air...
|
||||
if (effect.sound)
|
||||
{
|
||||
if(!sound)
|
||||
{
|
||||
Sound("WindCharge",false,nil,nil,1);
|
||||
sound=true;
|
||||
}
|
||||
Amount += 2; //Air is sucked in.
|
||||
CreateParticle("Air", SX, SY, Sin(A + R,-D / 2), Cos(A + R,-D / 2), 18, {Prototype = Particles_Air(), Size = PV_KeyFrames(0, 0, 0, 250, 3, 1000, 0)});
|
||||
Sound("WindCharge", false, nil, nil, -1);
|
||||
Sound("WindChargeStop");
|
||||
effect.sound = false;
|
||||
}
|
||||
else if(GBackSolid(0,0) || GBackLiquid(0,0))
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
var radius = RandomX(12, 24);
|
||||
var angle = Random(360);
|
||||
var angle_var = RandomX(-25, 25);
|
||||
var x = Sin(angle + angle_var, radius);
|
||||
var y = Cos(angle + angle_var, radius);
|
||||
// Check for a spot of air from which to take the air in.
|
||||
if (!GBackSolid(x, y) && !GBackLiquid(x, y) && !GBackSolid(0, 0) && !GBackLiquid(0, 0))
|
||||
{
|
||||
if (!effect.sound)
|
||||
{
|
||||
if(sound)
|
||||
ChargeSoundStop();
|
||||
Sound("WindCharge", false, nil, nil, 1);
|
||||
effect.sound = true;
|
||||
}
|
||||
|
||||
// Particles from the point where the air is sucked in.
|
||||
var air = {
|
||||
Prototype = Particles_Air(),
|
||||
Size = PV_KeyFrames(0, 0, 0, 250, 3, 1000, 0)
|
||||
};
|
||||
CreateParticle("Air", x, y, -x / 2, -y / 2, 18, air);
|
||||
|
||||
// Increase the fill amount proportional to the number of frames.
|
||||
fill_amount += effect.Interval;
|
||||
}
|
||||
else
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
public func FxIntReloadStop(object target, proplist effect, int reason, bool temp)
|
||||
{
|
||||
if (temp)
|
||||
return FX_OK;
|
||||
if (effect.sound)
|
||||
{
|
||||
RemoveEffect("JarReload",this);
|
||||
ChargeSoundStop();
|
||||
|
||||
Sound("WindCharge", false, nil, nil, -1);
|
||||
Sound("WindChargeStop");
|
||||
}
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
protected func ChargeSoundStop()
|
||||
|
||||
/*-- Blasting --*/
|
||||
|
||||
private func BlastWind(object clonk, int x, int y)
|
||||
{
|
||||
Sound("WindCharge",false,nil,nil,-1);
|
||||
Sound("WindChargeStop");
|
||||
sound=false;
|
||||
if (fill_amount <= 0)
|
||||
{
|
||||
fill_amount = 0;
|
||||
AddEffect("IntReload", this, 100, 1, this);
|
||||
return;
|
||||
}
|
||||
// The blast is handled by an effect.
|
||||
AddEffect("IntBurstWind", this, 100, 1, this, nil, clonk, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
private func FireWeapon(object pClonk,iX,iY)
|
||||
public func FxIntBurstWindStart(object target, proplist effect, int temp, object clonk, int x, int y)
|
||||
{
|
||||
var iAngle=Angle(0,0,iX,iY);
|
||||
|
||||
ChargeSoundStop();
|
||||
if (temp)
|
||||
return FX_OK;
|
||||
effect.Interval = 1;
|
||||
effect.clonk = clonk;
|
||||
effect.x = clonk->GetX();
|
||||
effect.y = clonk->GetY();
|
||||
effect.angle = Angle(0, 0, x, y);
|
||||
// Sound effect.
|
||||
Sound("WindGust");
|
||||
|
||||
//Find Victims to push
|
||||
for(var i=10; i<32; i++)
|
||||
// Particle effect.
|
||||
for (var dr = 12; dr < 32; dr++)
|
||||
{
|
||||
var R = RandomX(-20,20);
|
||||
var SX = Sin(180 - iAngle + R,i);
|
||||
var SY = Cos(180 - iAngle + R,i);
|
||||
|
||||
if(!GBackSolid(SX,SY))
|
||||
{
|
||||
CreateParticle("Air", SX, SY, Sin(180 - iAngle + (R),(Amount / 2) + 25), Cos(180 - iAngle + (R),(Amount / 2) + 25), 36, Particles_Air());
|
||||
}
|
||||
}
|
||||
|
||||
var sinspeed = Sin(180 - iAngle + (R / 2),(Amount) + 15);
|
||||
var cosspeed = Cos(180 - iAngle + (R / 2),(Amount) + 15);
|
||||
|
||||
if(pClonk->GetAction() != "Walk")
|
||||
{ //Makes the clonk firing it be pushed backwards a bit
|
||||
var x = pClonk->GetXDir();
|
||||
var y = pClonk->GetYDir();
|
||||
pClonk->SetXDir((x) - (sinspeed / 3));
|
||||
pClonk->SetYDir((y) - (cosspeed / 3));
|
||||
}
|
||||
|
||||
for( var obj in FindObjects(
|
||||
Find_Or(
|
||||
Find_Distance(10,Sin(180 - iAngle,20),Cos(180 - iAngle,20)),
|
||||
Find_Distance(18,Sin(180 - iAngle,40),Cos(180 - iAngle,40)),
|
||||
Find_Distance(25,Sin(180 - iAngle,70),Cos(180 - iAngle,70))
|
||||
),
|
||||
Find_Not(Find_Category(C4D_Structure)),
|
||||
Find_Not(Find_Func("IsEnvironment")),
|
||||
Find_Not(Find_Func("NoWindbagForce")),
|
||||
Find_Layer(GetObjectLayer()), Find_NoContainer()
|
||||
)
|
||||
)
|
||||
{
|
||||
if(obj != pClonk && PathFree(pClonk->GetX(),pClonk->GetY(),obj->GetX(),obj->GetY()))
|
||||
{
|
||||
//enemys are pushed back
|
||||
var x = obj->GetXDir();
|
||||
var y = obj->GetYDir();
|
||||
obj->SetXDir((x) + sinspeed);
|
||||
obj->SetYDir((y) + cosspeed);
|
||||
}
|
||||
var r = RandomX(-20, 20);
|
||||
var sx = Sin(effect.angle + r, dr / 2);
|
||||
var sy = -Cos(effect.angle + r, dr / 2);
|
||||
var vx = Sin(effect.angle + r, 2 * fill_amount / 3 + 12);
|
||||
var vy = -Cos(effect.angle + r, 2 * fill_amount / 3 + 12);
|
||||
if (!GBackSolid(sx, sy))
|
||||
CreateParticle("Air", sx, sy, vx, vy, 36, Particles_Air());
|
||||
}
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
func IsInventorProduct() { return true; }
|
||||
public func FxIntBurstWindTimer(object target, proplist effect, int time)
|
||||
{
|
||||
if (time > 12)
|
||||
return FX_Execute_Kill;
|
||||
|
||||
func Definition(def) {
|
||||
SetProperty("PictureTransformation",Trans_Mul(Trans_Scale(1500),Trans_Rotate(150,0,0,1),Trans_Rotate(-170,1,0,0),Trans_Rotate(10,0,1,0)),def);
|
||||
// Determine blast strength.
|
||||
var vx = Sin(effect.angle, 20 * fill_amount + 150);
|
||||
var vy = -Cos(effect.angle, 20 * fill_amount + 150);
|
||||
|
||||
// Change the velocity of the shooter.
|
||||
if (effect.clonk && effect.clonk->GetAction() != "Walk")
|
||||
{
|
||||
var cx = effect.clonk->GetXDir(100);
|
||||
var cy = effect.clonk->GetYDir(100);
|
||||
effect.clonk->SetXDir(cx - vx / (8 * time), 100);
|
||||
effect.clonk->SetYDir(cy - vy / (8 * time), 100);
|
||||
}
|
||||
|
||||
// Move other objects in a cone around the burst direction.
|
||||
var criteria = Find_And(Find_Not(Find_Category(C4D_Structure)), Find_Not(Find_Func("IsEnvironment")), Find_Not(Find_Func("NoWindbagForce")),
|
||||
Find_Layer(GetObjectLayer()), Find_NoContainer(), Find_Exclude(effect.clonk), Find_PathFree(effect.clonk));
|
||||
var dist = 14 + 5 * time / 2;
|
||||
var rad = 8 + 5 * time / 3;
|
||||
var cone_x = Sin(effect.angle, dist);
|
||||
var cone_y = -Cos(effect.angle, dist);
|
||||
var vx_cone = vx / (2 * time);
|
||||
var vy_cone = vy / (2 * time);
|
||||
for (var obj in FindObjects(Find_Distance(rad, cone_x + AbsX(effect.x), cone_y + AbsY(effect.y)), criteria))
|
||||
{
|
||||
var ox = obj->GetXDir(100);
|
||||
var oy = obj->GetYDir(100);
|
||||
var vx_cone_reduced = vx_cone / 2 + vx_cone / (2 * Max(1, obj->GetMass() / 4));
|
||||
var vy_cone_reduced = vy_cone / 2 + vy_cone / (2 * Max(1, obj->GetMass() / 4));
|
||||
obj->SetXDir(ox + vx_cone_reduced, 100);
|
||||
obj->SetYDir(oy + vy_cone_reduced, 100);
|
||||
}
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
public func FxIntBurstWindStop(object target, proplist effect, int reason, bool temp)
|
||||
{
|
||||
if (temp)
|
||||
return FX_OK;
|
||||
// Reset the fill amount and start reloading.
|
||||
fill_amount = 0;
|
||||
AddEffect("IntReload", target, 100, 1, target);
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
|
||||
/*-- Properties --*/
|
||||
|
||||
protected func Definition(def)
|
||||
{
|
||||
SetProperty("PictureTransformation", Trans_Mul(Trans_Scale(1500), Trans_Rotate(150, 0, 0, 1), Trans_Rotate(-170, 1, 0, 0), Trans_Rotate(10, 0, 1, 0)), def);
|
||||
}
|
||||
|
||||
local Name = "$Name$";
|
||||
|
@ -174,3 +225,4 @@ local Description = "$Description$";
|
|||
local UsageHelp = "$UsageHelp$";
|
||||
local Collectible = 1;
|
||||
local Rebuy = true;
|
||||
local MaxIntake = 30;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
Name=Windbeutel
|
||||
Description=Enthält komprimierten Wind der in einem Stoß entfesselt werden kann.
|
||||
UsageHelp=Ziele und drücke [Benutzen], um einen Windstoß in diese Richtung zu entfesseln.
|
||||
Description=Enthält komprimierten Wind der in einem Stoß entfesselt werden kann.
|
||||
UsageHelp=Ziele und drücke [Benutzen], um einen Windstoß in diese Richtung zu entfesseln.
|
||||
|
||||
MsgReloading=Lädt nach!
|
|
@ -1,3 +1,5 @@
|
|||
Name=Wind bag
|
||||
Description=Contains compressed wind that can be released in one gust.
|
||||
UsageHelp=Aim and press [Use] to release a gust of wind in the direction specified.
|
||||
|
||||
MsgReloading=Reloading!
|
Loading…
Reference in New Issue