openclonk/planet/Objects.ocd/Vehicles.ocd/Locomotive.ocd/Script.c

256 lines
4.9 KiB
C

/**
Locomotive
Transportation device for long distances and heavy cargo.
@author Pyrit
*/
#include Library_ElevatorControl
#include Library_LiquidContainer
#include Library_PipeControl
local move_dir;
local fuel_amount;
local drive_anim;
local rot_wheels;
protected func Initialize()
{
move_dir = 0;
fuel_amount = 0;
rot_wheels = 0;
AddTimer("Move", 1);
SetAction("Drive");
// Entrance is always open.
SetEntrance(true);
// Start driving animation.
drive_anim = PlayAnimation("Main TrainAction", 1, Anim_Const(0));
return;
}
public func OnContentMenuOpened()
{
//return Sound("Locomotive::Chuff");
}
public func OnContentMenuClosed()
{
//return Sound("Locomotive::Chuff");
}
public func Collection2(object obj)
{
if (obj->GetOCF() & OCF_CrewMember)
{
obj->SetAction("Walk");
obj->PlayAnimation("Drive", CLONK_ANIM_SLOT_Movement, Anim_Const(10), Anim_Const(1000));
}
return;
}
public func Ejection(object obj)
{
if (obj->GetOCF() & OCF_CrewMember)
{
}
return;
}
/*-- Liquid Control --*/
public func IsLiquidContainerForMaterial(string liquid)
{
return WildcardMatch("Water", liquid);
}
public func GetLiquidContainerMaxFillLevel(liquid_name)
{
return this.LiquidCapacity;
}
// The locomotive may only have a drain pipe.
public func QueryConnectPipe(object pipe, bool do_msg)
{
if (pipe->IsDrainPipe() && GetDrainPipe())
{
if (do_msg)
pipe->Report("$MsgHasDrainPipe$");
return true;
}
if (pipe->IsSourcePipe() || pipe->IsAirPipe())
{
if (do_msg)
pipe->Report("$MsgPipeProhibited$");
return true;
}
return false;
}
// Set to source or drain pipe.
public func OnPipeConnect(object pipe, string specific_pipe_state)
{
if (specific_pipe_state == PIPE_STATE_Drain)
{
SetDrainPipe(pipe);
pipe->SetDrainPipe();
}
else
{
if (!GetDrainPipe())
OnPipeConnect(pipe, PIPE_STATE_Drain);
}
pipe->Report("$MsgConnectedPipe$");
}
/*-- Movement --*/
public func Move()
{
UpdateFuel();
var water_amount = GetLiquidAmount(Water);
if (move_dir == 0)
return;
if (fuel_amount <= 0 && water_amount <= 0)
return Message("$MsgNoCoalAndWater$");
if (water_amount <= 0)
return Message("$MsgNoWater$");
if (fuel_amount <= 0)
return Message("$MsgNoCoal$");
if (Stuck())
return Message("$MsgStuck$");
fuel_amount--;
RemoveLiquid(Water, 1);
if (move_dir == -1)
SetDir(DIR_Left);
if (move_dir == 1)
SetDir(DIR_Right);
SetXDir(15 * move_dir);
DoExhaust();
TurnWheels();
return;
}
private func DoExhaust()
{
//Sound("Locomotive::Chuff");
Smoke(11 * (2 * GetDir() - 1), -18, 6);
var spark = {
Size = PV_Linear(1, 0),
ForceY = RandomX(-50, -60),
ForceX = PV_Random(-1, 1, 10),
DampingY = PV_Linear(600, 0),
Stretch = PV_Speed(1000, 500),
Rotation = PV_Direction(),
CollisionVertex = 500,
OnCollision = PC_Stop(),
R = 255,
G = PV_Linear(128, 32),
B = PV_Random(0, 128, 2),
Alpha = PV_Random(255, 0, 3),
BlitMode = GFX_BLIT_Additive,
};
CreateParticle("Magic", 12 * (2 * GetDir() - 1), -18, PV_Random(-3, 3), PV_Random(-3, -4), 36, spark, 1);
return;
}
private func TurnWheels()
{
var anim_pos = GetAnimationPosition(drive_anim);
anim_pos += Abs(GetXDir()) * 8;
while (anim_pos < 0)
anim_pos += 2000;
while (anim_pos > 2000)
anim_pos -= 2000;
SetAnimationPosition(drive_anim, Anim_Const(anim_pos));
return;
}
private func UpdateFuel()
{
if (fuel_amount > 0)
return;
var fuel = FindObject(Find_Or(Find_ID(Wood), Find_ID(Coal)), Find_Container(this));
if (fuel)
{
fuel_amount += fuel->GetFuelAmount();
fuel->RemoveObject();
}
return;
}
public func ContainedDown(object clonk)
{
move_dir = 0;
}
public func ContainedLeft(object clonk)
{
move_dir = -1;
}
public func ContainedRight(object clonk)
{
move_dir = 1;
}
public func ContainedStop(object clonk)
{
move_dir = 0;
}
public func Hit2()
{
Sound("Hits::Materials::Metal::DullMetalHit?");
}
public func IsVehicle() { return true; }
public func IsContainer() { return true; }
/*-- Contents --*/
protected func RejectCollect(id object_id)
{
if (object_id == Coal || object_id->~IsLiquid())
return false;
return true;
}
/*-- Properties --*/
local ActMap = {
Drive = {
Prototype = Action,
Name = "Drive",
Procedure = DFA_NONE,
Directions = 2,
FlipDir = 1,
X = 0,
Y = 0,
Wdt = 24,
Hgt = 22,
NextAction = "Drive",
},
};
// this.MeshTransformation = Trans_Mul(Trans_Rotate(90, 0, 0, 1), Trans_Scale(580, -580, 580), Trans_Translate(24000, -27000, 0))
local MeshTransformation = [0, 580, 0, -15660, 580, 0, 0, 13920, 0, 0, 580, 0];
// this.PictureTransformation = Trans_Mul(Trans_Translate(-18000, 27000, 0), Trans_Rotate(90, 0, 0, 1), Trans_Rotate(-20, 1, 0, 0))
local PictureTransformation = [0, -940, -342, -18000, 1000, 0, 0, 27000, 0, -342, 940, 0];
local Name = "$Name$";
local Description = "$Description$";
local BorderBound = C4D_Border_Sides;
local ContactCalls = true;
local Components = {Wood = 1, Metal = 4};
local LiquidCapacity = 2400;