|
|
|
@ -1,50 +1,119 @@
|
|
|
|
|
/*--
|
|
|
|
|
/**
|
|
|
|
|
Airplane
|
|
|
|
|
Author: Ringwaul
|
|
|
|
|
|
|
|
|
|
Acrobatic air-vehicle. Capable of firing lead shot.
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
@author: Ringwaul, Clonkonaut
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
local throttle = 0;
|
|
|
|
|
local rdir = 0;
|
|
|
|
|
local thrust = 0;
|
|
|
|
|
local dir = 0;
|
|
|
|
|
|
|
|
|
|
local newrot;
|
|
|
|
|
|
|
|
|
|
local throttle;
|
|
|
|
|
local rdir;
|
|
|
|
|
local thrust;
|
|
|
|
|
local dir;
|
|
|
|
|
local propanim;
|
|
|
|
|
local prop_speed, prop_speed_target, prop_speed_timer; // current and target propeller speed [0, 100]
|
|
|
|
|
|
|
|
|
|
local pilot;
|
|
|
|
|
local clonkmesh;
|
|
|
|
|
|
|
|
|
|
public func IsVehicle() { return true; }
|
|
|
|
|
/*-- Engine Callbacks --*/
|
|
|
|
|
|
|
|
|
|
protected func Construction(object byobj)
|
|
|
|
|
func Construction()
|
|
|
|
|
{
|
|
|
|
|
SetR(-90);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected func Initialize()
|
|
|
|
|
func Initialize()
|
|
|
|
|
{
|
|
|
|
|
propanim = PlayAnimation("Propellor", 15, Anim_Const(0));
|
|
|
|
|
AddEffect("IntPlane",this,1,1,this);
|
|
|
|
|
propanim = PlayAnimation("Propellor", 15, Anim_Const(0));
|
|
|
|
|
AddEffect("IntPlane", this, 1, 1, this);
|
|
|
|
|
SetAction("Land");
|
|
|
|
|
throttle = 0;
|
|
|
|
|
thrust = 0;
|
|
|
|
|
rdir = 0;
|
|
|
|
|
dir = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected func RejectCollect(id def, object obj)
|
|
|
|
|
func RejectCollect(id def, object obj)
|
|
|
|
|
{
|
|
|
|
|
// Only accept munition and clonks.
|
|
|
|
|
if (def != LeadBullet && def != Boompack && !(obj->GetOCF() & OCF_CrewMember))
|
|
|
|
|
var contents_count = ObjectCount(Find_Container(this), Find_Not(Find_OCF(OCF_CrewMember)));
|
|
|
|
|
if (contents_count >= MaxContentsCount)
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Damage(int change, int cause, int by_player)
|
|
|
|
|
{
|
|
|
|
|
if (GetDamage() >= this.HitPoints)
|
|
|
|
|
{
|
|
|
|
|
if (pilot) PlaneDismount(pilot);
|
|
|
|
|
SetController(by_player);
|
|
|
|
|
PlaneDeath();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-- Control: Fire Bullets --*/
|
|
|
|
|
func ActivateEntrance(object clonk)
|
|
|
|
|
{
|
|
|
|
|
if (clonk->Contained() == this)
|
|
|
|
|
return clonk->Exit();
|
|
|
|
|
|
|
|
|
|
// Clonks cannot get into the plane if it is underwater
|
|
|
|
|
if(GBackLiquid()) return false;
|
|
|
|
|
|
|
|
|
|
var passengers = ObjectCount(Find_Container(this), Find_OCF(OCF_CrewMember));
|
|
|
|
|
if (passengers >= MaxPassengerCount) return false;
|
|
|
|
|
|
|
|
|
|
clonk->Enter(this);
|
|
|
|
|
clonk->SetAction("Walk");
|
|
|
|
|
clonk->PlayAnimation("Drive", CLONK_ANIM_SLOT_Movement, Anim_Const(10), Anim_Const(1000));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Ejection(object obj)
|
|
|
|
|
{
|
|
|
|
|
if (pilot && obj == pilot)
|
|
|
|
|
PlaneDismount(obj);
|
|
|
|
|
if(obj->Contained()) Exit();
|
|
|
|
|
obj->SetSpeed(this->GetXDir(), this->GetYDir());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Inflict damage when hitting something with the plane and already damaged.
|
|
|
|
|
func Hit(int xdir, int ydir)
|
|
|
|
|
{
|
|
|
|
|
var remaining_hp = this.HitPoints - GetDamage();
|
|
|
|
|
if (remaining_hp < 10)
|
|
|
|
|
{
|
|
|
|
|
var speed = Distance(0, 0, xdir, ydir) / 10;
|
|
|
|
|
if (speed > 4 * remaining_hp)
|
|
|
|
|
DoDamage(speed / 6, FX_Call_DmgScript, GetController());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-- Callbacks --*/
|
|
|
|
|
|
|
|
|
|
public func IsContainer() { return true; }
|
|
|
|
|
|
|
|
|
|
public func IsProjectileTarget(target, shooter) { return true; }
|
|
|
|
|
|
|
|
|
|
/*-- Interface --*/
|
|
|
|
|
|
|
|
|
|
//Quick command for scenario designers. The plane starts facing right instead of left.
|
|
|
|
|
public func FaceRight()
|
|
|
|
|
{
|
|
|
|
|
SetR(90);
|
|
|
|
|
RollPlane(1, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func FaceLeft()
|
|
|
|
|
{
|
|
|
|
|
SetR(-90);
|
|
|
|
|
RollPlane(0, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-- Usage --*/
|
|
|
|
|
|
|
|
|
|
// Bullet firing
|
|
|
|
|
public func ContainedUseStart(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
//return ContainedUseAltStart(clonk, x, y);
|
|
|
|
|
if (clonk != pilot) return false;
|
|
|
|
|
|
|
|
|
|
var ammo = FindObject(Find_Container(this), Find_Func("IsBullet"));
|
|
|
|
|
if (!ammo)
|
|
|
|
|
{
|
|
|
|
@ -55,7 +124,135 @@ public func ContainedUseStart(object clonk, int x, int y)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected func FxFireBulletsStart(object target, proplist effect, int temp)
|
|
|
|
|
public func ContainedUseStop(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
if (clonk != pilot) return false;
|
|
|
|
|
|
|
|
|
|
if (GetEffect("FireBullets", this))
|
|
|
|
|
RemoveEffect("FireBullets", this);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedUseCancel(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
if (clonk != pilot) return false;
|
|
|
|
|
|
|
|
|
|
if (GetEffect("FireBullets", this))
|
|
|
|
|
RemoveEffect("FireBullets", this);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Rocket firing
|
|
|
|
|
public func ContainedUseAltStart(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
if (clonk != pilot) return false;
|
|
|
|
|
|
|
|
|
|
var rocket = FindObject(Find_Container(this), Find_ID(Boompack));
|
|
|
|
|
if (!rocket)
|
|
|
|
|
{
|
|
|
|
|
CustomMessage("$NoRockets$", this, clonk->GetOwner());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedUseAltStop(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
if (clonk != pilot) return false;
|
|
|
|
|
|
|
|
|
|
var rocket = FindObject(Find_Container(this), Find_ID(Boompack));
|
|
|
|
|
if (!rocket)
|
|
|
|
|
{
|
|
|
|
|
CustomMessage("$NoRockets$", this, clonk->GetOwner());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
FireRocket(rocket, x, y);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedUseAltCancel(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
if (clonk != pilot) return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Starting the plane
|
|
|
|
|
public func ContainedUp(object clonk)
|
|
|
|
|
{
|
|
|
|
|
if (pilot)
|
|
|
|
|
{
|
|
|
|
|
// For safety, check if the pilot is dead (which is never particularly good)
|
|
|
|
|
// During flight, pilot's health is constantly checked by the flying effect
|
|
|
|
|
if (!pilot->GetAlive())
|
|
|
|
|
PlaneDismount(pilot);
|
|
|
|
|
else if (clonk != pilot)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
//engine start
|
|
|
|
|
if(clonk && GetAction() == "Land")
|
|
|
|
|
{
|
|
|
|
|
if (!pilot) PlaneMount(clonk);
|
|
|
|
|
StartFlight(15);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Stopping the plane
|
|
|
|
|
public func ContainedDown(object clonk)
|
|
|
|
|
{
|
|
|
|
|
//engine shutoff
|
|
|
|
|
if(GetAction() == "Fly" && clonk == pilot)
|
|
|
|
|
{
|
|
|
|
|
CancelFlight();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (pilot)
|
|
|
|
|
{
|
|
|
|
|
if (!pilot->GetAlive())
|
|
|
|
|
PlaneDismount(pilot);
|
|
|
|
|
else if (clonk != pilot)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
//allow reverse
|
|
|
|
|
if(clonk && GetAction() == "Land")
|
|
|
|
|
{
|
|
|
|
|
if (!pilot) PlaneMount(clonk);
|
|
|
|
|
StartFlight(-5);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Steering
|
|
|
|
|
public func ContainedLeft(object clonk)
|
|
|
|
|
{
|
|
|
|
|
if (clonk != pilot) return false;
|
|
|
|
|
|
|
|
|
|
rdir = -1;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedRight(object clonk)
|
|
|
|
|
{
|
|
|
|
|
if (clonk != pilot) return false;
|
|
|
|
|
|
|
|
|
|
rdir = 1;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedStop(object clonk)
|
|
|
|
|
{
|
|
|
|
|
if (clonk != pilot) return false;
|
|
|
|
|
|
|
|
|
|
rdir = 0;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-- Bullet firing --*/
|
|
|
|
|
|
|
|
|
|
func FxFireBulletsStart(object target, proplist effect, int temp)
|
|
|
|
|
{
|
|
|
|
|
if (temp)
|
|
|
|
|
return FX_OK;
|
|
|
|
@ -66,10 +263,10 @@ protected func FxFireBulletsStart(object target, proplist effect, int temp)
|
|
|
|
|
if (!ammo)
|
|
|
|
|
return FX_Execute_Kill;
|
|
|
|
|
FireBullet(ammo);
|
|
|
|
|
return FX_OK;
|
|
|
|
|
return FX_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected func FxFireBulletsTimer(object target, proplist effect, int time)
|
|
|
|
|
func FxFireBulletsTimer(object target, proplist effect, int time)
|
|
|
|
|
{
|
|
|
|
|
var ammo = FindObject(Find_Container(this), Find_Func("IsBullet"));
|
|
|
|
|
if (!ammo)
|
|
|
|
@ -78,7 +275,7 @@ protected func FxFireBulletsTimer(object target, proplist effect, int time)
|
|
|
|
|
return FX_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected func FxFireBulletsStop(object target, proplist effect, int reason, bool temp)
|
|
|
|
|
func FxFireBulletsStop(object target, proplist effect, int reason, bool temp)
|
|
|
|
|
{
|
|
|
|
|
if (temp)
|
|
|
|
|
return FX_OK;
|
|
|
|
@ -87,7 +284,7 @@ protected func FxFireBulletsStop(object target, proplist effect, int reason, boo
|
|
|
|
|
return FX_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func FireBullet(object ammo)
|
|
|
|
|
func FireBullet(object ammo)
|
|
|
|
|
{
|
|
|
|
|
var shot = ammo->TakeObject();
|
|
|
|
|
var angle = this->GetR();
|
|
|
|
@ -101,60 +298,14 @@ private func FireBullet(object ammo)
|
|
|
|
|
var x = Sin(angle, 20);
|
|
|
|
|
var y = -Cos(angle, 20);
|
|
|
|
|
CreateParticle("Smoke", IX, IY, PV_Random(x - 20, x + 20), PV_Random(y - 20, y + 20), PV_Random(40, 60), Particles_Smoke(), 20);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CreateMuzzleFlash(IX, IY, angle, 20);
|
|
|
|
|
CreateParticle("Flash", 0, 0, GetXDir(), GetYDir(), 8, Particles_Flash());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedUseStop(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
//return ContainedUseAltStop(clonk, x, y);
|
|
|
|
|
if (GetEffect("FireBullets", this))
|
|
|
|
|
RemoveEffect("FireBullets", this);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
/*-- Rocket firing --*/
|
|
|
|
|
|
|
|
|
|
public func ContainedUseCancel(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
//return ContainedUseAltCancel(clonk, x, y);
|
|
|
|
|
if (GetEffect("FireBullets", this))
|
|
|
|
|
RemoveEffect("FireBullets", this);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-- Control: Fire Rockets --*/
|
|
|
|
|
|
|
|
|
|
public func ContainedUseAltStart(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
var rocket = FindObject(Find_Container(this), Find_ID(Boompack));
|
|
|
|
|
if (!rocket)
|
|
|
|
|
{
|
|
|
|
|
CustomMessage("$NoRockets$", this, clonk->GetOwner());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedUseAltStop(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
var rocket = FindObject(Find_Container(this), Find_ID(Boompack));
|
|
|
|
|
if (!rocket)
|
|
|
|
|
{
|
|
|
|
|
CustomMessage("$NoRockets$", this, clonk->GetOwner());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
FireRocket(rocket, x, y);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedUseAltCancel(object clonk, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func FireRocket(object rocket, int x, int y)
|
|
|
|
|
func FireRocket(object rocket, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
var launch_x = Cos(GetR() - 180 * (1 - dir), 10);
|
|
|
|
|
var launch_y = Sin(GetR() - 180 * (1 - dir), 10);
|
|
|
|
@ -164,10 +315,9 @@ private func FireRocket(object rocket, int x, int y)
|
|
|
|
|
effect.x = GetX() + x;
|
|
|
|
|
effect.y = GetY() + y;
|
|
|
|
|
rocket->SetDirectionDeviation(0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected func FxIntControlRocketTimer(object target, proplist effect, int time)
|
|
|
|
|
func FxIntControlRocketTimer(object target, proplist effect, int time)
|
|
|
|
|
{
|
|
|
|
|
// Remove gravity on rocket.
|
|
|
|
|
target->SetYDir(target->GetYDir(100) - GetGravity(), 100);
|
|
|
|
@ -186,49 +336,7 @@ protected func FxIntControlRocketTimer(object target, proplist effect, int time)
|
|
|
|
|
return FX_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-- Control: Movement --*/
|
|
|
|
|
|
|
|
|
|
public func ContainedUp(object clonk)
|
|
|
|
|
{
|
|
|
|
|
//engine start
|
|
|
|
|
if(GetAction() == "Land")
|
|
|
|
|
{
|
|
|
|
|
StartFlight(15);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedDown(object clonk)
|
|
|
|
|
{
|
|
|
|
|
//engine shutoff
|
|
|
|
|
if(GetAction() == "Fly")
|
|
|
|
|
{
|
|
|
|
|
CancelFlight();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
//allow reverse
|
|
|
|
|
if(GetAction() == "Land")
|
|
|
|
|
{
|
|
|
|
|
StartFlight(-5);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedLeft(object clonk)
|
|
|
|
|
{
|
|
|
|
|
rdir = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedRight(object clonk)
|
|
|
|
|
{
|
|
|
|
|
rdir = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ContainedStop(object clonk)
|
|
|
|
|
{
|
|
|
|
|
rdir = 0;
|
|
|
|
|
}
|
|
|
|
|
/*-- Movement --*/
|
|
|
|
|
|
|
|
|
|
public func StartFlight(int new_throttle)
|
|
|
|
|
{
|
|
|
|
@ -248,7 +356,6 @@ public func StartInstantFlight(int angle, int new_throttle)
|
|
|
|
|
SetR(angle);
|
|
|
|
|
SetXDir(Sin(angle, thrust));
|
|
|
|
|
SetYDir(-Cos(angle, thrust));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func CancelFlight()
|
|
|
|
@ -259,10 +366,10 @@ public func CancelFlight()
|
|
|
|
|
throttle = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func FxIntPlaneTimer(object target, effect, int timer)
|
|
|
|
|
func FxIntPlaneTimer(object target, effect, int timer)
|
|
|
|
|
{
|
|
|
|
|
//Lift
|
|
|
|
|
var lift = Distance(0,0,GetXDir(),GetYDir()) / 2;
|
|
|
|
|
var lift = Distance(0, 0, GetXDir(), GetYDir()) / 2;
|
|
|
|
|
if(lift > 20) lift = 20;
|
|
|
|
|
if(throttle < 1) lift = 0;
|
|
|
|
|
|
|
|
|
@ -301,7 +408,7 @@ private func FxIntPlaneTimer(object target, effect, int timer)
|
|
|
|
|
if(throttle > thrust) ++thrust;
|
|
|
|
|
if(throttle < thrust) --thrust;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//propellor
|
|
|
|
|
var change = GetAnimationPosition(propanim) + thrust * 3;
|
|
|
|
|
if(change > GetAnimationLength("Propellor"))
|
|
|
|
@ -312,21 +419,24 @@ private func FxIntPlaneTimer(object target, effect, int timer)
|
|
|
|
|
SetAnimationPosition(propanim, Anim_Const(change));
|
|
|
|
|
|
|
|
|
|
//Thrust
|
|
|
|
|
SetXDir(Sin(GetR(),thrust) + GetXDir(100), 100);
|
|
|
|
|
SetYDir(-Cos(GetR(),thrust) + GetYDir(100) - lift, 100);
|
|
|
|
|
SetXDir(Sin(GetR(), thrust) + GetXDir(100), 100);
|
|
|
|
|
SetYDir(-Cos(GetR(), thrust) + GetYDir(100) - lift, 100);
|
|
|
|
|
|
|
|
|
|
//Drag
|
|
|
|
|
var maxspeed = 40;
|
|
|
|
|
var speed = Distance(0,0,GetXDir(),GetYDir());
|
|
|
|
|
if(speed > 40)
|
|
|
|
|
var speed = Distance(0, 0, GetXDir(), GetYDir());
|
|
|
|
|
if(speed > maxspeed)
|
|
|
|
|
{
|
|
|
|
|
SetXDir(GetXDir(100)*maxspeed/speed,100);
|
|
|
|
|
SetYDir(GetYDir(100)*maxspeed/speed,100);
|
|
|
|
|
SetXDir(GetXDir(100)*maxspeed/speed, 100);
|
|
|
|
|
SetYDir(GetYDir(100)*maxspeed/speed, 100);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No pilot? Look for all layers, since an NPC might be in a different layer.
|
|
|
|
|
var pilot = FindObject(Find_OCF(OCF_CrewMember), Find_Container(this), Find_AnyLayer());
|
|
|
|
|
// var pilot = FindObject(Find_OCF(OCF_CrewMember), Find_Container(this), Find_AnyLayer());
|
|
|
|
|
|
|
|
|
|
if(!pilot && throttle != 0) CancelFlight();
|
|
|
|
|
if (pilot && !pilot->GetAlive())
|
|
|
|
|
PlaneDismount(pilot);
|
|
|
|
|
|
|
|
|
|
//Planes cannot fly underwater!
|
|
|
|
|
if(GBackLiquid())
|
|
|
|
@ -336,100 +446,26 @@ private func FxIntPlaneTimer(object target, effect, int timer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Pilot, but no mesh? In case they are scripted into the plane.
|
|
|
|
|
if(FindContents(Clonk) && !clonkmesh)
|
|
|
|
|
PlaneMount(FindContents(Clonk));
|
|
|
|
|
// if(FindContents(Clonk) && !clonkmesh)
|
|
|
|
|
// PlaneMount(FindContents(Clonk));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local newrot;
|
|
|
|
|
|
|
|
|
|
public func RollPlane(int rolldir, bool instant)
|
|
|
|
|
{
|
|
|
|
|
if(dir != rolldir)
|
|
|
|
|
{
|
|
|
|
|
var i = 36;
|
|
|
|
|
if(instant) i = 1;
|
|
|
|
|
newrot = PlayAnimation(Format("Roll%d",rolldir), 10, Anim_Linear(0, 0, GetAnimationLength(Format("Roll%d",rolldir)), i, ANIM_Hold));
|
|
|
|
|
newrot = PlayAnimation(Format("Roll%d",rolldir), 10, Anim_Linear(0, 0, GetAnimationLength(Format("Roll%d", rolldir)), i, ANIM_Hold));
|
|
|
|
|
dir = rolldir;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Quick command for scenario designers. The plane starts facing right instead of left.
|
|
|
|
|
public func FaceRight()
|
|
|
|
|
{
|
|
|
|
|
SetR(90);
|
|
|
|
|
RollPlane(1,true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func FaceLeft()
|
|
|
|
|
{
|
|
|
|
|
SetR(-90);
|
|
|
|
|
RollPlane(0,true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func IsProjectileTarget(target,shooter) { return true; }
|
|
|
|
|
|
|
|
|
|
public func Damage(int change, int cause, int by_player)
|
|
|
|
|
{
|
|
|
|
|
if (GetDamage() >= this.HitPoints)
|
|
|
|
|
{
|
|
|
|
|
SetController(by_player);
|
|
|
|
|
this->~PlaneDeath();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Inflict damage when hitting something with the plane and already damaged.
|
|
|
|
|
public func Hit(int xdir, int ydir)
|
|
|
|
|
{
|
|
|
|
|
var remaining_hp = this.HitPoints - GetDamage();
|
|
|
|
|
if (remaining_hp < 10)
|
|
|
|
|
{
|
|
|
|
|
var speed = Distance(0, 0, xdir, ydir) / 10;
|
|
|
|
|
if (speed > 4 * remaining_hp)
|
|
|
|
|
DoDamage(speed / 6, FX_Call_DmgScript, GetController());
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func PlaneDeath()
|
|
|
|
|
{
|
|
|
|
|
while(Contents(0))
|
|
|
|
|
Contents(0)->Exit();
|
|
|
|
|
Explode(36);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func ActivateEntrance(object clonk)
|
|
|
|
|
{
|
|
|
|
|
var cnt = ObjectCount(Find_Container(this), Find_OCF(OCF_CrewMember));
|
|
|
|
|
if(cnt > 0)
|
|
|
|
|
if(clonk->Contained() == this)
|
|
|
|
|
{
|
|
|
|
|
clonk->Exit();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//Clonk cannot get into the plane if it is underwater
|
|
|
|
|
if(GBackLiquid()) return;
|
|
|
|
|
|
|
|
|
|
if(cnt == 0)
|
|
|
|
|
{
|
|
|
|
|
clonk->Enter(this);
|
|
|
|
|
clonk->SetAction("Walk");
|
|
|
|
|
PlaneMount(clonk);
|
|
|
|
|
clonk->PlayAnimation("Drive", CLONK_ANIM_SLOT_Movement, Anim_Const(10), Anim_Const(1000));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func Ejection(object obj)
|
|
|
|
|
{
|
|
|
|
|
PlaneDismount(obj);
|
|
|
|
|
if(obj->Contained()) Exit();
|
|
|
|
|
obj->SetSpeed(this->GetXDir(),this->GetYDir());
|
|
|
|
|
}
|
|
|
|
|
/*-- Piloting --*/
|
|
|
|
|
|
|
|
|
|
public func PlaneMount(object clonk)
|
|
|
|
|
{
|
|
|
|
|
pilot = clonk;
|
|
|
|
|
SetOwner(clonk->GetController());
|
|
|
|
|
clonk->PlayAnimation("Stand", 15, nil, Anim_Const(1000));
|
|
|
|
|
clonkmesh = AttachMesh(clonk,"pilot","skeleton_body",Trans_Mul(Trans_Rotate(180, 1, 0, 0), Trans_Translate(-3000, 1000, 0)),AM_DrawBefore);
|
|
|
|
@ -441,16 +477,22 @@ public func PlaneDismount(object clonk)
|
|
|
|
|
clonk->StopAnimation(clonk->GetRootAnimation(15));
|
|
|
|
|
DetachMesh(clonkmesh);
|
|
|
|
|
clonkmesh = nil;
|
|
|
|
|
pilot = nil;
|
|
|
|
|
CancelFlight();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-- Effects --*/
|
|
|
|
|
|
|
|
|
|
/* Propeller sound */
|
|
|
|
|
|
|
|
|
|
local prop_speed, prop_speed_target, prop_speed_timer; // current and target propeller speed [0, 100]
|
|
|
|
|
func PlaneDeath()
|
|
|
|
|
{
|
|
|
|
|
while(Contents(0))
|
|
|
|
|
Contents(0)->Exit();
|
|
|
|
|
Explode(36);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Instantly set new propeller speed
|
|
|
|
|
private func SetPropellerSpeed(int new_speed)
|
|
|
|
|
public func SetPropellerSpeed(int new_speed)
|
|
|
|
|
{
|
|
|
|
|
if (prop_speed_timer)
|
|
|
|
|
{
|
|
|
|
@ -461,7 +503,7 @@ private func SetPropellerSpeed(int new_speed)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Schedule fading to new propeller speed
|
|
|
|
|
private func SetPropellerSpeedTarget(int new_speed_target)
|
|
|
|
|
public func SetPropellerSpeedTarget(int new_speed_target)
|
|
|
|
|
{
|
|
|
|
|
prop_speed_target = new_speed_target;
|
|
|
|
|
if (!prop_speed_timer) prop_speed_timer = AddTimer(this.PropellerSpeedTimer, 10);
|
|
|
|
@ -469,7 +511,7 @@ private func SetPropellerSpeedTarget(int new_speed_target)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Execute fading to new propeller speed
|
|
|
|
|
private func PropellerSpeedTimer()
|
|
|
|
|
func PropellerSpeedTimer()
|
|
|
|
|
{
|
|
|
|
|
prop_speed = BoundBy(prop_speed_target, prop_speed - 10, prop_speed + 4);
|
|
|
|
|
if (prop_speed == prop_speed_target)
|
|
|
|
@ -481,7 +523,7 @@ private func PropellerSpeedTimer()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set propeller speed sound. 0 = off, 100 = max speed.
|
|
|
|
|
private func SetPropellerSound(int speed)
|
|
|
|
|
func SetPropellerSound(int speed)
|
|
|
|
|
{
|
|
|
|
|
if (speed <= 0)
|
|
|
|
|
return Sound("Objects::Plane::PropellerLoop",0,100,nil,-1);
|
|
|
|
@ -489,11 +531,20 @@ private func SetPropellerSound(int speed)
|
|
|
|
|
return Sound("Objects::Plane::PropellerLoop",0,100,nil,1,0,(speed-100)*2/3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Properties */
|
|
|
|
|
/*-- Production --*/
|
|
|
|
|
|
|
|
|
|
public func IsContainer() { return true; }
|
|
|
|
|
public func IsVehicle() { return true; }
|
|
|
|
|
public func IsShipyardProduct() { return true; }
|
|
|
|
|
|
|
|
|
|
func IsShipyardProduct() { return true; }
|
|
|
|
|
/*-- Display --*/
|
|
|
|
|
|
|
|
|
|
func Definition(def)
|
|
|
|
|
{
|
|
|
|
|
SetProperty("MeshTransformation", Trans_Mul(Trans_Rotate(90,0,0,1), Trans_Translate(-10000,-3375,0), Trans_Rotate(25,0,1,0)));
|
|
|
|
|
SetProperty("PictureTransformation",Trans_Mul(Trans_Rotate(-5,1,0,0),Trans_Rotate(40,0,1,0),Trans_Translate(-20000,-4000,20000)),def);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-- Properties --*/
|
|
|
|
|
|
|
|
|
|
local ActMap = {
|
|
|
|
|
Fly = {
|
|
|
|
@ -526,14 +577,10 @@ local ActMap = {
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
func Definition(def)
|
|
|
|
|
{
|
|
|
|
|
SetProperty("MeshTransformation", Trans_Mul(Trans_Rotate(90,0,0,1), Trans_Translate(-10000,-3375,0), Trans_Rotate(25,0,1,0)));
|
|
|
|
|
SetProperty("PictureTransformation",Trans_Mul(Trans_Rotate(-5,1,0,0),Trans_Rotate(40,0,1,0),Trans_Translate(-20000,-4000,20000)),def);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local Name="$Name$";
|
|
|
|
|
local Description="$Description$";
|
|
|
|
|
local BorderBound = C4D_Border_Sides | C4D_Border_Top | C4D_Border_Bottom;
|
|
|
|
|
local HitPoints = 50;
|
|
|
|
|
local MaxContentsCount = 20;
|
|
|
|
|
local MaxPassengerCount = 3;
|
|
|
|
|
local Components = {Metal = 6, Wood = 4};
|
|
|
|
|