Work save regarding cable cars/lorries.

Started to work on a few station configuration options and combining these with producers for requesting materials (which now kind of works).
install-platforms
Clonkonaut 2017-10-04 01:19:46 +02:00
parent 3eb6dcbcd3
commit 3c87d0f135
15 changed files with 764 additions and 259 deletions

View File

@ -21,6 +21,8 @@ local lib_ccar_progress;
local lib_ccar_max_progress;
// This target point for pathfinding
local lib_ccar_destination;
// Current delivery the car is on, array: [starting station, target station, requested objects, amount]
local lib_ccar_delivery;
/*--- Overloads ---*/
@ -240,6 +242,7 @@ public func EngageRail(object crossing, bool silent)
UpdateInteractionMenus(this.GetCableCarMenuEntries);
Engaged();
lib_ccar_rail->OnCableCarEngaged(this);
}
// Detach the car from its current holding point (cable or crossing, does not matter)
@ -253,6 +256,7 @@ public func DisengageRail()
UpdateInteractionMenus(this.GetCableCarMenuEntries);
Disengaged();
if (lib_ccar_rail) lib_ccar_rail->OnCableCarDisengaged(this);
}
// Sets a target point for travelling and starts the movement process
@ -270,6 +274,8 @@ public func SetDestination(dest)
{
OnStart();
CrossingReached();
if (lib_ccar_rail)
lib_ccar_rail->~OnCableCarDeparture(this);
}
}
@ -299,6 +305,13 @@ func DestinationReached()
lib_ccar_max_progress = 0;
OnStop(false);
if (lib_ccar_rail)
{
if (lib_ccar_delivery)
FinishedRequest(lib_ccar_rail);
lib_ccar_rail->OnCableCarArrival(this);
}
}
// When the way to the current destination has vanished somehow
@ -364,41 +377,16 @@ public func OpenDestinationSelection(object clonk)
}
/*-- Delivery --*/
/*
local deliver_id, deliver_amount, deliver_to;
// Returns true when this car is not in move
public func IsAvailable()
public func AddRequest(proplist requested, int amount, proplist target, proplist source)
{
return !lib_ccar_destination;
lib_ccar_delivery = [source, target, requested, amount];
SetDestination(target);
}
public func AddDelivery(object from, object to, id object_id, int amount)
func FinishedRequest(object station)
{
deliver_id = object_id;
deliver_amount = amount;
deliver_to = to;
SetDestination(from);
}
public func ReturnDelivery()
{
SetDestination(deliver_to);
}
public func DeliverObjects()
{
if (ContentsCount(deliver_id) < deliver_amount) return DeliveryFailed();
for (var i = 0; i < deliver_amount; i++)
FindContents(deliver_id)->Enter(lib_ccar_rail);
lib_ccar_rail->DeliveryDone(deliver_id, deliver_amount);
deliver_id = false;
deliver_amount = false;
deliver_to = false;
}
private func DeliveryFailed()
{
}
*/
if (station && lib_ccar_delivery)
station->RequestArrived(this, lib_ccar_delivery[2], lib_ccar_delivery[3]);
lib_ccar_delivery = nil;
}

View File

