openclonk/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Hoist.ocd/Script.c

263 lines
5.9 KiB
C

/**
Cable Hoist
@author Clonkonaut
*/
#include Library_CableCar
local pickup;
/*-- Creation --*/
public func Construction()
{
this.MeshTransformation = Trans_Rotate(13, 0, 1, 0);
SetCableSpeed(1);
}
/*-- Engine Callbacks --*/
public func Damage(int change, int cause)
{
if (cause == FX_Call_DmgBlast)
{
// Explosions knock the hoist off the rail
if (GetAction() == "OnRail")
DisengageRail();
if (pickup)
DropVehicle();
}
}
/*-- Status --*/
public func IsToolProduct() { return true; }
/*-- Cable Car Library --*/
public func GetCableOffset(array position, int prec)
{
if (!prec)
prec = 1;
position[1] += 5 * prec;
}
public func Engaged()
{
this.Touchable = 0;
SetAction("OnRail");
}
public func Disengaged()
{
this.Touchable = 1;
SetAction("Idle");
if (pickup)
DropVehicle();
}
public func GetCableCarExtraMenuEntries(array menu_entries, proplist custom_entry, object clonk)
{
if (IsTravelling())
return;
if (!pickup && GetRailTarget())
{
// Picking up vehicles
var vehicles = FindObjects(Find_AtPoint(), Find_Category(C4D_Vehicle), Find_Not(Find_Func("RejectCableCarPickup", this)), Find_Exclude(this));
var i = 0;
for (var vehicle in vehicles)
{
if (GetEffect("FxCableHoistPickup", vehicle)) continue;
var to_pickup = new custom_entry {
Priority = 2000 + i,
Tooltip = "$TooltipPickup$",
OnClick = GuiAction_Call(this, "PickupVehicle", vehicle),
image = { Prototype = custom_entry.image, Symbol = vehicle },
icon = { Prototype = custom_entry.icon, Symbol = Icon_LibraryCableCar, GraphicsName = "Engage" }
};
PushBack(menu_entries, { symbol = vehicle, extra_data = "Pickup", custom = to_pickup });
i++;
}
}
else if (pickup && GetRailTarget())
{
// Drop the vehicle
var drop = new custom_entry {
Priority = 2000,
Tooltip = "$TooltipDrop$",
OnClick = GuiAction_Call(this, "DropVehicle"),
image = { Prototype = custom_entry.image, Symbol = pickup },
icon = { Prototype = custom_entry.icon, Symbol = Icon_LibraryCableCar, GraphicsName = "Disengage" }
};
PushBack(menu_entries, { symbol = pickup, extra_data = "Drop", custom = drop });
}
}
public func OnCableCarHover(symbol, extra_data, desc_menu_target, menu_id)
{
if (symbol && extra_data == "Pickup")
{
GuiUpdate({ Text = Format("$DescPickup$", symbol->GetName()) }, menu_id, 1, desc_menu_target);
return;
}
if (symbol && extra_data == "Drop")
{
GuiUpdate({ Text = Format("$DescDrop$", symbol->GetName()) }, menu_id, 1, desc_menu_target);
return;
}
return _inherited(symbol, extra_data, desc_menu_target, menu_id, ...);
}
/*-- Picking up vehicles --*/
public func PickupVehicle(object vehicle)
{
if (!vehicle) return;
if (GetEffect("FxCableHoistPickup", vehicle)) return;
var width = vehicle->GetObjWidth() / 2;
var height = vehicle->GetObjHeight() / 2;
if (!Inside(GetX(), vehicle->GetX() - width, vehicle->GetX() + width))
if (!Inside(GetY(), vehicle->GetY() - height, vehicle->GetY() + height))
return;
vehicle->CreateEffect(FxCableHoistPickup, 1, 1, this);
pickup = vehicle;
UpdateInteractionMenus(this.GetCableCarMenuEntries);
}
public func DropVehicle()
{
if (!pickup) return;
RemoveEffect("FxCableHoistPickup", pickup);
pickup = nil;
UpdateInteractionMenus(this.GetCableCarMenuEntries);
}
local FxCableHoistPickup = new Effect
{
Construction = func(object hoist)
{
this.hoist = hoist;
this.vehicle_touchable = Target.Touchable;
Target.Touchable = 0;
// Follow motion of hoist.
Target->SetPosition(this.hoist->GetX(10), this.hoist->GetY(10) + 4, false, 10);
Target->SetSpeed(0, 0);
Target->SetR(this.hoist->GetR());
Target->SetRDir(0);
},
Timer = func(int time)
{
// Follow motion of hoist.
Target->SetPosition(this.hoist->GetX(10), this.hoist->GetY(10) + 4, false, 10);
Target->SetSpeed(0, 0);
},
Destruction = func()
{
Target.Touchable = this.vehicle_touchable;
}
};
/*-- Actions --*/
public func OnRail()
{
DoMovement();
}
local ActMap = {
OnRail = {
Prototype = Action,
Name = "OnRail",
Procedure = DFA_FLOAT,
Directions = 2,
FlipDir = 1,
Length = 1,
Delay = 1,
X = 0,
Y = 0,
Wdt = 26,
Hgt = 18,
EndCall = "OnRail",
NextAction = "OnRail",
},
};
/*-- Callbacks --*/
public func GetAttachedVehicle()
{
return pickup;
}
// Calls from the stations will mostly be forwarded to the attached vehicle
public func DropContents(proplist station)
{
if (pickup)
pickup->DropContents(station);
}
// Check for available contents
public func IsAvailable(proplist requested, int amount)
{
// So far only do something if a lorry is connected, all other vehicles are considered off-limits
if (pickup && pickup->~IsLorry())
if (pickup->ContentsCount(requested) >= amount)
return true;
return false;
}
// Called when a station has asked to make a delivery
public func IsReadyForDelivery(proplist requested, int amount, proplist requesting_station)
{
// Is already on a delivery.
if (lib_ccar_delivery)
return false;
// Only if a lorry is connected
if (pickup && pickup->~IsLorry())
{
// Lorry must have enough space left...
if (pickup->ContentsCount() + amount <= pickup.MaxContentsCount)
return true;
// ...or contain the requested objects
if (pickup->ContentsCount(requested) >= amount)
return true;
}
return false;
}
// Called when searching for a better option to deliver something
public func OverridePriority(proplist requested, int amount, proplist requesting_station, proplist best)
{
// Check if the connected vehicle holds the requested objects and if yes, override the selection
if (pickup && pickup->ContentsCount(requested) >= amount)
return true;
return false;
}
/*-- Definition --*/
public func Definition(def)
{
def.PictureTransformation = Trans_Mul(Trans_Rotate(-25, 1, 0, 0), Trans_Rotate(40, 0, 1, 0));
}
local Name = "$Name$";
local Description = "$Description$";
local Touchable = 1;
local BorderBound = C4D_Border_Sides;
local Components = {Metal = 2};