New implementation for the production menu, similar to contents menu

heavy-resources
Maikel de Vries 2011-12-29 16:59:07 +01:00
parent 90427fced6
commit e1da36219f
9 changed files with 370 additions and 86 deletions

View File

@ -11,27 +11,27 @@ Definition1=Objects.ocd
Rules=Rule_EnergyNeed=1;Rule_TeamAccount=1;
[Player1]
Wealth=80
Wealth=30
Crew=Clonk=2
Knowledge=WoodenCabin=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;CableCrossing=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;
Knowledge=WoodenCabin=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Sawmill=1;CableCrossing=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;CableLorry=2;CableLorryReel=5;
[Player2]
Wealth=80
Wealth=30
Crew=Clonk=2
Knowledge=WoodenCabin=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;CableCrossing=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;
Knowledge=WoodenCabin=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Sawmill=1;CableCrossing=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;CableLorry=2;CableLorryReel=5;
[Player3]
Wealth=80
Wealth=30
Crew=Clonk=2
Knowledge=WoodenCabin=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;CableCrossing=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;
Knowledge=WoodenCabin=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Sawmill=1;CableCrossing=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;CableLorry=2;CableLorryReel=5;
[Player4]
Wealth=80
Wealth=30
Crew=Clonk=2
Knowledge=WoodenCabin=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;CableCrossing=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;
Knowledge=WoodenCabin=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Sawmill=1;CableCrossing=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;CableLorry=2;CableLorryReel=5;
[Landscape]

View File

@ -53,7 +53,8 @@ func Construction()
circ_menus = [];
}
func Close() {
func Close()
{
if(menu_object)
menu_object->~MenuClosed(this);
RemoveObject();

View File

@ -130,7 +130,9 @@ public func ResetSize() { SetSize(100); }
public func SetCount(int count)
{
item_count = BoundBy(count, 0, 999); // No more supported currently.
item_count = count;
if (item_count != nil)
item_count = BoundBy(item_count, 0, 999); // No more supported currently.
Update();
return;
}
@ -150,7 +152,16 @@ public func Update()
// Set mouse drag image.
this.MouseDragImage = item_object;
// Set item graphics.
// Update item symbol.
UpdateSymbol();
// Update item amount.
UpdateCount();
return;
}
private func UpdateSymbol()
{
if (!item_object)
{
SetGraphics(nil, nil, 1);
@ -186,38 +197,51 @@ public func Update()
SetName(item_object->GetName());
}
// Set item count.
var one = item_count % 10;
var ten = (item_count / 10) % 10;
var hun = (item_count / 100) % 10;
var s = 200;
var yoffs = 10000;
var xoffs = 13000;
var spacing = 5000;
SetGraphics(Format("10"), Icon_SlimNumber, 9, GFXOV_MODE_IngamePicture); //10 == "x"
SetGraphics(Format("%d", one), Icon_SlimNumber, 12, GFXOV_MODE_IngamePicture);
SetObjDrawTransform(s, 0, xoffs-spacing-500, 0, s, yoffs+300, 9);
SetObjDrawTransform(s, 0, xoffs, 0, s, yoffs, 12);
if (ten > 0 || hun > 0)
{
SetGraphics(Format("%d", ten), Icon_SlimNumber, 11, GFXOV_MODE_IngamePicture);
SetObjDrawTransform(s, 0, xoffs-spacing*2-500, 0, s, yoffs+300, 9);
SetObjDrawTransform(s, 0, xoffs-spacing, 0, s, yoffs, 11);
}
else
SetGraphics(nil, nil, 11);
if (hun > 0)
{
SetGraphics(Format("%d", hun), Icon_SlimNumber, 10, GFXOV_MODE_IngamePicture);
SetObjDrawTransform(s, 0, xoffs-spacing*3-500, 0, s, yoffs+300, 9);
SetObjDrawTransform(s, 0, xoffs-spacing*2, 0, s, yoffs, 10);
}
else
SetGraphics(nil, nil, 10);
return;
}
private func UpdateCount()
{
if (item_count == nil)
{
SetGraphics(nil, nil, 9);
SetGraphics(nil, nil, 10);
SetGraphics(nil, nil, 11);
SetGraphics(nil, nil, 12);
}
else
{
// Set item count.
var one = item_count % 10;
var ten = (item_count / 10) % 10;
var hun = (item_count / 100) % 10;
var s = 200;
var yoffs = 10000;
var xoffs = 13000;
var spacing = 5000;
SetGraphics(Format("10"), Icon_SlimNumber, 9, GFXOV_MODE_IngamePicture); //10 == "x"
SetGraphics(Format("%d", one), Icon_SlimNumber, 12, GFXOV_MODE_IngamePicture);
SetObjDrawTransform(s, 0, xoffs-spacing-500, 0, s, yoffs+300, 9);
SetObjDrawTransform(s, 0, xoffs, 0, s, yoffs, 12);
if (ten > 0 || hun > 0)
{
SetGraphics(Format("%d", ten), Icon_SlimNumber, 11, GFXOV_MODE_IngamePicture);
SetObjDrawTransform(s, 0, xoffs-spacing*2-500, 0, s, yoffs+300, 9);
SetObjDrawTransform(s, 0, xoffs-spacing, 0, s, yoffs, 11);
}
else
SetGraphics(nil, nil, 11);
if (hun > 0)
{
SetGraphics(Format("%d", hun), Icon_SlimNumber, 10, GFXOV_MODE_IngamePicture);
SetObjDrawTransform(s, 0, xoffs-spacing*3-500, 0, s, yoffs+300, 9);
SetObjDrawTransform(s, 0, xoffs-spacing*2, 0, s, yoffs, 10);
}
else
SetGraphics(nil, nil, 10);
}
return;
}

View File

@ -222,19 +222,6 @@ private func GetItemRadius(int total)
return 1;
}
// Shows the menu.
public func Show()
{
UpdateMenu();
// Change visibility.
for (var item in menu_items)
if (item)
item.Visibility = VIS_Owner;
this.Visibility = VIS_Owner;
menu_shown = true;
return;
}
public func UpdateMenu()
{
// Safety: check for items.
@ -258,6 +245,19 @@ public func UpdateMenu()
return;
}
// Shows the menu.
public func Show()
{
UpdateMenu();
// Change visibility.
for (var item in menu_items)
if (item)
item.Visibility = VIS_Owner;
this.Visibility = VIS_Owner;
menu_shown = true;
return;
}
public func Hide()
{
// Change visibility.
@ -276,7 +276,6 @@ protected func Destruction()
for (var i = 0; i < GetLength(menu_items); i++)
if (menu_items[i])
menu_items[i]->RemoveObject();
return;
}

