/** 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? // TODO: check for multiple objects var structure = FindObject(Find_Category(C4D_Structure), Find_Or(Find_Distance(20), Find_AtPoint()), Find_Layer(GetObjectLayer())); if (structure) { if (structure->GetDamage() > 0) { Repair(clonk, structure); return true; } } // Otherwise create a menu with possible structures to build. clonk->CreateConstructionMenu(this, true); 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) { if (structure->GetDamage() > 0) { Repair(clonk, structure); return true; } } clonk->CancelUse(); return true; } private func ShowConstructionMaterial(object clonk, object structure) { var mat_msg = "$TxtNeeds$"; 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); index++; } clonk->Message(mat_msg); 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, nil, index++, C4D_Structure)) construction_plans[index-1] = construct_id; return construction_plans; } /* 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.flipable = !structure_id->~NoConstructionFlip(); effect.preview = structure_id->~CreateConstructionPreview(clonk); if (!effect.preview) 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) { // CON_Use is accept if (ctrl == CON_Use) CreateConstructionSite(clonk, effect.structure, AbsX(effect.preview->GetX()), AbsY(effect.preview->GetY() + effect.preview.dimension_y/2), effect.preview.direction, effect.preview.stick_to); // movement is allowed else if (IsMovementControl(ctrl)) return false; // Flipping // 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.) else if (IsInteractionControl(ctrl)) { if (release) effect.preview->Flip(); return true; } // everything else declines RemoveEffect("ControlConstructionPreview", clonk, effect); return true; } effect.preview->Reposition(x, y); return true; } func FxControlConstructionPreviewStop(object clonk, effect, int reason, bool temp) { if (temp) return; effect.preview->RemoveObject(); SetPlayerControlEnabled(clonk->GetOwner(), CON_Aim, false); } /* Construction */ func CreateConstructionSite(object clonk, id structure_id, int x, int y, int dir, object stick_to) { // 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 if (structure_id->~RejectConstruction(x, y, clonk)) return false; if (!CheckConstructionSite(structure_id, x, y)) { CustomMessage("$TxtNoSiteHere$", this, clonk->GetOwner(), nil,nil, RGB(255,0,0)); // todo: stringtable return false; } // intersection-check with all other construction sites... bah for(var other_site in FindObjects(Find_ID(ConstructionSite))) { if(!(other_site->GetLeftEdge() > GetX()+x+structure_id->GetDefWidth()/2 || 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 )) { CustomMessage(Format("$TxtBlocked$",other_site->GetName()), this, clonk->GetOwner(), nil,nil, RGB(255,0,0)); // todo: stringtable return false; } } // Set owner for CreateConstruction SetOwner(clonk->GetOwner()); // Create construction site var site; site = CreateObject(ConstructionSite, x, y, Contained()->GetOwner()); // Randomize sign rotation 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)); site -> Set(structure_id, dir, stick_to); //if(!(site = CreateConstruction(structure_id, x, y, Contained()->GetOwner(), 1, 1, 1))) //return false; // check for material var comp, index = 0; var mat; var w = structure_id->GetDefWidth()+10; var h = structure_id->GetDefHeight()+10; while (comp = GetComponent(nil, index, nil, structure_id)) { // find material var count_needed = GetComponent(comp, nil, nil, structure_id); index++; mat = CreateArray(); // 1. look for stuff in the clonk mat[0] = FindObjects(Find_ID(comp), Find_Container(clonk)); // 2. look for stuff lying around mat[1] = clonk->FindObjects(Find_ID(comp), Find_NoContainer(), Find_InRect(-w/2, -h/2, w,h)); // 3. look for stuff in nearby lorries/containers var i = 2; for(var cont in clonk->FindObjects(Find_Or(Find_Func("IsLorry"), Find_Func("IsContainer")), Find_InRect(-w/2, -h/2, w,h))) mat[i] = FindObjects(Find_ID(comp), Find_Container(cont)); // move it for(var mat2 in mat) { for(var o in mat2) { if(count_needed <= 0) break; o->Exit(); o->Enter(site); count_needed--; } } } // Message clonk->Message("$TxtConstructions$", structure_id->GetName()); return true; }