diff --git a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Items.ocd/CableReel.ocd/CableLine.ocd/Script.c b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Items.ocd/CableReel.ocd/CableLine.ocd/Script.c
index 89bceeb8a..13177d2e6 100644
--- a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Items.ocd/CableReel.ocd/CableLine.ocd/Script.c
+++ b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Items.ocd/CableReel.ocd/CableLine.ocd/Script.c
@@ -1,6 +1,10 @@
-/*-- Cable line --*/
+/**
+ Cable line
-func Initialize()
+ @author Clonkonaut
+*/
+
+public func Initialize()
{
SetAction("Connect");
SetVertexXY(0, GetX(), GetY());
@@ -37,28 +41,44 @@ public func GetConnectedObject(object obj)
return GetActionTarget(0);
}
-/* Breaking */
-func LineBreak(bool no_msg)
+/*-- Breaking --*/
+
+public func OnLineBreak(bool no_msg)
{
Sound("Objects::Connect");
- if (GetActionTarget(0)) GetActionTarget(0)->~CableDeactivation(activations);
- if (GetActionTarget(1)) GetActionTarget(1)->~CableDeactivation(activations);
+ var act1 = GetActionTarget(0);
+ var act2 = GetActionTarget(1);
+
+ SetAction("Idle");
+ if (act1)
+ {
+ act1->~CableDeactivation(activations);
+ act1->~RemoveCableConnection(this);
+ }
+ if (act2)
+ {
+ act2->~CableDeactivation(activations);
+ act2->~RemoveCableConnection(this);
+ }
if (!no_msg)
BreakMessage();
}
-func BreakMessage()
+public func BreakMessage()
{
var line_end = GetActionTarget(0);
- if (line_end->GetID() != CableLorryReel)
+ if (!line_end || line_end->GetID() != CableLorryReel)
line_end = GetActionTarget(1);
- if (line_end->Contained()) line_end = line_end->Contained();
-
- line_end->Message("$TxtLinebroke$");
+ if (line_end && line_end->Contained())
+ line_end = line_end->Contained();
+ if (line_end)
+ line_end->Message("$TxtLinebroke$");
+ return;
}
-/* Activation */
+
+/*-- Activation --*/
local activations = 0;
@@ -67,7 +87,8 @@ local activations = 0;
public func Activation(int count)
{
// Count must be > 0
- if (count < 1) return FatalError("Cable Line: Activation() was called with count < 1.");
+ if (count < 1)
+ return FatalError("Cable Line: Activation() was called with count < 1.");
activations += count;
if (GetActionTarget(0)) GetActionTarget(0)->~CableActivation(count);
if (GetActionTarget(1)) GetActionTarget(1)->~CableActivation(count);
@@ -78,22 +99,29 @@ public func Activation(int count)
public func Deactivation(int count)
{
// Count must be > 0
- if (count < 1) return FatalError("Cable Line: Deactivation() was called with count < 1.");
+ if (count < 1)
+ return FatalError("Cable Line: Deactivation() was called with count < 1.");
activations -= count;
if (GetActionTarget(0)) GetActionTarget(0)->~CableDeactivation(count);
if (GetActionTarget(1)) GetActionTarget(1)->~CableDeactivation(count);
}
-/* Saving */
+
+/*-- Saving --*/
public func SaveScenarioObject(props)
{
- if (!inherited(props, ...)) return false;
+ if (!inherited(props, ...))
+ return false;
SaveScenarioObjectAction(props);
- if (IsCableLine()) props->AddCall("Connection", this, "SetConnectedObjects", GetActionTarget(0), GetActionTarget(1));
+ if (IsCableLine())
+ props->AddCall("Connection", this, "SetConnectedObjects", GetActionTarget(0), GetActionTarget(1));
return true;
}
+
+/*-- Properties --*/
+
local ActMap = {
Connect = {
Prototype = Action,
@@ -103,4 +131,4 @@ local ActMap = {
}
};
-local Name = "$Name$";
\ No newline at end of file
+local Name = "$Name$";
diff --git a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Items.ocd/CableReel.ocd/Script.c b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Items.ocd/CableReel.ocd/Script.c
index e8c0b5b36..dcb9af3e6 100644
--- a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Items.ocd/CableReel.ocd/Script.c
+++ b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Items.ocd/CableReel.ocd/Script.c
@@ -1,4 +1,9 @@
-/*-- Cable reel --*/
+/**
+ Cable reel
+ Connects cable stations.
+
+ @author Clonkonaut
+*/
protected func Hit()
{
@@ -7,6 +12,7 @@ protected func Hit()
public func IsToolProduct() { return true; }
+
/*-- Line connection --*/
protected func ControlUse(object clonk, int x, int y)
@@ -32,7 +38,7 @@ protected func ControlUse(object clonk, int x, int y)
else
{
// Connect existing power line to obj.
- if(line->GetActionTarget(0) == this)
+ if (line->GetActionTarget(0) == this)
line->SetActionTargets(obj, line->GetActionTarget(1));
else if(line->GetActionTarget(1) == this)
line->SetActionTargets(line->GetActionTarget(0), obj);
@@ -63,6 +69,9 @@ private func Find_CableLine(object obj)
return [C4FO_Func, "IsConnectedTo", obj];
}
+
+/*-- Properties --*/
+
local Name = "$Name$";
local Description = "$Description$";
local Collectible = 1;
diff --git a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Libraries.ocd/CableCar.ocd/Script.c b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Libraries.ocd/CableCar.ocd/Script.c
index f63281f44..b94a89c89 100644
--- a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Libraries.ocd/CableCar.ocd/Script.c
+++ b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Libraries.ocd/CableCar.ocd/Script.c
@@ -24,7 +24,8 @@ local lib_ccar_destination;
// Current delivery the car is on, array: [starting station, target station, requested objects, amount]
local lib_ccar_delivery;
-/*--- Overloads ---*/
+
+/*-- Overloads --*/
// Overload these functions as you feel fit
@@ -52,7 +53,8 @@ func OnStart() {}
// failed is true if the movement to a destination was cancelled (usually because the path broke in the meantime)
func OnStop(bool failed) {}
-/*--- Interface ---*/
+
+/*-- Interface --*/
// Sets the speed of the cable car
public func SetCableSpeed(int value)
@@ -97,13 +99,14 @@ public func DoMovement()
var origin = CreateArray(2), ending = CreateArray(2);
lib_ccar_rail->GetActionTarget(start)->GetCablePosition(origin, prec);
lib_ccar_rail->GetActionTarget(end)->GetCablePosition(ending, prec);
- position[0] = origin[0] + (ending[0] - origin[0]) * lib_ccar_progress/lib_ccar_max_progress;
- position[1] = origin[1] + (ending[1] - origin[1]) * lib_ccar_progress/lib_ccar_max_progress;
+ position[0] = origin[0] + (ending[0] - origin[0]) * lib_ccar_progress / lib_ccar_max_progress;
+ position[1] = origin[1] + (ending[1] - origin[1]) * lib_ccar_progress / lib_ccar_max_progress;
GetCableOffset(position, prec);
SetPosition(position[0], position[1], 1, prec);
}
-/*--- Status ---*/
+
+/*-- Status --*/
public func IsCableCar() { return true; }
@@ -113,7 +116,8 @@ public func GetRailTarget() { return lib_ccar_rail; }
public func IsTravelling() { return lib_ccar_destination; }
-/* Interaction */
+
+/*-- Interaction --*/
// Provides an own interaction menu.
public func HasInteractionMenu() { return true; }
@@ -185,7 +189,9 @@ public func GetCableCarMenuEntries(object clonk)
};
PushBack(menu_entries, { symbol = this, extra_data = "NoStation", custom = search });
}
- } else {
+ }
+ else
+ {
// Start the trip
if (!IsTravelling())
{
@@ -227,12 +233,22 @@ public func OnCableCarHover(symbol, extra_data, desc_menu_target, menu_id)
GuiUpdate({ Text = text }, menu_id, 1, desc_menu_target);
}
-/*--- Travelling ---*/
+
+/*-- Travelling --*/
+
+// Called when the network is updated.
+public func OnRailNetworkUpdate()
+{
+ // The car may have been stuck on a request, continue it now.
+ ContinueRequest();
+ return;
+}
// Attach the car onto a crossing
public func EngageRail(object crossing, bool silent)
{
- if (! crossing->~IsCableCrossing()) return false;
+ if (!crossing->~IsCableCrossing())
+ return false;
var position = CreateArray(2);
crossing->GetCablePosition(position);
@@ -244,7 +260,8 @@ public func EngageRail(object crossing, bool silent)
SetComDir(COMD_None);
lib_ccar_rail = crossing;
lib_ccar_direction = nil;
- if (!silent) Sound("Objects::Connect");
+ if (!silent)
+ Sound("Objects::Connect");
UpdateInteractionMenus(this.GetCableCarMenuEntries);
Engaged();
@@ -262,21 +279,23 @@ public func DisengageRail()
UpdateInteractionMenus(this.GetCableCarMenuEntries);
Disengaged();
- if (lib_ccar_rail) lib_ccar_rail->OnCableCarDisengaged(this);
+ if (lib_ccar_rail)
+ lib_ccar_rail->OnCableCarDisengaged(this);
}
// Sets a target point for travelling and starts the movement process
public func SetDestination(dest)
{
- if(GetType(dest) == C4V_Int)
+ if (GetType(dest) == C4V_Int)
{
dest = FindObjects(Find_Func("IsCableCrossing"))[dest];
- if (!dest) return;
+ if (!dest)
+ return;
}
lib_ccar_destination = dest;
- if(lib_ccar_direction == nil)
+ if (lib_ccar_direction == nil)
{
OnStart();
CrossingReached();
@@ -286,24 +305,25 @@ public func SetDestination(dest)
}
// Whenever a crossing is reached it must be queried for the next crossing to go to
-func CrossingReached()
+public func CrossingReached()
{
var target;
- if(lib_ccar_destination != lib_ccar_rail)
+ if (lib_ccar_destination != lib_ccar_rail)
{
- if(target = lib_ccar_rail->GetNextWaypoint(lib_ccar_destination))
+ if (target = lib_ccar_rail->GetNextWaypoint(lib_ccar_destination))
MoveTo(target);
else
DestinationFailed();
}
// Destination reached
- else {
+ else
+ {
DestinationReached();
}
}
// When the current destination is reached
-func DestinationReached()
+public func DestinationReached()
{
lib_ccar_destination = nil;
lib_ccar_direction = nil;
@@ -321,8 +341,11 @@ func DestinationReached()
}
// When the way to the current destination has vanished somehow
-func DestinationFailed()
+public func DestinationFailed()
{
+ if (lib_ccar_rail)
+ lib_ccar_rail->OnCableCarStopped(this);
+
lib_ccar_destination = nil;
lib_ccar_direction = nil;
lib_ccar_progress = 0;
@@ -331,8 +354,14 @@ func DestinationFailed()
OnStop(true);
}
+public func Destruction()
+{
+ if (lib_ccar_rail)
+ lib_ccar_rail->OnCableCarDestruction(this);
+}
+
// Setup movement process
-func MoveToIndex(int dest)
+public func MoveToIndex(int dest)
{
var dest_obj = FindObjects(Find_Func("IsCableCrossing"))[dest];
if (dest_obj) return MoveTo(dest_obj);
@@ -341,19 +370,19 @@ func MoveToIndex(int dest)
public func MoveTo(object dest)
{
var rail = 0;
- for(var test_rail in FindObjects(Find_Func("IsConnectedTo", lib_ccar_rail)))
+ for (var test_rail in FindObjects(Find_Func("IsConnectedTo", lib_ccar_rail)))
{
- if(test_rail->IsConnectedTo(dest))
+ if (test_rail->IsConnectedTo(dest))
{
rail = test_rail;
break;
}
}
- if(!rail)
+ if (!rail)
return DestinationFailed(); // Shouldn't happen
// Target the first or second action target?
- if(rail->GetActionTarget(0) == dest)
+ if (rail->GetActionTarget(0) == dest)
lib_ccar_direction = 0;
else
lib_ccar_direction = 1;
@@ -366,14 +395,14 @@ public func MoveTo(object dest)
lib_ccar_rail = rail;
}
-/* Destination selection */
+
+/*-- Destination selection --*/
public func OpenDestinationSelection(object clonk)
{
if (!clonk) return;
if (!GetRailTarget()) return;
- var plr = clonk->GetOwner();
// Close interaction menu
if (clonk->GetMenu())
if (!clonk->TryCancelMenu())
@@ -382,6 +411,7 @@ public func OpenDestinationSelection(object clonk)
GUI_DestinationSelectionMenu->CreateFor(clonk, this, GetRailTarget());
}
+
/*-- Delivery --*/
public func AddRequest(proplist requested, int amount, proplist target, proplist source)
@@ -390,9 +420,17 @@ public func AddRequest(proplist requested, int amount, proplist target, proplist
SetDestination(target);
}
-func FinishedRequest(object station)
+public func ContinueRequest()
+{
+ if (!lib_ccar_delivery)
+ return;
+ var target = lib_ccar_delivery[1];
+ SetDestination(target);
+}
+
+public func FinishedRequest(object station)
{
if (station && lib_ccar_delivery)
station->RequestArrived(this, lib_ccar_delivery[2], lib_ccar_delivery[3]);
lib_ccar_delivery = nil;
-}
\ No newline at end of file
+}
diff --git a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Libraries.ocd/CableStation.ocd/Script.c b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Libraries.ocd/CableStation.ocd/Script.c
index ec377bf9b..cb2324886 100644
--- a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Libraries.ocd/CableStation.ocd/Script.c
+++ b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Libraries.ocd/CableStation.ocd/Script.c
@@ -26,6 +26,9 @@ public func CableDeactivation(int count) { }
// Called by arriving cable cars if this station is the final stop
public func OnCableCarArrival(object car) { }
+// Called by cable cars if it stopped at this station (usually because of a problem)
+public func OnCableCarStopped(object car) { }
+
// Called by departing cable cars if it just starts a new journey
public func OnCableCarDeparture(object car) { }
@@ -35,6 +38,9 @@ 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 by a cable car that has been destroyed at this station
+public func OnCableCarDestruction(object car) { }
+
// Called when a cable car with a requested delivery arrives
public func OnCableCarDelivery(object car, id requested, int amount) { }
@@ -56,26 +62,10 @@ public func Construction()
return _inherited(...);
}
-/* Removes this crossing from the network
- It first clears every waypoint from the network and then renews the whole information.
- Optimisation welcome!
-*/
public func Destruction()
{
- for (var connection in FindObjects(Find_Func("IsConnectedTo", this)))
- {
- if (!connection->~IsCableLine()) continue;
- var other_crossing = connection->~GetConnectedObject(this);
- if (!other_crossing || !other_crossing->~IsCableCrossing()) continue;
- other_crossing->ClearConnections(this);
- }
- for (var connection in FindObjects(Find_Func("IsConnectedTo", this)))
- {
- if (!connection->~IsCableLine()) continue;
- var other_crossing = connection->~GetConnectedObject(this);
- if (!other_crossing || !other_crossing->~IsCableCrossing()) continue;
- other_crossing->RenewConnections(this);
- }
+ // The connection with other stations is broken via the cable and the network updating is handled there.
+ // So there is updating to be performed here.
return _inherited(...);
}
@@ -106,7 +96,8 @@ public func SetCableStation(bool station)
// Returns the cable hookup position for proper positioning of a car along the line.
public func GetCablePosition(array coordinates, int prec)
{
- if (!prec) prec = 1;
+ if (!prec)
+ prec = 1;
coordinates[0] = GetX(prec);
coordinates[1] = GetY(prec);
if (this.LineAttach)
@@ -153,19 +144,23 @@ public func GetDestinationList(object middle)
AddCableConnection(object cable)
AddCableDestinations(array new_list, object crossing)
AddCableDestination(object new_destination, object crossing, int distance_add)
- ClearConnections(object crossing)
- RenewConnections(object crossing)
+ ClearConnections()
+ RenewConnections()
*/
/** Returns the destination array so it can be used by other crossings.
*/
public func GetDestinations()
{
- return destination_list[:];
+ // This is a nested array, so ensure a proper deep copy is made.
+ var deep_copy = [];
+ for (var dest in destination_list)
+ PushBack(deep_copy, dest[:]);
+ return deep_copy;
}
-// Stores the next crossing (waypoint) to take when advancing to a certain final point
-// Scheme (2D array): [Desired final point, Next waypoint to take, Distance (not airline!) until final point]
+// Stores the next crossing (waypoint) to take when advancing to a certain final point. The list may not contain the crossing itself.
+// Scheme (2D array): [Desired final point, Next waypoint to take, Distance (not airline!) until final point].
local destination_list;
// Constants for easier script reading
@@ -181,16 +176,25 @@ local const_distance = 2;
public func AddCableConnection(object cable)
{
// Failsafe
- if (!cable || ! cable->~IsCableLine())
+ if (!cable || !cable->~IsCableLine())
return false;
// Line setup finished?
var other_crossing = cable->~GetConnectedObject(this);
- if (! other_crossing->~IsCableCrossing())
+ if (!other_crossing || !other_crossing->~IsCableCrossing())
return false;
// Acquire destinations of the other crossing, all these are now in reach
AddCableDestinations(other_crossing->GetDestinations(), other_crossing);
// Send own destinations, now in reach for the other one
- other_crossing->AddCableDestinations(destination_list[:], this);
+ other_crossing->AddCableDestinations(GetDestinations(), this);
+ // Awesome, more power to the network!
+ DestinationsUpdated();
+ return true;
+}
+
+public func RemoveCableConnection(object cable)
+{
+ // It is easiest to just update all connections.
+ UpdateConnections();
// Awesome, more power to the network!
DestinationsUpdated();
return true;
@@ -200,28 +204,28 @@ public func AddCableConnection(object cable)
* @param new_list The new destination list, formated like a crossing's normal destination list
* @param crossing The crossing where this list comes from
*/
-public func AddCableDestinations(array new_list, object crossing)
+public func AddCableDestinations(array new_list, object crossing, bool has_reversed)
{
- // Append crossing to the list
- if (crossing)
- {
- new_list[GetLength(new_list)] = [crossing, crossing];
- // This value is to be added to every distance
- var distance_add = ObjectDistance(crossing);
- }
- else
- return false; // Does not compute
+ if (!crossing)
+ return false;
+ // Append crossing itself to the list with zero distance.
+ new_list[GetLength(new_list)] = [crossing, crossing, 0];
+ // This value is to be added to every distance
+ var distance_add = ObjectDistance(crossing);
// Check every new destination
for (var list_item in new_list)
{
- if (!list_item) continue;
- // Destination is this
- if (list_item[const_finaldestination] == this) continue;
- // Check whether the destination is already in reach
+ if (!list_item)
+ continue;
+ // Destination may not be this crossing.
+ if (list_item[const_finaldestination] == this)
+ continue;
+ // Check whether the destination is already in already in the list.
var handled = false;
- for (var i = 0, destination = false; i < GetLength(destination_list); i++)
+ for (var i = 0, destination = nil; i < GetLength(destination_list); i++)
{
- if (!destination_list[i]) continue;
+ if (!destination_list[i])
+ continue;
destination = destination_list[i];
if (destination[const_finaldestination] == list_item[const_finaldestination])
{
@@ -231,18 +235,55 @@ public func AddCableDestinations(array new_list, object crossing)
{
// It is shorter, replace, route through crossing
destination_list[i] = [list_item[const_finaldestination], crossing, list_item[const_distance] + distance_add];
- // Inform the destination
+ // Inform the destination.
list_item[const_finaldestination]->UpdateCableDestination(this, crossing, distance_add);
}
}
}
- // Destination is replaced or to be dismissed (because the new path would be longer), do nothing
- if (handled) continue;
- // Destination is a new one, add to the list
- destination_list[GetLength(destination_list)] = [list_item[const_finaldestination], crossing, list_item[const_distance] + distance_add];
- // Add me to the new destination (the way to me is the same than to crossing)
- if (list_item[const_finaldestination] != crossing)
- list_item[const_finaldestination]->AddCableDestination(this, crossing, distance_add);
+
+ // Destination is replaced or to be dismissed (because the new path would be longer), do nothing.
+ if (handled)
+ continue;
+
+ // Destination is a new one, add to the list.
+ AddCableDestination(list_item[const_finaldestination], crossing, list_item[const_distance] + distance_add);
+ // Add me to the new destination (the way to me is the same than to crossing).
+ if (list_item[const_finaldestination] != crossing && !has_reversed)
+ {
+ // This new crossing may have a bunch of other connections that need to be explored and potentially added.
+ // The new crossing is connected to this crossing via the crossing specified as the parameter to this function.
+ // So for the new destinations we want to add, we need to add the distance to the crossing.
+ var add_destinations = list_item[const_finaldestination]->GetDestinations();
+ var add_dest_distance = 0;
+ for (var dest in crossing->GetDestinations())
+ if (dest[const_finaldestination] == list_item[const_finaldestination])
+ add_dest_distance = dest[const_distance];
+ for (var dest in add_destinations)
+ dest[const_distance] += add_dest_distance;
+ this->AddCableDestinations(add_destinations, crossing, has_reversed);
+
+ // However, this crossing and its destinations must also be added in reverse to the new crossing found.
+ var reverse_destinations = this->GetDestinations();
+ PushBack(reverse_destinations, [this, crossing, 0]);
+ var reverse_crossing = nil;
+ for (var dest in list_item[const_finaldestination]->GetDestinations())
+ if (dest[const_finaldestination] == crossing)
+ reverse_crossing = dest[const_nextwaypoint];
+ if (reverse_crossing == nil)
+ return FatalError("AddCableDestinations(): reverse_crossing not found.");
+ var add_reverse_distance = distance_add;
+ if (reverse_crossing != crossing)
+ {
+ for (var dest in reverse_crossing->GetDestinations())
+ if (dest[const_finaldestination] == crossing)
+ add_reverse_distance += dest[const_distance];
+ if (add_reverse_distance == distance_add)
+ return FatalError("AddCableDestinations(): reverse_distance not correct.");
+ }
+ for (var dest in reverse_destinations)
+ dest[const_distance] += add_reverse_distance;
+ list_item[const_finaldestination]->AddCableDestinations(reverse_destinations, reverse_crossing, true);
+ }
}
DestinationsUpdated();
return true;
@@ -253,28 +294,19 @@ public func AddCableDestinations(array new_list, object crossing)
* @param crossing The crossing which links to the new destination
* @param distance_add The distance between crossing and new_destination
*/
-public func AddCableDestination(object new_destination, object crossing, int distance_add)
+public func AddCableDestination(object new_destination, object crossing, int distance)
{
- // Failsafe
- if (!new_destination || !crossing) return false;
- if (new_destination == this) return false;
- // Find the entry of crossing to get the next waypoint and the distance
- var crossing_item;
- for (var list_item in destination_list)
- {
- if (!list_item) continue;
- if (list_item[const_finaldestination] == crossing)
- {
- crossing_item = list_item;
- break;
- }
- }
- // Failsafe
- if (!crossing_item) return false;
- // Save the new destination
- destination_list[GetLength(destination_list)] = [new_destination, crossing_item[const_nextwaypoint], crossing_item[const_distance] + distance_add];
+ // Failsafes.
+ if (!new_destination || !crossing)
+ return;
+ if (new_destination == this)
+ return;
+ if (!IsDirectlyConnectToCrossing(crossing))
+ return FatalError(Format("destination to %v for %v is not connected to crossing link %v.", new_destination, this, crossing));
+ // Add to destination list.
+ PushBack(destination_list, [new_destination, crossing, distance]);
DestinationsUpdated();
- return true;
+ return;
}
/** Updates the path to \a known_destination via \a crossing (e.g. because the path is shorter through \a crossing)
@@ -291,7 +323,8 @@ public func UpdateCableDestination(object known_destination, object crossing, in
var crossing_item, destination_item, i = 0;
for (var list_item in destination_list)
{
- if (!list_item) continue;
+ if (!list_item)
+ continue;
if (list_item[const_finaldestination] == crossing)
crossing_item = list_item;
if (list_item[const_finaldestination] == known_destination)
@@ -299,7 +332,8 @@ public func UpdateCableDestination(object known_destination, object crossing, in
i++;
}
// Failsafe
- if (!crossing_item || !destination_item) return false;
+ if (!crossing_item || !destination_item)
+ return false;
// Save the updated path
destination_list[destination_item][const_nextwaypoint] = crossing_item[const_nextwaypoint];
destination_list[destination_item][const_distance] = crossing_item[const_distance] + distance_add;
@@ -309,42 +343,68 @@ public func UpdateCableDestination(object known_destination, object crossing, in
local clearing;
-/* Called automatically by Destruction, see description there
-* @param crossing The calling crossing
-*/
-public func ClearConnections(object crossing)
+// Updates the network for this crossing, this is called when a cable to this crossing has changed.
+// It first clears every waypoint from the network and then renews the whole information.
+public func UpdateConnections()
{
- if (clearing) return;
+ // Clear this crossing and then other connected crossings.
+ ClearConnections();
+ RenewConnections();
+ return;
+}
+
+// Called automatically by UpdateConnections, see description there.
+public func ClearConnections()
+{
+ if (clearing)
+ return;
clearing = true;
destination_list = [];
for (var connection in FindObjects(Find_Func("IsConnectedTo", this)))
{
- if (!connection->~IsCableLine()) continue;
+ if (!connection->~IsCableLine())
+ continue;
var other_crossing = connection->~GetConnectedObject(this);
- if (!other_crossing || !other_crossing->~IsCableCrossing()) continue;
+ if (!other_crossing || !other_crossing->~IsCableCrossing())
+ continue;
other_crossing->ClearConnections();
}
}
-/* Called automatically by Destruction, see description there
-* @param crossing The calling crossing
-*/
-public func RenewConnections(object crossing)
+// Called automatically by UpdateConnections, see description there.
+public func RenewConnections()
{
- if (!clearing) return;
+ if (!clearing)
+ return;
clearing = false;
- for(var connection in FindObjects(Find_Func("IsConnectedTo", this)))
+ for (var connection in FindObjects(Find_Func("IsConnectedTo", this)))
{
- if (!connection->~IsCableLine()) continue;
+ if (!connection->~IsCableLine())
+ continue;
var other_crossing = connection->~GetConnectedObject(this);
- if (!other_crossing || !other_crossing->~IsCableCrossing()) continue;
- if (other_crossing == crossing) continue;
- destination_list[GetLength(destination_list)] = [other_crossing, other_crossing, ObjectDistance(other_crossing)];
+ if (!other_crossing || !other_crossing->~IsCableCrossing())
+ continue;
+ PushBack(destination_list, [other_crossing, other_crossing, ObjectDistance(other_crossing)]);
AddCableDestinations(other_crossing->GetDestinations(), other_crossing);
+ other_crossing->RenewConnections();
}
}
-/*--- Pathfinding ---*/
+// Returns whether there is a direct conenctions between this and the other crossing.
+public func IsDirectlyConnectToCrossing(object other_crossing)
+{
+ for (var connection in FindObjects(Find_Func("IsConnectedTo", this)))
+ {
+ if (!connection->~IsCableLine())
+ continue;
+ if (other_crossing == connection->~GetConnectedObject(this))
+ return true;
+ }
+ return false;
+}
+
+
+/*-- Pathfinding --*/
/* Functions:
GetNextWaypoint(object end)
@@ -356,10 +416,12 @@ public func RenewConnections(object crossing)
*/
public func GetNextWaypoint(object end)
{
- if (!destination_list) return nil;
+ if (!destination_list)
+ return nil;
for (var item in destination_list)
{
- if (!item) continue;
+ if (!item)
+ continue;
if (item[const_finaldestination] == end)
return item[const_nextwaypoint];
}
@@ -372,16 +434,19 @@ public func GetNextWaypoint(object end)
*/
public func GetLengthToTarget(object end)
{
- if (!destination_list) return nil;
+ if (!destination_list)
+ return nil;
for (var item in destination_list)
{
- if (!item) continue;
+ if (!item)
+ continue;
if (item[const_finaldestination] == end)
return item[const_distance];
}
return nil;
}
+
/*-- Auto production --*/
local request_queue;
@@ -410,12 +475,11 @@ public func AddRequest(proplist requested_id, int amount)
// Great. Start working immediately
PushBack(request_queue, [requested_id, amount]);
car->AddRequest(requested_id, amount, this, source);
-
return true;
}
// Check all connected stations for available objects
-func CheckAvailability(proplist requested, int amount)
+public func CheckAvailability(proplist requested, int amount)
{
var nearest_station;
var length_to;
@@ -494,4 +558,4 @@ public func RemoveRequest(id requested, int amount)
return false;
RemoveArrayIndex(request_queue, i, true);
return true;
-}
\ No newline at end of file
+}
diff --git a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/Script.c b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/Script.c
index 8dd8937a1..091caf957 100644
--- a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/Script.c
+++ b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/Script.c
@@ -1,11 +1,11 @@
-/*--
+/**
Cable Crossing
The standard crossing for the cable network.
The crossing will automatically be a station if it is at the end of the cable line (i.e. only one cable connected).
But the crossing can also manually be set to function as a station.
- Author: Clonkonaut
---*/
+ @author Clonkonaut
+*/
#include Library_CableStation
@@ -32,7 +32,8 @@ func Initialize()
// Prevents the automatic change of the station status when manually set to station mode
local manual_setting = false;
-/* Library functions: Cable Station */
+
+/*-- Library functions: Cable Station --*/
public func DestinationsUpdated()
{
@@ -44,6 +45,11 @@ public func DestinationsUpdated()
else
SetCableStation(false);
CheckStationStatus();
+
+ // Inform all cars at station about the update.
+ for (var car in arrived_cars)
+ if (car)
+ car->~OnRailNetworkUpdate();
}
public func IsAvailable(proplist requested, int amount)
@@ -107,7 +113,8 @@ public func OnCableCarDelivery(object car, id requested, int amount)
}
}
-/* Construction */
+
+/*-- Construction --*/
public func IsHammerBuildable() { return true; }
@@ -124,7 +131,7 @@ public func ConstructionCombineOffset(proplist other)
return;
// Make sure the station preview is on the same ground level than the other building
- var ret = [0,0];
+ var ret = [0, 0];
ret[1] = other->GetObjHeight()/2 - this->GetDefHeight()/2;
return ret;
}
@@ -238,7 +245,9 @@ public func ToggleDropOff(bool silent)
if (!IsCableStation())
ToggleStation(true);
setting_dropoff = true;
- } else {
+ }
+ else
+ {
setting_dropoff = false;
}
if (!silent)
@@ -246,7 +255,8 @@ public func ToggleDropOff(bool silent)
CheckStationStatus();
}
-/* Cable Car Management */
+
+/*-- Cable Car Management --*/
public func OnCableCarArrival(object car)
{
@@ -259,6 +269,11 @@ public func OnCableCarArrival(object car)
PushBack(arrived_cars, car);
}
+public func OnCableCarStopped(object car)
+{
+ PushBack(arrived_cars, car);
+}
+
public func OnCableCarDeparture(object car)
{
RemoveArrayValue(arrived_cars, car, true);
@@ -274,19 +289,23 @@ public func OnCableCarDisengaged(object car)
RemoveArrayValue(arrived_cars, car, true);
}
-/* Visuals */
+public func OnCableCarDestruction(object car)
+{
+ RemoveArrayValue(arrived_cars, car, true);
+}
-func CheckStationStatus()
+
+/*-- Visuals --*/
+
+public func CheckStationStatus()
{
if (IsCableStation())
{
// In order of priority
if (setting_dropoff)
- {
SetMeshMaterial("CableCarStation_SignDropOff", 1);
- } else {
+ else
SetMeshMaterial("CableCarStation_SignStation", 1);
- }
}
else
SetMeshMaterial("CableCarStation_Sign", 1);
@@ -294,14 +313,14 @@ func CheckStationStatus()
local activations = 0;
-func CableActivation(int count)
+public func CableActivation(int count)
{
if (activations <= 0)
SetAnimationPosition(turn_anim, Anim_Linear(GetAnimationPosition(turn_anim), 0, GetAnimationLength("Engine"), 175, ANIM_Loop));
activations += count;
}
-func CableDeactivation(int count)
+public func CableDeactivation(int count)
{
activations -= count;
if (activations <= 0)
@@ -310,9 +329,10 @@ func CableDeactivation(int count)
public func NoConstructionFlip() { return true; }
-/* Saving */
-func SaveScenarioObject(props)
+/*-- Saving --*/
+
+public func SaveScenarioObject(props)
{
if (!inherited(props, ...)) return false;
if (IsCableStation() && manual_setting)
@@ -327,7 +347,8 @@ func SaveScenarioObject(props)
public func SetManual() { manual_setting = true; return true; }
-/* Properties */
+
+/*-- Properties --*/
local Name = "$Name$";
local BlastIncinerate = 50;
diff --git a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/StringTblDE.txt b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/StringTblDE.txt
index 57ce696f6..b68eab1c6 100644
--- a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/StringTblDE.txt
+++ b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/StringTblDE.txt
@@ -3,5 +3,7 @@ Name=Seilbahnkreuzung
StationSettings=Seilbahneinstellungen
TooltipToggleStation=Bahnhofs-Status umstellen.
+TooltipToggleDropOff=Toggle item dropping status
-DescToggleStation=Diese Kreuzung von Hand zu einem Bahnhof oder wieder zu einer Kreuzung umschalten. Nur Bahnhöfe sind als Ziel wählbar und nur am Bahnhöfen können Fahrzeuge aufgesetzt werden.
\ No newline at end of file
+DescToggleStation=Diese Kreuzung von Hand zu einem Bahnhof oder wieder zu einer Kreuzung umschalten. Nur Bahnhöfe sind als Ziel wählbar und nur am Bahnhöfen können Fahrzeuge aufgesetzt werden.
+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.
\ No newline at end of file
diff --git a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Hoist.ocd/Script.c b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Hoist.ocd/Script.c
index 425fdb911..4fba57361 100644
--- a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Hoist.ocd/Script.c
+++ b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Hoist.ocd/Script.c
@@ -1,20 +1,26 @@
-/*-- Cable Hoist --*/
+/**
+ Cable Hoist
+
+ @author Clonkonaut
+*/
#include Library_CableCar
local pickup;
-/* Creation */
-func Construction()
+/*-- Creation --*/
+
+public func Construction()
{
- SetProperty("MeshTransformation",Trans_Rotate(13,0,1,0));
+ this.MeshTransformation = Trans_Rotate(13, 0, 1, 0);
SetCableSpeed(1);
}
-/* Engine Callbacks */
-func Damage(int change, int cause)
+/*-- Engine Callbacks --*/
+
+public func Damage(int change, int cause)
{
if (cause == FX_Call_DmgBlast)
{
@@ -26,25 +32,28 @@ func Damage(int change, int cause)
}
}
-/* Status */
+
+/*-- Status --*/
public func IsToolProduct() { return true; }
-/* Cable Car Library */
-func GetCableOffset(array position, int prec)
+/*-- Cable Car Library --*/
+
+public func GetCableOffset(array position, int prec)
{
- if (!prec) prec = 1;
+ if (!prec)
+ prec = 1;
position[1] += 5 * prec;
}
-func Engaged()
+public func Engaged()
{
this.Touchable = 0;
SetAction("OnRail");
}
-func Disengaged()
+public func Disengaged()
{
this.Touchable = 1;
SetAction("Idle");
@@ -52,9 +61,10 @@ func Disengaged()
DropVehicle();
}
-func GetCableCarExtraMenuEntries(array menu_entries, proplist custom_entry, object clonk)
+public func GetCableCarExtraMenuEntries(array menu_entries, proplist custom_entry, object clonk)
{
- if (IsTravelling()) return;
+ if (IsTravelling())
+ return;
if (!pickup && GetRailTarget())
{
@@ -103,7 +113,8 @@ public func OnCableCarHover(symbol, extra_data, desc_menu_target, menu_id)
return _inherited(symbol, extra_data, desc_menu_target, menu_id, ...);
}
-/* Picking up vehicles */
+
+/*-- Picking up vehicles --*/
public func PickupVehicle(object vehicle)
{
@@ -155,9 +166,10 @@ local FxCableHoistPickup = new Effect
}
};
-/* Actions */
-func OnRail()
+/*-- Actions --*/
+
+public func OnRail()
{
DoMovement();
}
@@ -180,7 +192,8 @@ local ActMap = {
},
};
-/* Callbacks */
+
+/*-- Callbacks --*/
public func GetAttachedVehicle()
{
@@ -230,15 +243,15 @@ public func OverridePriority(proplist requested, int amount, proplist requesting
// 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)
+/*-- Definition --*/
+
+public func Definition(def)
{
- SetProperty("PictureTransformation",Trans_Mul(Trans_Rotate(-25,1,0,0),Trans_Rotate(40,0,1,0)),def);
+ def.PictureTransformation = Trans_Mul(Trans_Rotate(-25, 1, 0, 0), Trans_Rotate(40, 0, 1, 0));
}
local Name = "$Name$";
diff --git a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Lorry.ocd/Script.c b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Lorry.ocd/Script.c
index d982819d3..7c607d6cc 100644
--- a/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Lorry.ocd/Script.c
+++ b/planet/Experimental.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Lorry.ocd/Script.c
@@ -12,23 +12,23 @@ local empty_anim;
/*-- Engine Callbacks --*/
-func Construction()
+public func Construction()
{
SetProperty("MeshTransformation", Trans_Rotate(13, 0, 1, 0));
}
-func Initialize()
+public func Initialize()
{
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));
}
-func Hit3()
+public func Hit3()
{
Sound("Hits::Materials::Metal::DullMetalHit?");
}
-func RejectCollect(id object_id, object obj)
+public func RejectCollect(id object_id, object obj)
{
// Collection maybe blocked if this object was just dumped.
if (!obj->Contained() && GetEffect("BlockCollectionByLorry", obj))
@@ -59,7 +59,7 @@ func RejectCollect(id object_id, object obj)
}
// Automatic unloading in buildings.
-func Entrance(object container)
+public func Entrance(object container)
{
// Only in buildings
if (container->GetCategory() & (C4D_StaticBack | C4D_Structure))
@@ -69,19 +69,19 @@ func Entrance(object container)
container->GrabContents(this);
}
-func ContactLeft()
+public func ContactLeft()
{
if (Stuck() && !Random(5))
SetRDir(RandomX(-7, +7));
}
-func ContactRight()
+public func ContactRight()
{
if (Stuck() && !Random(5))
SetRDir(RandomX(-7, +7));
}
-func Damage(int change, int cause, int by_player)
+public func Damage(int change, int cause, int by_player)
{
// Only explode the lorry on blast damage.
if (cause != FX_Call_DmgBlast)
@@ -144,7 +144,7 @@ public func DropContents(proplist station)
ScheduleCall(this, "Empty", 35);
}
-func Empty()
+public func Empty()
{
// Exit everything at once (as opposed to manual dumping below)
while (Contents())
diff --git a/planet/Experimental.ocf/CableLorrys.ocs/Objects.c b/planet/Experimental.ocf/CableLorrys.ocs/Objects.c
index e74ad78c0..00eece8d2 100644
--- a/planet/Experimental.ocf/CableLorrys.ocs/Objects.c
+++ b/planet/Experimental.ocf/CableLorrys.ocs/Objects.c
@@ -144,6 +144,7 @@ func InitializeObjects()
CableLine019->SetConnectedObjects(CableCrossing019, CableCrossing003);
var ToolsWorkshop001 = CreateObjectAbove(ToolsWorkshop, 76, 388);
+ CableCrossing019->CombineWith(ToolsWorkshop001);
var CableHoist001 = CreateObjectAbove(CableHoist, 560, 384);
CableHoist001->SetComDir(COMD_None);
diff --git a/planet/Experimental.ocf/CableLorrys.ocs/Script.c b/planet/Experimental.ocf/CableLorrys.ocs/Script.c
index e38c140dc..5e9784005 100644
--- a/planet/Experimental.ocf/CableLorrys.ocs/Script.c
+++ b/planet/Experimental.ocf/CableLorrys.ocs/Script.c
@@ -150,6 +150,10 @@ protected func InitializePlayer(int plr)
// No FOW here.
//SetFoW(false, plr);
JoinPlayer(plr);
+ // Give all knowledge.
+ var index = 0, def;
+ while (def = GetDefinition(index++))
+ SetPlrKnowledge(plr, def);
return;
}
diff --git a/planet/Tests.ocf/CableCars.ocs/Script.c b/planet/Tests.ocf/CableCars.ocs/Script.c
index cb9a03c3d..b472c6ead 100644
--- a/planet/Tests.ocf/CableCars.ocs/Script.c
+++ b/planet/Tests.ocf/CableCars.ocs/Script.c
@@ -56,10 +56,10 @@ protected func InitializePlayer(int plr)
SetPlrKnowledge(plr, def);
// Add test control effect.
- var effect = AddEffect("IntTestControl", nil, 100, 2);
- effect.testnr = 1;
- effect.launched = false;
- effect.plr = plr;
+ var fx = AddEffect("IntTestControl", nil, 100, 2);
+ fx.testnr = 7;
+ fx.launched = false;
+ fx.plr = plr;
return;
}
@@ -191,7 +191,7 @@ global func Test1_OnStart(int plr)
workshop->AddToQueue(Shovel, 2);
// Log what the test is about.
- Log("A workshop needs material to produce 2 shovels, lorry in system has materials.");
+ Log("A workshop needs material to produce shovels, lorry in system has materials.");
return true;
}
@@ -288,11 +288,13 @@ global func Test3_OnStart(int plr)
var workshop = CreateObjectAbove(ToolsWorkshop, 40, 160, plr);
crossing1->CombineWith(workshop);
- workshop->AddToQueue(Shovel, 2);
+ workshop->AddToQueue(Shovel, 1);
ScheduleCall(line_to_break, "OnLineBreak", 36, 0, true);
ScheduleCall(line_to_break, "RemoveObject", 37, 0, true);
+ ScheduleCall(nil, "PrintCableCarNetwork", 38, 0);
ScheduleCall(nil, "CreateCableCrossingsConnection", 240, 0, crossing2, crossing3);
+ ScheduleCall(nil, "PrintCableCarNetwork", 241, 0);
// Log what the test is about.
Log("Check if a delivery is continued when a cable breaks and is repaired.");
@@ -301,7 +303,7 @@ global func Test3_OnStart(int plr)
global func Test3_Completed()
{
- if (ObjectCount(Find_ID(Shovel)) >= 2)
+ if (ObjectCount(Find_ID(Shovel)) >= 1)
return true;
return false;
}
@@ -319,26 +321,30 @@ global func Test4_OnStart(int plr)
var crossing1 = CreateObjectAbove(CableCrossing, 70, 160, plr);
var crossing2 = CreateObjectAbove(CableCrossing, 216, 64, plr);
- var crossing3 = CreateObjectAbove(CableCrossing, 272, 64, plr);
- var crossing4 = CreateObjectAbove(CableCrossing, 450, 104, plr);
+ var crossing3 = CreateObjectAbove(CableCrossing, 244, 64, plr);
+ var crossing4 = CreateObjectAbove(CableCrossing, 272, 64, plr);
+ var crossing5 = CreateObjectAbove(CableCrossing, 450, 104, plr);
CreateCableCrossingsConnection(crossing1, crossing2);
CreateCableCrossingsConnection(crossing2, crossing3);
CreateCableCrossingsConnection(crossing3, crossing4);
+ CreateCableCrossingsConnection(crossing4, crossing5);
- var hoist = crossing4->CreateObject(CableHoist);
- hoist->EngageRail(crossing4);
- var lorry = crossing4->CreateObject(CableLorry);
+ var hoist = crossing5->CreateObject(CableHoist);
+ hoist->EngageRail(crossing5);
+ var lorry = crossing5->CreateObject(CableLorry);
hoist->PickupVehicle(lorry);
lorry->CreateContents(Metal, 2);
lorry->CreateContents(Wood, 2);
var workshop = CreateObjectAbove(ToolsWorkshop, 40, 160, plr);
crossing1->CombineWith(workshop);
- workshop->AddToQueue(Shovel, 2);
+ workshop->AddToQueue(Shovel, 1);
- ScheduleCall(crossing2, "RemoveObject", 36, 0, true);
- ScheduleCall(nil, "CreateCableCrossingsConnection", 240, 0, crossing1, crossing3);
+ ScheduleCall(crossing3, "RemoveObject", 36, 0, true);
+ ScheduleCall(nil, "PrintCableCarNetwork", 37, 0);
+ ScheduleCall(nil, "CreateCableCrossingsConnection", 240, 0, crossing2, crossing4);
+ ScheduleCall(nil, "PrintCableCarNetwork", 241, 0);
// Log what the test is about.
Log("Check if a delivery is continued when a station is destroyed.");
@@ -347,7 +353,7 @@ global func Test4_OnStart(int plr)
global func Test4_Completed()
{
- if (ObjectCount(Find_ID(Shovel)) >= 2)
+ if (ObjectCount(Find_ID(Shovel)) >= 1)
return true;
return false;
}
@@ -358,7 +364,6 @@ global func Test4_OnFinished()
return;
}
-
global func Test5_OnStart(int plr)
{
SetWindFixed(50);
@@ -464,7 +469,7 @@ global func Test6_OnStart(int plr)
var drain = CreateObjectAbove(Pipe, 80, 300, plr);
drain->ConnectPipeTo(pump, PIPE_STATE_Drain);
- Schedule(nil, "CreateObject(Dynamite, 482, 266)->Fuse()", 180, 10**6);
+ Schedule(nil, "CreateObject(Rock, 480, 274)", 36, 10**6);
// Log what the test is about.
Log("Test automated concrete production line.");
@@ -539,6 +544,141 @@ global func Test7_OnFinished()
return;
}
+global func Test8_OnStart(int plr)
+{
+ ClearFreeRect(0, 0, LandscapeWidth(), LandscapeHeight());
+
+ var nr_crossings = RandomX(6, 12);
+ var connect_chance = 20; // In percent.
+ var start_time = GetTime();
+ var crossings = [];
+ for (var cnt = 0; cnt < nr_crossings; cnt++)
+ PushBack(crossings, CreateObjectAbove(CableCrossing, RandomX(10, LandscapeWidth() - 10), RandomX(20, LandscapeHeight() - 20), plr));
+
+ var nr_connections = 0;
+ for (var c1 in crossings)
+ {
+ for (var c2 in crossings)
+ {
+ if (c1 != c2 && Random(100) < connect_chance)
+ {
+ CreateCableCrossingsConnection(c1, c2);
+ nr_connections++;
+ }
+ }
+ }
+
+ // Log what the test is about.
+ Log("Test a random network for symmetric distance measures.");
+ var time = GetTime() - start_time;
+ Log("It took %d ms to create %d stations with %d connections.", time, nr_crossings, nr_connections);
+ return true;
+}
+
+global func Test8_Completed()
+{
+ if (IsSymmetricCableCarNetwork())
+ return true;
+ return false;
+}
+
+global func Test8_OnFinished()
+{
+ RemoveTestObjects();
+ return;
+}
+
+
+/*-- Cable Network Functions --*/
+
+global func CreateCableCrossingsConnection(object c1, object c2)
+{
+ var cable = c1->CreateObject(CableLine);
+ cable->SetConnectedObjects(c1, c2);
+ // Log the distance the cable covers of the cable.
+ var dummy = CreateObject(Dummy, (c1->GetX() + c2->GetX()) / 2, (c1->GetY() + c2->GetY()) / 2);
+ dummy->SetCategory(C4D_StaticBack);
+ dummy.Visibility = VIS_All;
+ dummy->Message("@%d", ObjectDistance(c1, c2));
+ cable->CreateEffect(FxRemoveWith, 1, 0, dummy);
+ return cable;
+}
+
+static const FxRemoveWith = new Effect
+{
+ Construction = func(object to_remove)
+ {
+ this.to_remove = to_remove;
+ },
+ Destruction = func()
+ {
+ this.to_remove->RemoveObject();
+ }
+};
+
+global func CreateObjectAbove(id obj, ...)
+{
+ var res = _inherited(obj, ...);
+ if (obj == CableCrossing)
+ res->Message("@%d", res->ObjectNumber());
+ return res;
+}
+
+global func PrintCableCarNetwork()
+{
+ Log("Distances between all of the cable crossings:");
+ var cable_crossings = FindObjects(Find_Func("IsCableCrossing"));
+ var header = "Obj# |";
+ var line = "------";
+ for (var crossing in cable_crossings)
+ {
+ //Log("%v: %v", crossing, crossing->GetDestinations());
+ header = Format("%s %04d", header, crossing->ObjectNumber());
+ line = Format("%s-----", line);
+ }
+ Log(header);
+ Log(line);
+ for (var crossing1 in cable_crossings)
+ {
+ var msg = Format("%04d |", crossing1->ObjectNumber());
+ for (var crossing2 in cable_crossings)
+ {
+ var len = crossing1->GetLengthToTarget(crossing2);
+ msg = Format("%s %04d", msg, len);
+ }
+ Log(msg);
+ }
+ Log(line);
+ if (!IsSymmetricCableCarNetwork())
+ Log("WARNING: distance table is not symmetric.");
+ return;
+}
+
+global func IsSymmetricCableCarNetwork()
+{
+ var cable_crossings = FindObjects(Find_Func("IsCableCrossing"));
+ var dist_table = [];
+ var index1 = 0;
+ for (var crossing1 in cable_crossings)
+ {
+ var index2 = 0;
+ dist_table[index1] = [];
+ for (var crossing2 in cable_crossings)
+ {
+ var len = crossing1->GetLengthToTarget(crossing2);
+ dist_table[index1][index2] = len;
+ index2++;
+ }
+ index1++;
+ }
+ var is_symmetric = true;
+ for (var index1 = 0; index1 < GetLength(dist_table); index1++)
+ for (var index2 = index1 + 1; index2 < GetLength(dist_table); index2++)
+ if (dist_table[index1][index2] != dist_table[index2][index1])
+ is_symmetric = false;
+ return is_symmetric;
+}
+
/*-- Helper Functions --*/
@@ -608,40 +748,3 @@ global func RemoveTestObjects()
));
return;
}
-
-global func CreateCableCrossingsConnection(object c1, object c2)
-{
- var cable = c1->CreateObject(CableLine);
- cable->SetConnectedObjects(c1, c2);
- return cable;
-}
-
-
-global func PrintCableCarNetwork()
-{
- Log("Distances between all of the cable crossings:");
- var cable_crossings = FindObjects(Find_Func("IsCableCrossing"));
- var header = "Obj# |";
- var line = "------";
- for (var crossing in cable_crossings)
- {
- header = Format("%s %04d", header, crossing->ObjectNumber());
- line = Format("%s-----", line);
- }
- Log(Format("%s tot", header));
- Log(Format("%s-----", line));
- for (var crossing1 in cable_crossings)
- {
- var msg = Format("%04d |", crossing1->ObjectNumber());
- var sum = 0;
- for (var crossing2 in cable_crossings)
- {
- var len = crossing1->GetLengthToTarget(crossing2);
- sum += len;
- msg = Format("%s %04d", msg, len);
- }
- msg = Format("%s %04d", msg, sum);
- Log(msg);
- }
- return;
-}