@ -23,6 +23,28 @@ public func CableActivation(int count) { }
// count is a value indicating the amount of deactivations (e.g. a cable with more than one car broke).
public func CableDeactivation(int count) { }
// Called by arriving cable cars if this station is the final stop
public func OnCableCarArrival(object car) { }
// Called by departing cable cars if it just starts a new journey
public func OnCableCarDeparture(object car) { }
// Called by a cable car that has been hooked up to the rail at this station
public func OnCableCarEngaged(object car) { }
// Called by a cable car that has been taken off the rail at this station
public func OnCableCarDisengaged(object car) { }
// Called when a cable car with a requested delivery arrives
public func OnCableCarDelivery(object car, id requested, int amount) { }
// Called by other stations to check if a certain object and amount are available for delivery at this station.
// Return true if there are means to collect the required amount.
public func IsAvailable(proplist requested, int amount)
{
return false;
}
/*--- Callbacks ---*/
// Be sure to always call these via _inherited(...);
@ -30,6 +52,7 @@ public func CableDeactivation(int count) { }
func Initialize()
{
destination_list = [];
request_queue = [];
return _inherited(...);
}
@ -360,103 +383,115 @@ public func GetLengthToTarget(object end)
}
/*-- Auto production --*/
/*
public func CheckAcquire(id object_id, int amount)
{
var container = false;
for (var list_item in destination_list)
if (list_item[const_finaldestination]->CheckAvailability(object_id, amount))
{
if (!container) container = list_item[const_finaldestination];
else if (GetLengthToTarget(container) > GetLengthToTarget(list_item[const_finaldestination]))
container = list_item[const_finaldestination];
}
return container;
}
public func CheckAcquiringCar(object target)
{
var car = false;
if (!target) target = this;
for (var car_to_check in FindObjects(Find_Func("IsCableCar")))
{
if (car_to_check->GetRailTarget() == target)
{
if (car_to_check->IsAvailable())
return car_to_check;
}
else if (car_to_check->GetRailTarget() == this)
if (car_to_check->IsAvailable())
car = car_to_check;
}
return car;
}
local request_queue;
public func DoAcquire(id object_id, int amount)
// Add a new acquiring order
public func AddRequest(proplist requested_id, int amount)
{
// Check if the objects are available
var container = CheckAcquire(object_id, amount);
if (!container) return false;
// Check if a cable car is available
var car = CheckAcquiringCar(container);
if (!car) return false;
container->AddReservation(object_id, amount);
car->AddDelivery(container, nil, object_id, amount);
return true;
}
public func DeliveryDone(id object_id, int amount)
{
// Nothing so far
}
/*-- Object requests and deliveries --*/
/*
local reservations; // two dimensional array with ongoing deliveries: [[ID, amount]]
public func CheckAvailability(id object_id, int amount)
{
if (ContentsCount(object_id) < amount) return false;
var reserved = 0;
for (var reservation in reservations)
if (reservation[0] == object_id)
reserved += reservation[1];
if (ContentsCount(object_id) - reserved < amount)
return false;
return true;
}
public func AddReservation(id object_id, int amount)
{
reservations[GetLength(reservations)] = [object_id, amount];
}
public func RemoveReservation(id object_id, int amount)
{
var new_list = [], removed = false;
for (var reservation in reservations)
{
if (reservation[0] == object_id && reservation[1] == amount && !removed)
{
removed = true;
continue;
}
new_list[GetLength(new_list)] = reservation;
}
reservations = new_list;
}
public func AddRequest(id requested_id, int amount, id requested_object)
{
if (!requested_id && !requested_object) return false;
if (!requested_id) return false;
if (!amount) amount = 1;
// First of all check if a similar request already is on the line
// Similar requests will be dismissed, even if they are technically new
for (var request in request_queue)
if (request[0] == requested_id)
if (request[1] == amount)
return true; // The request is considered handled
var source = CheckAvailability(requested_id, amount);
if (!source)
return false; // Items are not available
var car = source->GetAvailableCableCar(requested_id, amount, this);
if (!car)
return false; // No cable car is available for delivery
// Great. Start working immediately
PushBack(request_queue, [requested_id, amount]);
car->AddRequest(requested_id, amount, this, source);
return true;
}
public func RequestObjects(object requester, id request_id, int amount)
// Check all connected stations for available objects
func CheckAvailability(proplist requested, int amount)
{
if (ContentsCount(request_id) < amount)
var nearest_station;
var length_to;
for (var destination in destination_list)
{
if (destination[const_finaldestination]->IsAvailable(requested, amount))
{
var station = destination[const_finaldestination];
if (!nearest_station)
{
nearest_station = station;
length_to = GetLengthToTarget(nearest_station);
}
else {
// Storages (like chests) are always preferred over other producer because the items
// might be stored in another producer to produce something
if (station->~IsStorage() && !nearest_station->~IsStorage())
{
nearest_station = station;
length_to = GetLengthToTarget(nearest_station);
}
else if (nearest_station->~IsStorage() && !station->~IsStorage())
continue;
// Otherwise the shorter the path, the better
else if (GetLengthToTarget(station) < length_to)
{
nearest_station = station;
length_to = GetLengthToTarget(nearest_station);
}
}
}
}
return nearest_station;
}
// Check if there is a cable car ready for delivery
public func GetAvailableCableCar(proplist requested, int amount, proplist requesting_station)
{
}
// A delivery has arrived, remove it from the queue and handle the request
public func RequestArrived(proplist car, proplist requested_id, int amount)
{
if (!HasRequest(requested_id, amount))
return;
OnCableCarDelivery(car, requested_id, amount);
RemoveRequest(requested_id, amount);
}
public func HasRequest(id requested, int amount)
{
for (var i = 0; i < GetLength(request_queue); i++)
{
if (request_queue[i][0] != requested)
continue;
if (request_queue[i][1] != amount)
continue;
return true;
}
return false;
}
public func RemoveRequest(id requested, int amount)
{
for (var i = 0; i < GetLength(request_queue); i++)
{
if (request_queue[i][0] != requested)
continue;
if (request_queue[i][1] != amount)
continue;
break;
}
if (i >= GetLength(request_queue))
return false;
for (var i = 0; i < amount; i++)
FindContents(request_id)->Enter(requester);
RemoveArrayIndex(request_queue, i, true);
return true;
}*/
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -62,4 +62,26 @@ material CableCarStation_SignStation
}
}
}
}
material CableCarStation_SignDropOff
{
receive_shadows on
technique
{
pass
{
ambient 1.0 1.0 1.0 1.0
diffuse 1.0 1.0 1.0 1.0
specular 0.0 0.0 0.0 1.0 12.5
emissive 1.0 1.0 1.0 1.0
texture_unit
{
texture CableCarStation_dropoff.png
tex_address_mode wrap
filtering trilinear
}
}
}
}

View File