View File

@ -13,6 +13,6 @@ VertexFriction=90,90,90
Value=3
Mass=8
Rotate=1
Components=Coal=1;Sulphur=1
ContactIncinerate=1
BlastIncinerate=1
Components=Sulphur=1;Coal=1

View File

@ -0,0 +1,7 @@
[DefCore]
id=Library_ProductionMenu
Version=5,2,0,1
Category=C4D_StaticBack | C4D_IgnoreFoW | C4D_Foreground | C4D_Parallax | C4D_MouseSelect
Width=640
Height=320
Offset=-160,-160

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

View File

@ -0,0 +1,221 @@
/**
Production Menu, it consists of two parts: a circle with possible products
and a rectangle with the current queue.
@author Maikel
*/
#include GUI_Menu
local menu_queue;
/** Creates a production menu for the calling object. This is supposed to be a crew member,
controlled by a player.
@param producer the producer for which to create the production menu.
@return a pointer to the created menu, or \c nil if failed.
*/
global func CreateProductionMenu(object producer)
{
// Safety checks.
if (!this) return;
if (!(GetOCF() & OCF_CrewMember)) return;
if (!(this->~HasMenuControl())) return;
// Create the menu controller.
var controller = CreateObject(Library_ProductionMenu);
controller->SetMenuObject(this);
this->SetMenu(controller);
controller->SetCommander(producer);
// Add all products to the menu (circle).
controller->AddMenuProducts(producer);
// Add currennt queue to the menu (rectangle).
controller->AddMenuQueue(producer);
// Show and return production menu.
controller->Show();
return controller;
}
protected func Construction()
{
menu_queue = [];
SetPosition(600, 400);
return _inherited(...);
}
public func AddMenuProducts(object producer)
{
for (var product in producer->GetProducts())
{
var item = CreateObject(GUI_MenuItem);
if (!AddItem(item))
return item->RemoveObject();
item->SetSymbol(product);
}
return;
}
public func AddMenuQueue(object producer)
{
for (var qitem in producer->GetQueue())
{
var item = CreateObject(GUI_MenuItem);
if (!AddQueueItem(item))
return item->RemoveObject();
item->SetSymbol(qitem.Product);
item->SetCount(qitem.Amount);
}
UpdateQueueMenu();
return;
}
public func UpdateMenuQueue(object producer)
{
for (var qitem in menu_queue)
qitem->RemoveObject();
SetLength(menu_queue, 0);
AddMenuQueue(producer);
return;
}
/* Menu properties */
public func AddQueueItem(object item)
{
var queue_cnt = GetLength(menu_queue);
// Create new menu item.
menu_queue[queue_cnt] = item;
item->SetMenu(this);
item->SetOwner(GetOwner());
// Set item visibility.
item.Visibility = VIS_None;
if (menu_shown)
item.Visibility = VIS_Owner;
return true;
}
public func UpdateQueueMenu()
{
// Safety: check for queue items.
var queue_cnt = GetLength(menu_queue);
var x = GetX();
var y = GetY();
for (var i = 0; i < queue_cnt; i++)
{
var pos = 2 * i * MENU_Radius / 3 + 200;
var qitem = menu_queue[i];
if (qitem)
{
qitem->SetSize(200 * MENU_Radius / 3 / 96);
qitem->SetPosition(x + pos, y - 80);
}
}
return;
}
public func Close()
{
if(menu_object)
menu_object->~MenuClosed(this);
RemoveObject();
}
public func Show()
{
// Change visibility.
for (var qitem in menu_queue)
if (qitem)
qitem.Visibility = VIS_Owner;
return _inherited(...);
}
public func Hide()
{
// Change visibility.
for (var qitem in menu_queue)
if (qitem)
qitem.Visibility = VIS_None;
return _inherited(...);
}
// Engine callback: if the menu is destroyed, the items must follow.
protected func Destruction()
{
for (var i = 0; i < GetLength(menu_queue); i++)
if (menu_queue[i])
menu_queue[i]->RemoveObject();
return _inherited(...);
}
private func IsProductItem(object item)
{
for (var test in menu_items)
if (test == item)
return true;
return false;
}
private func IsQueueItem(object item)
{
for (var test in menu_queue)
if (test == item)
return true;
return false;
}
private func GetQueueIndex(object item)
{
var index = 0;
for (index = 0; index < GetLength(menu_queue); index++)
if (menu_queue[index] == item)
break;
return index;
}
/* Callbacks from the menu items, to be translated into commands for the producer. */
// Called when an item has been selected (left mouse button).
public func OnItemSelection(object item)
{
// If item is from products, add one to queue.
if (IsProductItem(item))
{
menu_commander->AddToQueue(item->GetSymbol(), 1);
UpdateMenuQueue(menu_commander);
}
// If item is from queue, remove one from queue.
if (IsQueueItem(item))
{
menu_commander->RemoveFromQueue(GetQueueIndex(item), 1);
UpdateMenuQueue(menu_commander);
}
return _inherited(item, ...);
}
// Called when an item has been selected (right mouse button).
public func OnItemSelectionAlt(object item)
{
return _inherited(item, ...);
}
// Called when an object is dragged onto the menu
public func MouseDrop(int plr, obj)
{
return _inherited(plr, obj, ...);
}
// Called when another item has been dropped on an item in this menu.
public func OnItemDropped(object drop_item, object on_item)
{
return _inherited(drop_item, on_item, ...);
}
// Called after an item from this menu has been dragged onto an item
public func OnItemDragDone(object drag_item, object on_item)
{
return _inherited(drag_item, on_item, ...);
}

