1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
/**
Surrounding
Enables you to pick up objects from your surrounding.
@author Zapper
*/
// Search for new objects only once per frame.
local last_search_frame;
local current_objects;
// Overload contents callback for the interaction menu.
public func Contents(int index)
{
RefreshIfNecessary();
if (index < 0 || index >= GetLength(current_objects)) return nil;
return current_objects[index];
}
public func ContentsCount(id definition)
{
RefreshIfNecessary();
if (definition == nil)
{
return GetLength(current_objects);
}
else
{
var count = 0;
for (var index = 0; index < GetLength(current_objects); ++index)
if (current_objects[index] && current_objects[index]->GetID() == definition)
{
count += 1;
}
return count;
}
}
private func RefreshIfNecessary()
{
if (last_search_frame != FrameCounter())
{
current_objects = GetPossibleObjects();
last_search_frame = FrameCounter();
}
}
private func GetPossibleObjects(id limit_definition)
{
var sort = nil, check_id = nil;
if (limit_definition != nil)
{
sort = Sort_Distance();
check_id = Find_ID(limit_definition);
}
return FindObjects(Find_Distance(Radius), Find_NoContainer(), Find_Property("Collectible"), Find_Layer(GetActionTarget()->GetObjectLayer()), check_id, sort);
}
// Find first contents object of type. Used by interaction menu.
public func FindContents(id idcont)
{
var objs = GetPossibleObjects(idcont);
if (!GetLength(objs)) return nil;
return objs[0];
}
// Called by the Clonk when an interaction menu is opened.
public func InitFor(object clonk, object menu)
{
SetAction("Attach", clonk);
SetOwner(clonk->GetOwner());
this.Visibility = VIS_Owner;
// The effects will remove this object once the interaction menu is closed.
AddEffect("KeepAlive", menu, 1, 0, this);
}
// You can transfer items to the environment, which will then be placed on the ground.
public func Collection2(object obj)
{
var clonk = GetActionTarget();
obj->Exit(0, clonk->GetDefBottom() - clonk->GetY());
OnDropped(clonk, obj);
}
// When the item is moved into this object via script, we don't even have to collect it in the first place.
public func Collect(object obj)
{
var clonk = GetActionTarget();
var container = obj->Contained();
if (container)
{
// Special treatment for objects that the Clonk holds. Just use the appropriate library function.
if (container->~IsClonk() && !obj->~IsCarryHeavy())
{
container->DropInventoryItem(container->GetItemPos(obj));
}
else
{
// Otherwise, just force-drop it at the clonks's bottom.
obj->Exit();
obj->SetPosition(clonk->GetX(), clonk->GetDefBottom() - obj->GetDefHeight() - obj->GetDefOffset(1));
OnDropped(clonk, obj);
}
}
else
{
obj->SetPosition(clonk->GetX(), clonk->GetDefBottom() - obj->GetDefHeight() - obj->GetDefOffset(1));
OnDropped(clonk, obj);
}
return true;
}
private func OnDropped(object clonk, object obj)
{
// Make the Clonk not directly re-collect the object;
clonk->~OnDropped(obj);
}
public func AttachTargetLost()
{
RemoveObject();
}
private func FxKeepAliveStop(object target, proplist effect, int reason, int temp)
{
if (temp) return;
RemoveObject();
}
public func IsObjectContained(object obj)
{
// Callback from menu if obj is still "in" this container
// Since we're hacking our contents, just do the distance check
return (obj && !obj->Contained() && ObjectDistance(obj) <= this.Radius);
}
private func GetSurroundingMessageObjects(clonk)
{
return FindObjects(Find_Distance(Radius), Find_NoContainer(), Find_Exclude(clonk), Find_Func("GetSurroundingEntryMessage", clonk), Find_Layer(clonk->GetObjectLayer()), Sort_Distance());
}
private func AddSurroundingObjectMessages(object clonk)
{
var message_objects = GetSurroundingMessageObjects(clonk);
var menu_entries = [], i=0;
for (var obj in message_objects)
{
var entry = {Symbol = Clonk, Bottom = "2em",
custom =
{
Right = "100%", Bottom = "2em",
Bottom = "1.2em",
Priority = i,
BackgroundColor = 0x80804040,
image = {Right = "2em", Symbol = obj},
text = {Left = "2em", Text = obj->GetSurroundingEntryMessage(clonk) }
}};
menu_entries[i++] = entry;
}
return menu_entries;
}
public func GetInteractionMenus(object clonk)
{
if (!GetLength(GetSurroundingMessageObjects(clonk))) return nil;
return [{
entries_callback = this.AddSurroundingObjectMessages,
BackgroundColor = 0x705050,
Priority = 100 // high priority items are actually at the bottom
}];
}
public func IsContainer() { return true; }
local Name = "$Name$";
local Description = "$Description$";
local Plane = 1;
local Radius = 20;
local ActMap =
{
Attach =
{
Prototype = Action,
Name="Attach",
Procedure=DFA_ATTACH,
NextAction="Hold",
Length=1,
FacetBase=1,
AbortCall = "AttachTargetLost"
}
};
|