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; }
|
|
|
|
|
|
|
|
|
|
|
|
public func ControlUseStart(object clonk, int x, int y)
|
|
|
|
{
|
|
|
|
// Is the clonk able to construct?
|
|
|
|
if(clonk->GetProcedure() != "WALK")
|
|
|
|
{
|
|
|
|
clonk->CancelUse();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Is the clonk at an construction site?
|
|
|
|
var structure = FindObject(Find_Category(C4D_Structure), Find_Or(Find_Distance(20), Find_AtPoint()), Find_Layer(GetObjectLayer()));
|
|
|
|
if (structure)
|
|
|
|
{
|
2012-03-29 20:08:54 +00:00
|
|
|
/* if (structure->GetCon() < 100)
|
2012-01-02 02:14:57 +00:00
|
|
|
{
|
|
|
|
Construct(clonk, structure);
|
|
|
|
return true;
|
2012-03-29 20:08:54 +00:00
|
|
|
}*/
|
2012-01-02 02:14:57 +00:00
|
|
|
if (structure->GetDamage() > 0)
|
|
|
|
{
|
|
|
|
Repair(clonk, structure);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise create a menu with possible structures to build.
|
|
|
|
clonk->CreateConstructionMenu(this);
|
|
|
|
clonk->CancelUse();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public func HoldingEnabled() { return true; }
|
|
|
|
|
|
|
|
public func ControlUseHolding(object clonk, int x, int y)
|
|
|
|
{
|
|
|
|
// Is the clonk still able to construct?
|
|
|
|
if (clonk->GetProcedure() != "WALK")
|
|
|
|
{
|
|
|
|
clonk->CancelUse();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Is the clonk still at an construction site?
|
|
|
|
var structure = FindObject(Find_Category(C4D_Structure), Find_Or(Find_Distance(20), Find_AtPoint()), Find_Layer(GetObjectLayer()));
|
|
|
|
if (structure)
|
|
|
|
{
|
2012-03-29 20:08:54 +00:00
|
|
|
/*
|
2012-01-02 02:14:57 +00:00
|
|
|
if (structure->GetCon() < 100)
|
|
|
|
{
|
|
|
|
Construct(clonk, structure);
|
|
|
|
return true;
|
2012-03-29 20:08:54 +00:00
|
|
|
}*/
|
2012-01-02 02:14:57 +00:00
|
|
|
if (structure->GetDamage() > 0)
|
|
|
|
{
|
|
|
|
Repair(clonk, structure);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
clonk->CancelUse();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private func Construct(object clonk, object structure)
|
|
|
|
{
|
|
|
|
// Look for missing components.
|
|
|
|
var structure_id = structure->GetID();
|
|
|
|
var con = structure->GetCon();
|
|
|
|
var comp, index = 0;
|
2012-01-08 14:22:26 +00:00
|
|
|
var can_construct = true;
|
2012-01-02 02:14:57 +00:00
|
|
|
while (comp = structure->GetComponent(nil, index))
|
|
|
|
{
|
|
|
|
var max_amount = GetComponent(comp, nil, nil, structure_id);
|
2012-01-08 14:22:26 +00:00
|
|
|
// Try to transfer components from constructing clonk to the structure.
|
|
|
|
for (var i = 0; i < max_amount - structure->GetComponent(comp); i++)
|
2012-01-02 02:14:57 +00:00
|
|
|
{
|
|
|
|
var content = FindObject(Find_Container(clonk), Find_ID(comp));
|
2012-01-08 14:22:26 +00:00
|
|
|
if (content)
|
2012-01-02 02:14:57 +00:00
|
|
|
{
|
2012-01-08 14:22:26 +00:00
|
|
|
clonk->Message("Used {{%i}}", comp);
|
|
|
|
content->RemoveObject();
|
|
|
|
structure->SetComponent(comp, structure->GetComponent(comp) + 1);
|
2012-01-02 02:14:57 +00:00
|
|
|
}
|
2012-01-08 14:22:26 +00:00
|
|
|
}
|
|
|
|
// Check if there now is enough material for current con, if so the construction can continue.
|
|
|
|
if (100 * structure->GetComponent(comp) / max_amount < con)
|
|
|
|
can_construct = false;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
// Continue construction if possible.
|
|
|
|
if (can_construct)
|
|
|
|
{
|
|
|
|
structure->DoCon(1);
|
|
|
|
clonk->Message("Constructing %d%", structure->GetCon());
|
|
|
|
}
|
|
|
|
// Otherwise show missing construction materials.
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ShowConstructionMaterial(clonk, structure);
|
|
|
|
clonk->CancelUse();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
private func ShowConstructionMaterial(object clonk, object structure)
|
|
|
|
{
|
|
|
|
var mat_msg = "Construction needs ";
|
|
|
|
var structure_id = structure->GetID();
|
|
|
|
var comp, index = 0;
|
|
|
|
while (comp = structure->GetComponent(nil, index))
|
|
|
|
{
|
|
|
|
var current_amount = structure->GetComponent(comp);
|
|
|
|
var max_amount = GetComponent(comp, nil, nil, structure_id);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private func Repair(object clonk, object structure)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Gives a list of ids of the players knowledge.
|
|
|
|
*/
|
|
|
|
public func GetConstructionPlans(int plr)
|
|
|
|
{
|
|
|
|
var construction_plans = [];
|
|
|
|
var construct_id, index = 0;
|
|
|
|
while (construct_id = GetPlrKnowledge(plr, 0, index++, C4D_Structure))
|
|
|
|
construction_plans[index-1] = construct_id;
|
|
|
|
return construction_plans;
|
|
|
|
}
|
|
|
|
|
2012-03-27 18:10:44 +00:00
|
|
|
/* Construction preview */
|
|
|
|
|
|
|
|
func ShowConstructionPreview(object clonk, id structure_id)
|
|
|
|
{
|
|
|
|
AddEffect("ControlConstructionPreview", clonk, 1, 0, this, nil, structure_id, clonk);
|
|
|
|
SetPlayerControlEnabled(clonk->GetOwner(), CON_Aim, true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
func FxControlConstructionPreviewStart(object clonk, effect, int temp, id structure_id, object clonk)
|
|
|
|
{
|
|
|
|
if (temp) return;
|
|
|
|
|
|
|
|
effect.structure = structure_id;
|
|
|
|
effect.preview = CreateObject(ConstructionPreviewer, AbsX(clonk->GetX()), AbsY(clonk->GetY()), clonk->GetOwner());
|
|
|
|
effect.preview->Set(structure_id, clonk);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Called by Control2Effect
|
|
|
|
func FxControlConstructionPreviewControl(object clonk, effect, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
|
|
|
{
|
|
|
|
if (ctrl != CON_Aim)
|
|
|
|
{
|
2012-03-28 17:39:00 +00:00
|
|
|
// CON_Use is accept
|
2012-03-27 18:10:44 +00:00
|
|
|
if (ctrl == CON_Use)
|
|
|
|
CreateConstructionSite(clonk, effect.structure, AbsX(effect.preview->GetX()), AbsY(effect.preview->GetY() + effect.preview.dimension_y/2));
|
2012-03-28 17:39:00 +00:00
|
|
|
// movement is allowed
|
|
|
|
else if(ctrl == CON_Left || ctrl == CON_Right || ctrl == CON_Up || ctrl == CON_Down || ctrl == CON_Jump)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
func FxControlConstructionPreviewStop(object target, effect, int reason, bool temp)
|
|
|
|
{
|
|
|
|
if (temp) return;
|
|
|
|
|
|
|
|
effect.preview->RemoveObject();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Construction */
|
|
|
|
|
|
|
|
func CreateConstructionSite(object clonk, id structure_id, int x, int y)
|
2012-01-02 02:14:57 +00:00
|
|
|
{
|
|
|
|
// Only when the clonk is standing and outdoors
|
|
|
|
if (clonk->GetAction() != "Walk")
|
|
|
|
return false;
|
|
|
|
if (clonk->Contained())
|
|
|
|
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;
|
2012-03-29 20:08:54 +00:00
|
|
|
|
|
|
|
// check for material
|
|
|
|
var comp, index = 0;
|
|
|
|
var found_material, mat, missing;
|
|
|
|
var r = Max(structure_id->GetDefWidth(), structure_id->GetDefHeight())/2 + 7;
|
|
|
|
var mat_msg = "Construction needs:"; //todo: stringtable
|
|
|
|
var missing = false;
|
|
|
|
found_material = CreateArray();
|
|
|
|
while (comp = GetComponent(nil, index, nil, structure_id))
|
|
|
|
{
|
|
|
|
// find material
|
|
|
|
found_material[index] = CreateArray();
|
|
|
|
var max_amount = GetComponent(comp, nil, nil, structure_id);
|
|
|
|
|
|
|
|
// 1. look for stuff in the clonk
|
|
|
|
found_material[index] = FindObjects(Find_ID(comp), Find_Container(clonk));
|
|
|
|
|
|
|
|
// 2. look for stuff lying around
|
|
|
|
if(GetLength(found_material[index]) < max_amount)
|
|
|
|
{
|
|
|
|
mat = clonk->FindObjects(Find_ID(comp), Find_NoContainer(), Find_Distance(r, x, y));
|
|
|
|
for(var o in mat)
|
|
|
|
PushBack(found_material[index], o);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 3. look for stuff in nearby lorries/containers
|
|
|
|
for(var cont in clonk->FindObjects(Find_Or(Find_Func("IsLorry"), Find_Func("IsContainer")), Find_Distance(r, x,y)))
|
|
|
|
if(GetLength(found_material[index]) < max_amount)
|
|
|
|
{
|
|
|
|
mat = FindObjects(Find_ID(comp), Find_Container(cont));
|
|
|
|
for(var o in mat)
|
|
|
|
PushBack(found_material[index], o);
|
|
|
|
}
|
|
|
|
|
|
|
|
// not enough?
|
|
|
|
var c = GetLength(found_material[index]);
|
|
|
|
if(c < max_amount)
|
|
|
|
{
|
|
|
|
mat_msg = Format("%s|%dx{{%i}}", mat_msg, max_amount-c, comp);
|
|
|
|
missing = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// not enough materials? :(
|
|
|
|
if(missing)
|
|
|
|
{
|
|
|
|
clonk->Message(mat_msg);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-01-02 02:14:57 +00:00
|
|
|
// Set owner for CreateConstruction
|
|
|
|
SetOwner(clonk->GetOwner());
|
|
|
|
// Create construction site
|
|
|
|
var site;
|
2012-03-27 18:10:44 +00:00
|
|
|
if (!(site = CreateConstruction(structure_id, x, y, Contained()->GetOwner(), 1, 1, 1)))
|
2012-01-02 02:14:57 +00:00
|
|
|
return false;
|
2012-03-29 20:08:54 +00:00
|
|
|
|
|
|
|
// pack material into the construction site
|
|
|
|
for(var mats in found_material)
|
|
|
|
{
|
|
|
|
var comp = mats[0]->GetID();
|
|
|
|
var max = GetComponent(comp,0,0,structure_id);
|
|
|
|
for(var j=0; j < max; ++j)
|
|
|
|
{
|
|
|
|
if(mats[j] == nil)
|
|
|
|
Log("PANICK"); // this should never happen
|
|
|
|
mats[j]->RemoveObject();
|
|
|
|
}
|
|
|
|
site->SetComponent(comp,max);
|
|
|
|
}
|
|
|
|
|
|
|
|
// todo: hammer-action for the clonk
|
|
|
|
Schedule(site, "DoCon(2)",1,50);
|
|
|
|
|
2012-01-02 02:14:57 +00:00
|
|
|
// Message
|
|
|
|
clonk->Message("$TxtConstructions$", site->GetName());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|