2012-01-02 02:14:57 +00:00
/**
Constructor
Library for objects which are able to construct structures .
@ author Maikel
*/
public func IsConstructor ( ) { return true ; }
2013-05-23 21:59:50 +00:00
func RejectUse ( object clonk )
{
return ! clonk - > IsWalking ( ) ;
}
2012-01-02 02:14:57 +00:00
2016-02-07 09:47:11 +00:00
public func ControlUse ( object clonk , int x , int y )
2012-01-02 02:14:57 +00:00
{
// Otherwise create a menu with possible structures to build.
2014-02-26 17:30:51 +00:00
OpenConstructionMenu ( clonk ) ;
2012-01-02 02:14:57 +00:00
return true ;
}
2012-01-08 14:22:26 +00:00
private func ShowConstructionMaterial ( object clonk , object structure )
{
2012-05-08 18:43:30 +00:00
var mat_msg = " $TxtNeeds$ " ;
2012-01-08 14:22:26 +00:00
var structure_id = structure - > GetID ( ) ;
var comp , index = 0 ;
while ( comp = structure - > GetComponent ( nil , index ) )
{
var current_amount = structure - > GetComponent ( comp ) ;
2016-04-30 20:46:10 +00:00
var max_amount = structure_id - > GetComponent ( comp ) ;
2012-01-08 14:22:26 +00:00
mat_msg = Format ( " %s %dx{{%i}} " , mat_msg , Max ( 0 , max_amount - current_amount ) , comp ) ;
2012-01-02 02:14:57 +00:00
index + + ;
}
2012-01-08 14:22:26 +00:00
clonk - > Message ( mat_msg ) ;
2012-01-02 02:14:57 +00:00
return ;
}
2015-05-25 09:31:23 +00:00
// Gives a list of ids of the players knowledge.
2012-01-02 02:14:57 +00:00
public func GetConstructionPlans ( int plr )
{
var construction_plans = [ ] ;
var construct_id , index = 0 ;
2016-06-18 17:45:45 +00:00
while ( construct_id = GetPlrKnowledge ( plr , nil , index + + , C4D_Structure ) ) // Structures
if ( CanBuild ( construct_id ) )
construction_plans [ GetLength ( construction_plans ) ] = construct_id ;
index = 0 ;
while ( construct_id = GetPlrKnowledge ( plr , nil , index + + , C4D_Vehicle ) ) // Vehicles
if ( CanBuild ( construct_id ) )
construction_plans [ GetLength ( construction_plans ) ] = construct_id ;
index = 0 ;
while ( construct_id = GetPlrKnowledge ( plr , nil , index + + , C4D_Object ) ) // Objects
if ( CanBuild ( construct_id ) )
construction_plans [ GetLength ( construction_plans ) ] = construct_id ;
2012-01-02 02:14:57 +00:00
return construction_plans ;
}
2016-06-18 17:45:45 +00:00
// Checks whether a certain construction plans can be built by this constructor.
// Overload as seem fit.
func CanBuild ( id construction_plan )
{
return true ;
}
2012-03-27 18:10:44 +00:00
2015-05-25 09:31:23 +00:00
/*-- Construction preview --*/
public func ShowConstructionPreview ( object clonk , id structure_id )
2012-03-27 18:10:44 +00:00
{
AddEffect ( " ControlConstructionPreview " , clonk , 1 , 0 , this , nil , structure_id , clonk ) ;
SetPlayerControlEnabled ( clonk - > GetOwner ( ) , CON_Aim , true ) ;
return true ;
}
2015-05-25 09:31:23 +00:00
public func FxControlConstructionPreviewStart ( object clonk , effect , int temp , id structure_id , object clonk )
2012-03-27 18:10:44 +00:00
{
if ( temp ) return ;
effect . structure = structure_id ;
2012-05-08 18:27:24 +00:00
effect . flipable = ! structure_id - > ~ NoConstructionFlip ( ) ;
2013-06-22 18:01:51 +00:00
effect . preview = structure_id - > ~ CreateConstructionPreview ( clonk ) ;
2015-01-10 09:14:02 +00:00
if ( ! effect . preview ) effect . preview = CreateObjectAbove ( ConstructionPreviewer , AbsX ( clonk - > GetX ( ) ) , AbsY ( clonk - > GetY ( ) ) , clonk - > GetOwner ( ) ) ;
2012-03-27 18:10:44 +00:00
effect . preview - > Set ( structure_id , clonk ) ;
}
// Called by Control2Effect
2016-02-23 21:19:39 +00:00
public func FxControlConstructionPreviewControl ( object clonk , effect , int ctrl , int x , int y , int strength , bool repeat , int status )
2012-03-27 18:10:44 +00:00
{
if ( ctrl ! = CON_Aim )
{
2015-05-25 09:31:23 +00:00
// CON_Use is accept, but don't remove the preview, this is done on releasing the button.
2016-02-23 21:19:39 +00:00
if ( ctrl = = CON_Use & & status = = CONS_Down )
2015-05-25 09:31:23 +00:00
{
2015-12-16 22:00:17 +00:00
var ok = CreateConstructionSite ( clonk , effect . structure , AbsX ( effect . preview - > GetX ( ) ) , AbsY ( effect . preview - > GetY ( ) + effect . preview . dimension_y / 2 ) , effect . preview . blocked , effect . preview . direction , effect . preview . stick_to ) ;
if ( ok )
clonk - > ~ PlaySoundConfirm ( ) ;
else
clonk - > ~ PlaySoundDecline ( ) ;
2015-05-25 09:31:23 +00:00
return true ;
}
2012-03-28 17:39:00 +00:00
// movement is allowed
2012-05-08 18:27:24 +00:00
else if ( IsMovementControl ( ctrl ) )
2012-03-28 17:39:00 +00:00
return false ;
2012-04-16 15:31:38 +00:00
// Flipping
2012-05-08 18:27:24 +00:00
// this is actually realized twice. Once as an Extra-Interaction in the clonk, and here. We don't want the Clonk to get any non-movement controls though, so we handle it here too.
// (yes, this means that actionbar-hotkeys wont work for it. However clicking the button will.)
2012-05-08 18:43:30 +00:00
else if ( IsInteractionControl ( ctrl ) )
2012-04-16 15:31:38 +00:00
{
2016-02-23 21:19:39 +00:00
if ( status = = CONS_Up )
2012-04-16 15:31:38 +00:00
effect . preview - > Flip ( ) ;
return true ;
}
2012-03-28 17:39:00 +00:00
// everything else declines
2012-03-27 18:10:44 +00:00
RemoveEffect ( " ControlConstructionPreview " , clonk , effect ) ;
return true ;
}
2012-03-28 17:39:00 +00:00
2012-03-27 18:10:44 +00:00
effect . preview - > Reposition ( x , y ) ;
return true ;
}
2015-05-25 09:31:23 +00:00
public func FxControlConstructionPreviewStop ( object clonk , effect , int reason , bool temp )
2012-03-27 18:10:44 +00:00
{
if ( temp ) return ;
effect . preview - > RemoveObject ( ) ;
2012-04-14 21:16:17 +00:00
SetPlayerControlEnabled ( clonk - > GetOwner ( ) , CON_Aim , false ) ;
2012-03-27 18:10:44 +00:00
}
2015-05-25 09:31:23 +00:00
/*-- Construction --*/
public func CreateConstructionSite ( object clonk , id structure_id , int x , int y , bool blocked , int dir , object stick_to )
2012-01-02 02:14:57 +00:00
{
// Only when the clonk is standing and outdoors
if ( clonk - > GetAction ( ) ! = " Walk " )
return false ;
2012-04-21 23:00:41 +00:00
if ( clonk - > Contained ( ) )
2012-01-02 02:14:57 +00:00
return false ;
// Check if the building can be build here
2012-03-27 18:10:44 +00:00
if ( structure_id - > ~ RejectConstruction ( x , y , clonk ) )
2012-01-02 02:14:57 +00:00
return false ;
2014-05-30 07:44:30 +00:00
if ( blocked )
2012-04-02 21:49:39 +00:00
{
2014-01-25 09:20:27 +00:00
CustomMessage ( " $TxtNoSiteHere$ " , this , clonk - > GetOwner ( ) , nil , nil , RGB ( 255 , 0 , 0 ) ) ;
2012-04-02 21:49:39 +00:00
return false ;
2014-05-30 07:44:30 +00:00
}
2012-04-14 22:29:38 +00:00
// intersection-check with all other construction sites... bah
2014-02-26 17:30:51 +00:00
for ( var other_site in FindObjects ( Find_ID ( ConstructionSite ) ) )
2012-04-14 22:29:38 +00:00
{
2015-05-25 09:31:23 +00:00
if ( ! ( other_site - > GetLeftEdge ( ) > GetX ( ) + x + structure_id - > GetDefWidth ( ) / 2 | |
2012-04-14 22:29:38 +00:00
other_site - > GetRightEdge ( ) < GetX ( ) + x - structure_id - > GetDefWidth ( ) / 2 | |
other_site - > GetTopEdge ( ) > GetY ( ) + y + structure_id - > GetDefHeight ( ) / 2 | |
other_site - > GetBottomEdge ( ) < GetY ( ) + y - structure_id - > GetDefHeight ( ) / 2 ) )
{
2015-05-25 09:31:23 +00:00
CustomMessage ( Format ( " $TxtBlocked$ " , other_site - > GetName ( ) ) , this , clonk - > GetOwner ( ) , nil , nil , RGB ( 255 , 0 , 0 ) ) ;
2012-04-14 22:29:38 +00:00
return false ;
}
}
2012-04-02 21:49:39 +00:00
// Set owner for CreateConstruction
SetOwner ( clonk - > GetOwner ( ) ) ;
// Create construction site
var site ;
2015-01-10 09:14:02 +00:00
site = CreateObjectAbove ( ConstructionSite , x , y , Contained ( ) - > GetOwner ( ) ) ;
2014-01-25 09:20:27 +00:00
/* note: this is necessary to have the site at the exact position x,y. Otherwise, for reasons I don't know, the
ConstructionSite seems to move 2 pixels downwards ( on ConstructionSite : : Construction ( ) it is still the
original position ) which leads to that the CheckConstructionSite function gets different parameters later
when the real construction should be created which of course could mean that it returns something else . ( # 1012 )
- Newton
*/
site - > SetPosition ( GetX ( ) + x , GetY ( ) + y ) ;
2013-08-20 12:03:43 +00:00
// Randomize sign rotation
2014-02-26 17:30:51 +00:00
site - > SetProperty ( " MeshTransformation " , Trans_Mul ( Trans_Rotate ( RandomX ( - 30 , 30 ) , 0 , 1 , 0 ) , Trans_Rotate ( RandomX ( - 10 , 10 ) , 1 , 0 , 0 ) ) ) ;
site - > PlayAnimation ( " LeftToRight " , 1 , Anim_Const ( RandomX ( 0 , GetAnimationLength ( " LeftToRight " ) ) ) , Anim_Const ( 500 ) ) ;
2013-08-20 12:03:43 +00:00
2014-02-26 17:30:51 +00:00
site - > Set ( structure_id , dir , stick_to ) ;
2012-04-02 21:49:39 +00:00
//if(!(site = CreateConstruction(structure_id, x, y, Contained()->GetOwner(), 1, 1, 1)))
//return false;
2016-03-29 15:38:43 +00:00
site - > TakeConstructionMaterials ( clonk ) ;
2012-03-29 20:08:54 +00:00
2012-01-02 02:14:57 +00:00
// Message
2012-04-02 21:49:39 +00:00
clonk - > Message ( " $TxtConstructions$ " , structure_id - > GetName ( ) ) ;
2012-01-02 02:14:57 +00:00
return true ;
2014-02-26 17:30:51 +00:00
}
/*-- Construction Menu --*/
2014-04-09 20:48:06 +00:00
// Local variable to keep track of the menu properties.
2014-02-26 17:30:51 +00:00
local menu , menu_id , menu_target , menu_controller ;
public func OpenConstructionMenu ( object clonk )
{
// If the menu is already open, don't open another instance.
if ( clonk - > GetMenu ( ) & & clonk - > GetMenu ( ) . ID = = menu_id )
return ;
// Create a menu target for visibility.
menu_target = CreateObject ( Dummy , 0 , 0 , clonk - > GetOwner ( ) ) ;
menu_target . Visibility = VIS_Owner ;
menu_controller = clonk ;
2014-04-09 20:48:06 +00:00
// Size of the grid items in em.
2015-09-06 17:02:31 +00:00
var item_size = 4 ;
2014-02-26 17:30:51 +00:00
// Construction menu proplist.
menu =
{
Target = menu_target ,
Decoration = GUI_MenuDeco ,
2014-12-25 16:21:39 +00:00
BackgroundColor = 0xee403020
2014-02-26 17:30:51 +00:00
} ;
2015-06-15 19:14:26 +00:00
menu . structures = CreateStructureGrid ( clonk , item_size ) ;
menu . struct_info = CreateStructureInfo ( ) ;
2014-12-25 16:21:39 +00:00
menu . separator =
2014-04-09 20:48:06 +00:00
{
2015-06-15 19:14:26 +00:00
Left = " 60% " ,
2015-09-06 17:02:31 +00:00
Right = " 60%+0.5em " ,
2014-04-09 20:48:06 +00:00
BackgroundColor = { Std = 0x50888888 }
} ;
// Menu ID.
2014-10-11 09:51:26 +00:00
menu_id = GuiOpen ( menu ) ;
2014-04-09 20:48:06 +00:00
clonk - > SetMenu ( menu_id ) ;
return ;
}
2015-06-15 19:14:26 +00:00
public func CreateStructureGrid ( object clonk , int item_size )
2014-04-09 20:48:06 +00:00
{
2014-02-26 17:30:51 +00:00
var structures =
{
Target = menu_target ,
ID = 1 ,
2015-06-15 19:14:26 +00:00
Right = " 60% " ,
2014-12-25 16:21:39 +00:00
Style = GUI_GridLayout
2014-02-26 17:30:51 +00:00
} ;
2014-04-09 20:48:06 +00:00
structures = MenuAddStructures ( structures , clonk , item_size ) ;
return structures ;
}
2015-06-15 19:14:26 +00:00
public func CreateStructureInfo ( )
2014-04-09 20:48:06 +00:00
{
2014-02-26 17:30:51 +00:00
var structinfo =
{
Target = menu_target ,
ID = 2 ,
2015-09-06 17:02:31 +00:00
Left = " 60%+0.5em "
2014-02-26 17:30:51 +00:00
} ;
2015-06-15 19:14:26 +00:00
// Bottom part for material costs, description and other written information.
2014-12-25 16:21:39 +00:00
structinfo . description =
2014-02-26 17:30:51 +00:00
{
Target = menu_target ,
Priority = 0x0fffff ,
2015-09-06 17:02:31 +00:00
Left = " 0.25em " ,
Right = " 100%-0.25em " ,
Top = " 100%-3em " ,
2014-02-26 17:30:51 +00:00
Bottom = " 100% " ,
2014-04-09 20:48:06 +00:00
Text = nil // will be updated
2014-02-26 17:30:51 +00:00
} ;
2015-06-15 19:14:26 +00:00
structinfo . materials =
2014-02-26 17:30:51 +00:00
{
Target = menu_target ,
2015-06-15 19:14:26 +00:00
Priority = 0x0fffff ,
2015-09-06 17:02:31 +00:00
Left = " 0.25em " ,
Right = " 100%-0.25em " ,
Top = " 100%-5em " ,
Bottom = " 100%-3em " ,
2015-06-15 19:14:26 +00:00
Text = nil // will be updated
2014-02-26 17:30:51 +00:00
} ;
2015-06-15 19:14:26 +00:00
// Upper part is for the picture and power display.
structinfo . picture =
2014-02-26 17:30:51 +00:00
{
Target = menu_target ,
2015-09-06 17:02:31 +00:00
Bottom = " 100%-5em " ,
Margin = [ " 10%+0.5em " ] ,
2015-06-15 19:14:26 +00:00
Symbol = nil , // will be updated
power_consumer =
{
Target = menu_target ,
2015-09-06 17:02:31 +00:00
Right = " 1.5em " ,
Bottom = " 1.5em " ,
2015-06-15 19:14:26 +00:00
Symbol = nil // will be updated
} ,
power_producer =
{
Target = menu_target ,
2015-09-06 17:02:31 +00:00
Left = " 1.5em " ,
Right = " 3em " ,
Bottom = " 1.5em " ,
2015-06-15 19:14:26 +00:00
Symbol = nil // will be updated
}
2014-02-26 17:30:51 +00:00
} ;
2014-12-25 16:21:39 +00:00
structinfo . close_button =
2014-02-26 17:30:51 +00:00
{
Target = menu_target ,
2015-09-06 17:02:31 +00:00
Left = " 100%-2em " ,
Bottom = " 2em " ,
2014-02-26 17:30:51 +00:00
Symbol = Icon_Cancel ,
BackgroundColor = { Std = 0 , Hover = 0x50ffff00 } ,
OnMouseIn = GuiAction_SetTag ( " Hover " ) ,
OnMouseOut = GuiAction_SetTag ( " Std " ) ,
2014-04-09 20:48:06 +00:00
OnClick = GuiAction_Call ( this , " CloseConstructionMenu " )
2014-02-26 17:30:51 +00:00
} ;
2014-04-09 20:48:06 +00:00
return structinfo ;
2014-02-26 17:30:51 +00:00
}
2014-04-09 20:48:06 +00:00
public func MenuAddStructures ( proplist struct , object clonk , int item_size )
2014-02-26 17:30:51 +00:00
{
var plans = GetConstructionPlans ( clonk - > GetOwner ( ) ) ;
2015-06-15 19:14:26 +00:00
for ( var structure in plans )
2014-02-26 17:30:51 +00:00
{
var str =
{
Target = menu_target ,
2014-04-09 20:48:06 +00:00
Right = Format ( " %dem " , item_size ) ,
Bottom = Format ( " %dem " , item_size ) ,
2014-02-26 17:30:51 +00:00
BackgroundColor = { Std = 0 , Hover = 0x50ffffff } ,
OnMouseIn = [ GuiAction_SetTag ( " Hover " ) , GuiAction_Call ( this , " OnConstructionHover " , structure ) ] ,
OnMouseOut = GuiAction_SetTag ( " Std " ) ,
2015-06-15 19:14:26 +00:00
OnClick = GuiAction_Call ( this , " OnConstructionSelection " , { struct = structure , constructor = clonk } ) ,
Priority = structure - > GetValue ( ) ,
2014-12-25 16:21:39 +00:00
picture =
2014-02-26 17:30:51 +00:00
{
Left = " 8% " ,
Right = " 92% " ,
Top = " 8% " ,
Bottom = " 92% " ,
2014-04-09 20:48:06 +00:00
Symbol = structure
}
2014-02-26 17:30:51 +00:00
} ;
2014-12-25 16:21:39 +00:00
GuiAddSubwindow ( str , struct ) ;
2014-02-26 17:30:51 +00:00
}
return struct ;
}
public func OnConstructionSelection ( proplist par )
{
2015-06-15 19:14:26 +00:00
ShowConstructionPreview ( par . constructor , par . struct ) ;
2014-02-26 17:30:51 +00:00
CloseConstructionMenu ( ) ;
return ;
}
public func OnConstructionHover ( id structure )
{
2014-12-25 16:21:39 +00:00
var struct_info = menu . struct_info ;
2014-02-26 17:30:51 +00:00
2015-06-15 19:14:26 +00:00
// Update the description and costs of this part of the menu.
struct_info . description . Text = Format ( " %s: %s " , structure - > GetName ( ) , structure . Description ) ;
struct_info . materials . Text = GetStructureMaterialsString ( structure ) ;
2014-02-26 17:30:51 +00:00
// Update the picture of the structure.
2014-12-25 16:21:39 +00:00
struct_info . picture . Symbol = structure ;
2014-02-26 17:30:51 +00:00
// Update also power consumption/production.
if ( structure - > ~ IsPowerConsumer ( ) )
2015-06-15 19:14:26 +00:00
struct_info . picture . power_consumer . Symbol = Library_PowerConsumer ;
2014-02-26 17:30:51 +00:00
else
2015-06-15 19:14:26 +00:00
struct_info . picture . power_consumer . Symbol = nil ;
2014-12-25 16:21:39 +00:00
2014-02-26 17:30:51 +00:00
if ( structure - > ~ IsPowerProducer ( ) )
2015-06-15 19:14:26 +00:00
struct_info . picture . power_producer . Symbol = Library_PowerProducer ;
2014-02-26 17:30:51 +00:00
else
2015-06-15 19:14:26 +00:00
struct_info . picture . power_producer . Symbol = nil ;
2014-12-25 16:21:39 +00:00
// update everything - close the old info first to clean up possible remainers and then re-open it
menu . struct_info = struct_info ;
GuiClose ( menu_id , menu . struct_info . ID , menu . struct_info . Target ) ;
GuiUpdate ( { struct_info = menu . struct_info } , menu_id ) ;
2014-02-26 17:30:51 +00:00
return ;
}
2015-06-15 19:14:26 +00:00
private func GetStructureMaterialsString ( id structure )
{
var comp , index = 0 ;
var components = [ ] ;
2016-04-30 20:46:10 +00:00
while ( comp = structure - > GetComponent ( nil , index + + ) )
components [ GetLength ( components ) ] = [ comp , structure - > GetComponent ( comp ) ] ;
2015-06-15 19:14:26 +00:00
var materials_string = " Costs: " ;
for ( comp in components )
materials_string = Format ( " %s %dx {{%i}} " , materials_string , comp [ 1 ] , comp [ 0 ] ) ;
return materials_string ;
}
2014-02-26 17:30:51 +00:00
public func CloseConstructionMenu ( )
{
2014-10-11 09:51:26 +00:00
GuiClose ( menu_id , nil , menu_target ) ;
2014-02-26 17:30:51 +00:00
menu_id = nil ;
menu_target - > RemoveObject ( ) ;
menu_target = nil ;
if ( menu_controller )
menu_controller - > MenuClosed ( ) ;
menu_controller = nil ;
return ;
}