View File

@ -51,7 +51,8 @@ public func GetInteractionMetaInfo(object clonk)
public func Interact(object clonk)
{
// Open production menu for the caller.
OpenProductionMenu(clonk);
clonk->CreateProductionMenu(this);
//OpenProductionMenu(clonk);
return true;
}
@ -95,6 +96,23 @@ private func IsProduct(id product_id)
return false;
}
/** Returns an array with the ids of products which can be produced at this producer.
@return array with products.
*/
public func GetProducts()
{
var products = [];
// Cycle through all definitions to find the ones this producer can produce.
var index = 0, product;
while (product = GetDefinition(index))
{
if (IsProduct(product))
products[GetLength(products)] = product;
index++;
}
return products;
}
/** Determines whether the raw material specified is needed for production. Should be overloaded by the producer.
@param rawmat_id id of raw material for which to determine if it is needed for production.
@return \c true if the raw material is needed, \c false otherwise.
@ -126,30 +144,42 @@ private func ProductionCosts(id item_id)
/*-- Production queue --*/
/** Adds an item to the production queue.
@param item_id id of the item.
@param product_id id of the item.
@param amount the amount of items of \c item_id which should be produced.
@return \c current position of the item in the production queue.
*/
public func AddToQueue(id item_id, int amount)
public func AddToQueue(id product_id, int amount)
{
// Check if this producer can produce the requested item.
if (!IsProduct(item_id))
if (!IsProduct(product_id))
return nil;
var pos = GetLength(queue);
queue[pos] = [item_id, amount];
// Check if the same product is in the position before, cause of possible redundancy.
if (amount != nil && pos > 0 && queue[pos-1].Product == product_id)
queue[pos-1].Amount += amount;
// Otherwise create a new entry in the queue.
else
queue[pos] = { Product = product_id, Amount = amount };
return pos;
}
/** Removes an item from the production queue.
/** Removes a item or some of it from from the production queue.
@param pos position of the item in the queue.
@param amount the amount of this item which should be removed.
@return \c nil.
*/
public func RemoveFromQueue(int pos)
public func RemoveFromQueue(int pos, int amount)
{
var length = GetLength(queue);
// Safety, pos out of reach.
if (pos > length - 1)
return;
// Reduce and check amount.
queue[pos].Amount -= amount;
if (queue[pos].Amount > 0)
return;
// If amount < 0, remove item from queue.
// From pos onwards queue items should be shift downwards.
for (var i = pos; i < GetLength(queue); i++)
queue[i] = queue[i+1];
@ -175,6 +205,14 @@ public func ClearQueue(bool abort)
return;
}
/** Returns the current queue.
@return an array containing the queue elements (.Product for id, .Amount for amount).
*/
public func GetQueue()
{
return queue;
}
protected func FxProcessQueueStart()
{
@ -188,36 +226,30 @@ protected func FxProcessQueueTimer(object target, proplist effect)
return 1;
// Wait if there are no items in the queue.
var to_produce = queue[0];
if (!to_produce)
if (!queue[0])
return 1;
// Produce first item in the queue.
var item_id = to_produce[0];
var amount = to_produce[1];
var product_id = queue[0].Product;
var amount = queue[0].Amount;
// Check raw material need.
if (!CheckMaterial(item_id))
if (!CheckMaterial(product_id))
{
// No material available? request from cable network.
RequestMaterial(item_id);
RequestMaterial(product_id);
return 1;
}
// Start the item production.
if (!Produce(item_id))
if (!Produce(product_id))
return 1;
// Update amount and or queue.
if (amount == nil)
return 1;
amount--;
// If amount is zero, remove item from queue.
if (amount <= 0)
{
RemoveFromQueue(0);
return 1;
}
// Update queue, insert new amount.
queue[0] = [item_id, amount];
// Update queue, reduce amount.
RemoveFromQueue(0, 1);
// Done with production checks.
return 1;
}
@ -316,7 +348,7 @@ private func CheckForPower(id product)
{
// At least ten percent of the power need must be in the network.
if (!CheckPower(PowerNeed() / 10, true))
return false;
return false;
}
return true;
}
@ -345,7 +377,7 @@ protected func FxProcessProductionStart(object target, proplist effect, int temp
// Production is active.
effect.Active = true;
Log("Production started on %i", effect.Product);
//Log("Production started on %i", effect.Product);
// Callback to the producer.
this->~OnProductionStart(effect.Product);
@ -384,7 +416,7 @@ protected func FxProcessProductionTimer(object target, proplist effect, int time
// Add effect interval to production duration.
effect.Duration += effect.Interval;
Log("Production in progress on %i, %d frames, %d time", effect.Product, effect.Duration, time);
//Log("Production in progress on %i, %d frames, %d time", effect.Product, effect.Duration, time);
// Check if production time has been reached.
if (effect.Duration >= ProductionTime())
@ -398,7 +430,7 @@ protected func FxProcessProductionStop(object target, proplist effect, int reaso
if (reason != 0)
return 1;
// Callback to the producer.
Log("Production finished on %i after %d frames", effect.Product, effect.Duration);
//Log("Production finished on %i after %d frames", effect.Product, effect.Duration);
this->~OnProductionFinish(effect.Product);
// Create product.
var product = CreateObject(effect.Product);