@ -9,18 +9,31 @@
#include Library_CableStation
// Animation
local turn_anim;
// Settings
local setting_dropoff = false;
// Combined building
local connected_building;
// Array of all cable cars currently idling at this station
local arrived_cars;
func Initialize()
{
turn_anim = PlayAnimation("Engine", 1, Anim_Const(0), Anim_Const(1000));
arrived_cars = [];
SetCategory(GetCategory() | C4D_StaticBack);
return _inherited(...);
}
// Prevents the automatic change of the station status when manually set to station mode
local manual_setting = false;
// Called from the cable crossing library
/* Library functions: Cable Station */
public func DestinationsUpdated()
{
// Do nothing if set manually
@ -33,6 +46,100 @@ public func DestinationsUpdated()
CheckStationStatus();
}
public func IsAvailable(proplist requested, int amount)
{
// Check connected buildings for contents
if (connected_building)
if (connected_building->ContentsCount(requested) >= amount)
return true;
// Check cable cars idling at this station
if (GetLength(arrived_cars))
{
for (var car in arrived_cars)
{
if (car->~IsAvailable(requested, amount))
return true;
}
}
return false;
}
public func GetAvailableCableCar(proplist requested, int amount, proplist requesting_station)
{
// Check cars that are idling at this station
var best;
for (var car in arrived_cars)
{
if (!car->~IsReadyForDelivery(requested, amount, requesting_station))
continue;
if (!best)
best = car;
// A car might want to override the search for an available car, mainly because it holds the container
// which holds the requested items
else if (car->~OverridePriority(requested, amount, requesting_station, best))
best = car;
}
if (best)
return best;
// Check cars that are idling at the requesting station
if (requesting_station != this)
if (best = requesting_station->~GetAvailableCableCar(requested, amount, requesting_station))
return best;
return nil;
}
public func OnCableCarDelivery(object car, id requested, int amount)
{
// Transfer the requested material to the connected producer
if (!connected_building)
return;
car = car->~GetAttachedVehicle() ?? car;
for (var i = 0; i < amount; i++)
{
var item = car->FindContents(requested);
if (!item)
break;
item->Enter(connected_building);
}
}
/* Construction */
public func IsHammerBuildable() { return true; }
public func ConstructionCombineWith() { return "IsNoCableStationConnected"; }
public func ConstructionCombineDirection(object other)
{
return CONSTRUCTION_STICK_Left | CONSTRUCTION_STICK_Right;
}
public func ConstructionCombineOffset(proplist other)
{
if (!other)
return;
// Make sure the station preview is on the same ground level than the other building
var ret = [0,0];
ret[1] = other->GetObjHeight()/2 - this->GetDefHeight()/2;
return ret;
}
public func CombineWith(object stick_to)
{
if (!stick_to) return;
if (stick_to->~IsProducer())
{
connected_building = stick_to;
stick_to->ConnectCableStation(this);
}
}
/* Interaction */
// Provides an own interaction menu.
@ -75,15 +182,27 @@ public func GetSettingsMenuEntries()
var menu_entries = [];
// Clickable buttons
var station = new custom_entry {
Priority = 1000,
Tooltip = "$TooltipToggleStation$",
OnClick = GuiAction_Call(this, "ToggleStation", false)
OnClick = GuiAction_Call(this, "ToggleStation", false),
image = { Prototype = custom_entry.image }
};
station.image.Symbol = CableCrossing_Icons;
station.image.GraphicsName = "Station";
PushBack(menu_entries, { symbol = CableCrossing_Icons, extra_data = "Station", custom = station });
var drop_off = new custom_entry {
Priority = 1001,
Tooltip = "$TooltipToggleDropOff$",
OnClick = GuiAction_Call(this, "ToggleDropOff", false),
image = { Prototype = custom_entry.image }
};
drop_off.image.Symbol = CableCrossing_Icons;
drop_off.image.GraphicsName = "DropOff";
PushBack(menu_entries, { symbol = CableCrossing_Icons, extra_data = "DropOff", custom = drop_off });
return menu_entries;
}
@ -94,6 +213,8 @@ public func OnSettingsHover(symbol, extra_data, desc_menu_target, menu_id)
var text = "";
if (extra_data == "Station")
text = "$DescToggleStation$";
if (extra_data == "DropOff")
text = "$DescToggleDropOff$";
GuiUpdate({ Text = text }, menu_id, 1, desc_menu_target);
}
@ -110,12 +231,63 @@ public func ToggleStation(bool silent)
CheckStationStatus();
}
public func ToggleDropOff(bool silent)
{
if (!setting_dropoff)
{
if (!IsCableStation())
ToggleStation(true);
setting_dropoff = true;
} else {
setting_dropoff = false;
}
if (!silent)
Sound("UI::Click2");
CheckStationStatus();
}
/* Cable Car Management */
public func OnCableCarArrival(object car)
{
// Apply all settings to the arriving car
if (setting_dropoff)
if (car)
car->~DropContents(this);
// Save the car
PushBack(arrived_cars, car);
}
public func OnCableCarDeparture(object car)
{
RemoveArrayValue(arrived_cars, car, true);
}
public func OnCableCarEngaged(object car)
{
PushBack(arrived_cars, car);
}
public func OnCableCarDisengaged(object car)
{
RemoveArrayValue(arrived_cars, car, true);
}
/* Visuals */
func CheckStationStatus()
{
if (IsCableStation())
SetMeshMaterial("CableCarStation_SignStation", 1);
{
// In order of priority
if (setting_dropoff)
{
SetMeshMaterial("CableCarStation_SignDropOff", 1);
} else {
SetMeshMaterial("CableCarStation_SignStation", 1);
}
}
else
SetMeshMaterial("CableCarStation_Sign", 1);
}
@ -147,11 +319,16 @@ func SaveScenarioObject(props)
props->AddCall("StationSetting", this, "ToggleStation", true);
if (!IsCableStation() && manual_setting)
props->AddCall("ManualSetting", this, "SetManual");
if (connected_building)
props->AddCall("Combination", this, "CombineWith", connected_building);
return true;
}
public func SetManual() { manual_setting = true; return true; }
/* Properties */
local Name = "$Name$";
local BlastIncinerate = 50;
local LineAttach = [6,-9];

View File

@ -3,5 +3,7 @@ Name=Cable Crossing
StationSettings=Cable crossing settings
TooltipToggleStation=Toggle station status
TooltipToggleDropOff=Toggle item dropping status
DescToggleStation=Manually set or unset this crossing to be a cable station. Cable stations are selectable as targets when engaging a cable car onto the cable.
DescToggleStation=Manually set or unset this crossing to be a cable station. Cable stations are selectable as targets when engaging a cable car onto the cable.
DescToggleDropOff=All arriving vehicle are emptied upon arrival at this station (giving it is the final stop). Will also be set as a cable station.

View File

@ -12,6 +12,20 @@ func Construction()
SetCableSpeed(1);
}
/* Engine Callbacks */
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; }
@ -21,7 +35,7 @@ public func IsToolProduct() { return true; }
func GetCableOffset(array position, int prec)
{
if (!prec) prec = 1;
position[1] += 7 * prec;
position[1] += 5 * prec;
}
func Engaged()
@ -97,7 +111,7 @@ public func DropVehicle()
func FxCableHoistPickupStart(object vehicle, proplist effect)
{
vehicle->SetPosition(GetX(), GetY());
vehicle->SetPosition(GetX(), GetY()+4);
vehicle->SetSpeed(0,0);
vehicle->SetR(GetR());
vehicle->SetRDir(0);
@ -107,7 +121,7 @@ func FxCableHoistPickupStart(object vehicle, proplist effect)
func FxCableHoistPickupTimer(object vehicle, proplist effect)
{
vehicle->SetPosition(GetX(), GetY());
vehicle->SetPosition(GetX(), GetY()+4);
vehicle->SetSpeed(0,0);
}
@ -141,6 +155,59 @@ local ActMap = {
},
};
/* 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)
{
// 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 */
func Definition(def)
{
SetProperty("PictureTransformation",Trans_Mul(Trans_Rotate(-25,1,0,0),Trans_Rotate(40,0,1,0)),def);

View File

@ -1,73 +1,65 @@
/*-- Lorry --*/
/**
Lorry
Transportation and storage for up to 50 objects.
@authors Maikel
*/
local content_menu;
protected func Construction()
{
//PlayAnimation("Open", 1, Anim_Linear(0, 0, 1, 20, ANIM_Hold));
SetProperty("MeshTransformation",Trans_Rotate(13,0,1,0));
}
public func IsLorry() { return true; }
public func IsToolProduct() { return true; }
#include Library_ElevatorControl
local drive_anim;
local tremble_anim;
local empty_anim;
local tilt_anim;
/*-- Engine Callbacks --*/
protected func Initialize()
func Construction()
{
drive_anim = PlayAnimation("Drive", 1, Anim_Const(0), Anim_Const(500));
//tremble_anim = PlayAnimation("Tremble", 5, Anim_Const(0), Anim_Const(500));
tilt_anim = PlayAnimation("Empty", 1, Anim_Const(0), Anim_Const(100));
iRotWheels = 0;
AddTimer("TurnWheels", 1);
iTremble = 0;
return _inherited(...);
SetProperty("MeshTransformation", Trans_Rotate(13, 0, 1, 0));
}
private func Disengaged()
func Initialize()
{
SetAction("Drive");
drive_anim = PlayAnimation("Drive", 1, Anim_X(0,0, GetAnimationLength("Drive"), 30), Anim_Const(1000));
empty_anim = PlayAnimation("Empty", 2, Anim_Const(0), Anim_Const(0));
}
/*-- Movement --*/
protected func ContactLeft()
func Hit3()
{
if (Stuck() && !Random(5))
SetRDir(RandomX(-7, +7));
Sound("Hits::Materials::Metal::DullMetalHit?");
}
protected func ContactRight()
{
if (Stuck() && !Random(5))
SetRDir(RandomX(-7, +7));
}
/*-- Contents --*/
local MaxContentsCount = 50;
protected func RejectCollect(id object_id, object obj)
func RejectCollect(id object_id, object obj)
{
// Collection maybe blocked if this object was just dumped.
if (!obj->Contained() && GetEffect("BlockCollectionByLorry", obj))
return true;
// Objects can still be collected.
if (ContentsCount() < MaxContentsCount)
{
Sound("Objects::Clonk");
return false;
}
// The object cannot be collected, notify carrier?
if (obj->Contained())
return Message("$TxtLorryisfull$");
return _inherited(object_id, obj, ...);
Message("$TxtLorryisfull$");
else
{
// If not carried, objects slide over the lorry.
if (Abs(obj->GetXDir()) > 5)
{
obj->SetYDir(-2);
obj->SetRDir(0);
Sound("Hits::SoftHit*");
}
}
// Reject collection.
return true;
}
// Automatic unloading in buildings.
protected func Entrance(object container)
func Entrance(object container)
{
// Only in buildings
if (container->GetCategory() & (C4D_StaticBack | C4D_Structure))
@ -77,67 +69,235 @@ protected func Entrance(object container)
container->GrabContents(this);
}
local iRotWheels;
local iTremble;
func TurnWheels()
func ContactLeft()
{
// TODO: Use Anim_X(Dir), keep from timer=1
// TODO: Could also use GetAnimationPosition() instead of these local variables...
iRotWheels += GetXDir()*2000/100; // Einmal rum (20 frames mal 10fps) nach 10 m
while(iRotWheels < 0) iRotWheels += 2000;
while(iRotWheels > 2000) iRotWheels -= 2000;
SetAnimationPosition(drive_anim, Anim_Const(iRotWheels));
if(Random(100) < Abs(GetXDir()))
{
iTremble += 100;
if(iTremble < 0) iTremble += 2000;
if(iTremble > 2000) iTremble -= 2000;
//SetAnimationPosition(tremble_anim, Anim_Const(iTremble));
}
if (Stuck() && !Random(5))
SetRDir(RandomX(-7, +7));
}
func ContactRight()
{
if (Stuck() && !Random(5))
SetRDir(RandomX(-7, +7));
}
func Damage(int change, int cause, int by_player)
{
// Only explode the lorry on blast damage.
if (cause != FX_Call_DmgBlast)
return _inherited(change, cause, by_player, ...);
// Explode the lorry when it has taken to much damage.
if (GetDamage() > 100)
{
// Only exit objects and parts if this lorry is not contained.
if (!Contained())
{
// First eject the contents in different directions.
for (var obj in FindObjects(Find_Container(this)))
{
var speed = RandomX(3, 5);
var angle = Random(360);
var dx = Cos(angle, speed);
var dy = Sin(angle, speed);
obj->Exit(RandomX(-4, 4), RandomX(-4, 4), Random(360), dx, dy, RandomX(-20, 20));
obj->SetController(by_player);
}
// Toss around some fragments with particles attached.
for (var i = 0; i < 6; i++)
{
var fragment = CreateObject(LorryFragment, RandomX(-4, 4), RandomX(-4, 4), GetOwner());
var speed = RandomX(40, 60);
var angle = Random(360);
var dx = Cos(angle, speed);
var dy = Sin(angle, speed);
fragment->SetXDir(dx, 10);
fragment->SetYDir(dy, 10);
fragment->SetR(360);
fragment->SetRDir(RandomX(-20, 20));
// Set the controller of the fragments to the one causing the blast for kill tracing.
fragment->SetController(by_player);
// Incinerate the fragments.
fragment->Incinerate(100, by_player);
}
}
// Remove the lorry itself, eject possible contents as they might have entered again.
// Or let the engine eject the contents if it is inside a container.
return RemoveObject(true);
}
return _inherited(change, cause, by_player, ...);
}
/*-- Callbacks --*/
public func IsLorry() { return true; }
public func IsVehicle() { return true; }
public func IsContainer() { return true; }
// Called upon arrival at a cable station
public func DropContents(proplist station)
{
// Drop everything in a few seconds
SetAnimationWeight(empty_anim, Anim_Const(1000));
SetAnimationPosition(empty_anim, Anim_Linear(0,0, GetAnimationLength("Empty"), 35, ANIM_Hold));
ScheduleCall(this, "Empty", 35);
}
func Empty()
{
// Exit everything at once (as opposed to manual dumping below)
while (Contents())
{
var content = Contents();
AddEffect("BlockCollectionByLorry", content, 100, 16, this);
content->Exit(RandomX(-5,5), RandomX(-2,2), Random(360));
}
SetAnimationWeight(empty_anim, Anim_Linear(1000,1000, 0, 35, ANIM_Hold));
SetAnimationPosition(empty_anim, Anim_Linear(GetAnimationLength("Empty"), GetAnimationLength("Empty"), 0, 35, ANIM_Hold));
}
/*-- Usage --*/
public func HoldingEnabled() { return true; }
public func ControlUseStart(object clonk, int x, int y)
{
var direction = DIR_Left;
if (x > 0)
direction = DIR_Right;
if (!GetEffect("DumpContents", this))
AddEffect("DumpContents", this, 100, 1, this, nil, direction);
return true;
}
public func ControlUseHolding(object clonk, int x, int y)
{
var direction = DIR_Left;
if (x > 0)
direction = DIR_Right;
var effect = GetEffect("DumpContents", this);
if (effect)
effect.dump_dir = direction;
return true;
}
public func ControlUseStop(object clonk, int x, int y)
{
RemoveEffect("DumpContents", this);
return true;
}
public func ControlUseCancel(object clonk, int x, int y)
{
RemoveEffect("DumpContents", this);
return true;
}
public func FxDumpContentsStart(object target, proplist effect, int temp, int direction)
{
if (temp)
return FX_OK;
// The time it takes to dump the contents depends on the mass of the lorry.
effect.dump_strength = BoundBy(1000 / GetMass(), 3, 8);
effect.dump_dir = direction;
// Rotate the lorry into the requested direction.
var rdir = -effect.dump_strength;
if (effect.dump_dir == DIR_Right)
rdir = effect.dump_strength;
SetRDir(rdir);
// Start dump sounds together.
Sound("Objects::Lorry::Dump1", false, 100, nil, +1);
Sound("Objects::Lorry::Dump2", false, 100, nil, +1);
return FX_OK;
}
public func FxDumpContentsTimer(object target, proplist effect, int time)
{
// Rotate the lorry into the requested direction.
var rdir = -effect.dump_strength;
if (effect.dump_dir == DIR_Right)
rdir = effect.dump_strength;
SetRDir(rdir);
// Dump one item every some frames if the angle is above 45 degrees. Only do this if the effect is at least active
// for 10 frames to prevent an accidental click while holding the lorry to dump some of its contents.
if (time >= 10 && ((effect.dump_dir == DIR_Left && GetR() < -45) || (effect.dump_dir == DIR_Right && GetR() > 45)))
{
if (!Random(3))
{
var x = RandomX(6, 8) * Sign(GetR());
var xdir = RandomX(70, 90) * Sign(GetR());
var random_content = FindObjects(Find_Container(this), Sort_Random());
if (GetLength(random_content) >= 1)
{
random_content = random_content[0];
random_content->Exit(x, RandomX(2, 3), Random(360), 0, 0, RandomX(-5, 5));
random_content->SetXDir(xdir, 100);
// Assume the controller of the lorry is also the one dumping the contents.
random_content->SetController(GetController());
AddEffect("BlockCollectionByLorry", random_content, 100, 8, this);
if (random_content->~IsLiquid())
{
random_content->SetPosition(GetX(), GetY());
random_content->Disperse(GetR() + 10 * Sign(GetR()));
}
}
}
}
return FX_OK;
}
public func FxDumpContentsStop(object target, proplist effect, int reason, bool temp)
{
if (temp)
return FX_OK;
// Stop rotating the lorry.
SetRDir(0);
// Stop dump sounds.
Sound("Objects::Lorry::Dump1", false, 100, nil, -1);
Sound("Objects::Lorry::Dump2", false, 100, nil, -1);
return FX_OK;
}
public func FxBlockCollectionByLorryTimer() { return FX_Execute_Kill; }
/*-- Production --*/
public func IsToolProduct() { return true; }
/*-- Actions --*/
local ActMap = {
Drive = {
Prototype = Action,
Name = "Drive",
Procedure = DFA_NONE,
Directions = 2,
FlipDir = 1,
Length = 20,
Delay = 2,
X = 0,
Y = 0,
Wdt = 22,
Hgt = 16,
NextAction = "Drive",
//Animation = "Drive",
},
OnRail = {
Prototype = Action,
Name = "OnRail",
Procedure = DFA_FLOAT,
Directions = 2,
FlipDir = 1,
Length = 1,
Delay = 1,
X = 0,
Y = 0,
Wdt = 22,
Hgt = 16,
StartCall="OnRail",
NextAction = "OnRail",
//Animation = "Drive",
},
Drive = {
Prototype = Action,
Name = "Drive",
Procedure = DFA_NONE,
Directions = 2,
FlipDir = 1,
Length = 20,
Delay = 2,
X = 0,
Y = 0,
Wdt = 22,
Hgt = 16,
NextAction = "Drive",
//Animation = "Drive",
},
};
func Definition(def)
/*-- Display --*/
public func Definition(proplist 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);
}
/*-- Properties --*/
local Name = "$Name$";
local Description = "$Description$";
local Touchable = 1;
local BorderBound = C4D_Border_Sides;
local ContactCalls = true;
local ContactCalls = true;
local Components = {Metal = 2, Wood = 1};
local MaxContentsCount = 50;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -4,114 +4,162 @@ func InitializeObjects()
{
var CableCrossing001 = CreateObjectAbove(CableCrossing, 347, 389);
var CableCrossing002 = CreateObjectAbove(CableCrossing, 554, 391);
CableCrossing002->SetMeshMaterial("CableCarStation_SignStation", 1);
CableCrossing002->ToggleStation(true);
var CableLine001 = CreateObjectAbove(CableLine, 551, 749);
var CableLine001 = CreateObject(CableLine, 551, 749);
CableLine001.LineColors = [-15461326,-15461326];
CableLine001->SetPosition(551, 749);
CableLine001->SetAction("Connect", CableCrossing001, CableCrossing002);
CableLine001->SetConnectedObjects(CableCrossing001, CableCrossing002);
var CableCrossing003 = CreateObjectAbove(CableCrossing, 209, 390);
var CableLine002 = CreateObjectAbove(CableLine, 206, 747);
var CableLine002 = CreateObject(CableLine, 206, 747);
CableLine002.LineColors = [-15461326,-15461326];
CableLine002->SetPosition(206, 747);
CableLine002->SetAction("Connect", CableCrossing001, CableCrossing003);
CableLine002->SetConnectedObjects(CableCrossing001, CableCrossing003);
var CableCrossing004 = CreateObjectAbove(CableCrossing, 652, 491);
var CableLine003 = CreateObjectAbove(CableLine, 551, 849);
var CableLine003 = CreateObjectAbove(CableLine, 551, 1319);
CableLine003.LineColors = [-15461326,-15461326];
CableLine003->SetAction("Connect", CableCrossing004, CableCrossing002);
CableLine003->SetConnectedObjects(CableCrossing004, CableCrossing002);
var CableCrossing005 = CreateObjectAbove(CableCrossing, 694, 419);
var CableLine004 = CreateObjectAbove(CableLine, 651, 949);
var CableLine004 = CreateObjectAbove(CableLine, 651, 1419);
CableLine004.LineColors = [-15461326,-15461326];
CableLine004->SetAction("Connect", CableCrossing005, CableCrossing004);
CableLine004->SetConnectedObjects(CableCrossing005, CableCrossing004);
var CableCrossing006 = CreateObjectAbove(CableCrossing, 770, 360);
var CableLine005 = CreateObjectAbove(CableLine, 693, 806);
var CableLine005 = CreateObjectAbove(CableLine, 693, 1204);
CableLine005.LineColors = [-15461326,-15461326];
CableLine005->SetAction("Connect", CableCrossing006, CableCrossing005);
CableLine005->SetConnectedObjects(CableCrossing006, CableCrossing005);
var CableCrossing007 = CreateObjectAbove(CableCrossing, 810, 351);
var CableLine006 = CreateObjectAbove(CableLine, 771, 687);
var CableLine006 = CreateObjectAbove(CableLine, 771, 1026);
CableLine006.LineColors = [-15461326,-15461326];
CableLine006->SetAction("Connect", CableCrossing007, CableCrossing006);
CableLine006->SetConnectedObjects(CableCrossing007, CableCrossing006);
var CableCrossing008 = CreateObjectAbove(CableCrossing, 939, 360);
CableCrossing008->SetMeshMaterial("CableCarStation_SignStation", 1);
var CableLine007 = CreateObjectAbove(CableLine, 815, 679);
var CableLine007 = CreateObject(CableLine, 815, 679);
CableLine007.LineColors = [-15461326,-15461326];
CableLine007->SetPosition(815, 679);
CableLine007->SetAction("Connect", CableCrossing008, CableCrossing007);
CableLine007->SetConnectedObjects(CableCrossing008, CableCrossing007);
var CableCrossing009 = CreateObjectAbove(CableCrossing, 599, 257);
var CableLine008 = CreateObjectAbove(CableLine, 808, 669);
var CableLine008 = CreateObject(CableLine, 808, 669);
CableLine008.LineColors = [-15461326,-15461326];
CableLine008->SetPosition(808, 669);
CableLine008->SetAction("Connect", CableCrossing009, CableCrossing007);
CableLine008->SetConnectedObjects(CableCrossing009, CableCrossing007);
var CableCrossing010 = CreateObjectAbove(CableCrossing, 519, 259);
var CableLine009 = CreateObjectAbove(CableLine, 599, 484);
var CableLine009 = CreateObjectAbove(CableLine, 599, 722);
CableLine009.LineColors = [-15461326,-15461326];
CableLine009->SetAction("Connect", CableCrossing010, CableCrossing009);
CableLine009->SetConnectedObjects(CableCrossing010, CableCrossing009);
var CableCrossing011 = CreateObjectAbove(CableCrossing, 465, 289);
var CableLine010 = CreateObjectAbove(CableLine, 517, 516);
var CableLine010 = CreateObject(CableLine, 517, 516);
CableLine010.LineColors = [-15461326,-15461326];
CableLine010->SetPosition(517, 516);
CableLine010->SetAction("Connect", CableCrossing011, CableCrossing010);
CableLine010->SetConnectedObjects(CableCrossing011, CableCrossing010);
var CableLine011 = CreateObjectAbove(CableLine, 465, 645);
var CableLine011 = CreateObject(CableLine, 465, 645);
CableLine011.LineColors = [-15461326,-15461326];
CableLine011->SetPosition(465, 645);
CableLine011->SetAction("Connect", CableCrossing003, CableCrossing011);
CableLine011->SetConnectedObjects(CableCrossing003, CableCrossing011);
var CableCrossing012 = CreateObjectAbove(CableCrossing, 744, 589);
var CableLine012 = CreateObjectAbove(CableLine, 652, 1046);
var CableLine012 = CreateObjectAbove(CableLine, 652, 1623);
CableLine012.LineColors = [-15461326,-15461326];
CableLine012->SetAction("Connect", CableCrossing012, CableCrossing004);
CableLine012->SetConnectedObjects(CableCrossing012, CableCrossing004);
var CableCrossing013 = CreateObjectAbove(CableCrossing, 680, 619);
var CableLine013 = CreateObjectAbove(CableLine, 743, 1174);
var CableLine013 = CreateObjectAbove(CableLine, 743, 1772);
CableLine013.LineColors = [-15461326,-15461326];
CableLine013->SetAction("Connect", CableCrossing013, CableCrossing012);
CableLine013->SetConnectedObjects(CableCrossing013, CableCrossing012);
var CableCrossing014 = CreateObjectAbove(CableCrossing, 568, 690);
var CableLine014 = CreateObjectAbove(CableLine, 678, 1278);
var CableLine014 = CreateObjectAbove(CableLine, 678, 1947);
CableLine014.LineColors = [-15461326,-15461326];
CableLine014->SetAction("Connect", CableCrossing014, CableCrossing013);
CableLine014->SetConnectedObjects(CableCrossing014, CableCrossing013);
var CableCrossing015 = CreateObjectAbove(CableCrossing, 456, 711);
var CableLine015 = CreateObjectAbove(CableLine, 570, 1369);
var CableLine015 = CreateObjectAbove(CableLine, 570, 2059);
CableLine015.LineColors = [-15461326,-15461326];
CableLine015->SetAction("Connect", CableCrossing015, CableCrossing014);
CableLine015->SetConnectedObjects(CableCrossing015, CableCrossing014);
var CableCrossing016 = CreateObjectAbove(CableCrossing, 372, 650);
var CableLine016 = CreateObjectAbove(CableLine, 454, 1390);
var CableLine016 = CreateObjectAbove(CableLine, 454, 2080);
CableLine016.LineColors = [-15461326,-15461326];
CableLine016->SetAction("Connect", CableCrossing016, CableCrossing015);
CableLine016->SetConnectedObjects(CableCrossing016, CableCrossing015);
var CableCrossing017 = CreateObjectAbove(CableCrossing, 231, 590);
var CableLine017 = CreateObjectAbove(CableLine, 374, 1266);
var CableLine017 = CreateObjectAbove(CableLine, 374, 1895);
CableLine017.LineColors = [-15461326,-15461326];
CableLine017->SetAction("Connect", CableCrossing017, CableCrossing016);
CableLine017->SetConnectedObjects(CableCrossing017, CableCrossing016);
var CableCrossing018 = CreateObjectAbove(CableCrossing, 131, 528);
CableCrossing018->SetMeshMaterial("CableCarStation_SignStation", 1);
var CableLine018 = CreateObjectAbove(CableLine, 231, 1148);
var CableLine018 = CreateObjectAbove(CableLine, 231, 1717);
CableLine018.LineColors = [-15461326,-15461326];
CableLine018->SetAction("Connect", CableCrossing018, CableCrossing017);
CableLine018->SetConnectedObjects(CableCrossing018, CableCrossing017);
var CableCrossing019 = CreateObjectAbove(CableCrossing, 113, 387, 0);
CableCrossing019->SetMeshMaterial("CableCarStation_SignStation", 1);
CreateObjectAbove(CableHoist, 527, 380);
var CableLine019 = CreateObjectAbove(CableLine, 208, 747);
CableLine019.LineColors = [-15461326,-15461326];
CableLine019->SetAction("Connect", CableCrossing019, CableCrossing003);
CableLine019->SetConnectedObjects(CableCrossing019, CableCrossing003);
CreateObjectAbove(CableLorry, 503, 380);
var ToolsWorkshop001 = CreateObjectAbove(ToolsWorkshop, 76, 388);
CreateObjectAbove(CableLorryReel, 530, 388);
var CableHoist001 = CreateObjectAbove(CableHoist, 560, 384);
CableHoist001->SetComDir(COMD_None);
var CableLorry001 = CreateObjectAbove(CableLorry, 560, 384);
var Wood001 = CableLorry001->CreateContents(Wood);
Wood001->SetPosition(560, 377);
var Wood002 = CableLorry001->CreateContents(Wood);
Wood002->SetPosition(560, 377);
var Wood003 = CableLorry001->CreateContents(Wood);
Wood003->SetPosition(560, 377);
var Metal001 = ToolsWorkshop001->CreateContents(Metal);
Metal001->SetPosition(76, 369);
var CableLorryReel001 = CreateObjectAbove(CableLorryReel, 163, 386);
CableLorryReel001->Unstick(7);
return true;
}

View File

@ -1,6 +1,5 @@
[Head]
Icon=26
Title=CableLorries
Version=8
Difficulty=10
MaxPlayer=8
@ -30,7 +29,6 @@ Vegetation=Mushroom=1
VegetationLevel=100,0,0,100
InEarth=Rock=1;Gold=1;Firestone=1;Loam=1
InEarthLevel=65,0,0,100
Sky=Clouds2
BottomOpen=1
MapWidth=500,0,64,10000
MapHeight=100,0,40,10000
@ -39,7 +37,6 @@ Amplitude=10,10,0,100
Phase=50,50,0,100
Period=10,10,0,100
Random=20,20,0,100
Liquid=Water-Smooth
LiquidLevel=20,30,0,100
Layers=Rock=7;Rock=7;Gold=7;Granite=4;Water=5;Earth-earth=50;Earth-earth_dry=50
SkyScrollMode=2
@ -47,4 +44,4 @@ SkyScrollMode=2
[Weather]
Climate=0,0,0,100
YearSpeed=20,10,0,100
Wind=1,100,-100,100
Wind=1,100,-100,100

View File

@ -167,5 +167,6 @@ private func JoinPlayer(int plr)
var clonk = GetCrew(plr);
clonk->DoEnergy(100000);
clonk->SetPosition(510, 370);
clonk->CreateContents(Hammer);
return;
}

View File

@ -28,6 +28,8 @@
// Contains proplists of format {Product = <objid>, Amount = <int>, Infinite = (optional)<bool>, ProducingPlayer = (optional)<int>}. /Infinite/ == true -> infinite production.
local queue;
// Possibly connected cable station
local cable_station;
protected func Initialize()
{
@ -763,14 +765,23 @@ public func OnProductEjection(object product)
}
/*-- --*/
/*-- Cable Network --*/
public func IsNoCableStationConnected() { return !cable_station; }
public func ConnectCableStation(object station)
{
cable_station = station;
}
/**
Requests the necessary material from the cable network if available.
*/
private func RequestAllMissingComponents(id item_id)
func RequestAllMissingComponents(id item_id)
{
if (!cable_station)
return false;
for (var item in ProductionCosts(item_id))
{
var mat_id = item[0];
@ -782,15 +793,12 @@ private func RequestAllMissingComponents(id item_id)
return true;
}
// Must exist if Library_CableStation is not included by either this
// library or the structure including this library.
public func RequestObject(id item_id, int amount)
{
return _inherited(item_id, amount, ...);
if (cable_station)
cable_station->AddRequest(item_id, amount);
}
/*-- Storage --*/