collect objects solely via CTRL now

The player can also choose which object to collect by holding CTRL and navigating left/right.
Controls
David Dormagen 2015-08-30 20:39:50 +02:00
parent d1ceafea16
commit e9a69c4252
6 changed files with 251 additions and 42 deletions

View File

@ -23,54 +23,20 @@ func Construction()
return _inherited(...);
}
// Called by other libraries and objects when the Clonk has forcefully dropped (not thrown) an object. Collection will be disabled for some time.
// Called by other libraries and objects when the Clonk has forcefully dropped (not thrown) an object.
func OnDropped(object obj)
{
// An object has just left this one. Make sure we don't immediately collect it again.
// Note that this can also happen for objects which were not originally contained in this one but in a subcontainer (f.e. items in HasExtraSlot objects).
AddEffect("NoCollectDelay", this, 1, 36 * 1, this, nil, obj, GetX(), GetY());
return _inherited(obj, ...);
}
func FxNoCollectDelayStart(object target, proplist effect, temp, object item, int x, int y)
{
if (temp) return;
effect.x = x;
effect.y = y;
effect.item = item;
}
func FxNoCollectDelayTimer(object target, proplist effect, int time)
{
if (!effect.item) return -1;
if (ObjectDistance(this, effect.item) > 20) return -1;
return 1;
}
// Checks if we just dropped the object and thus can not collect it again.
func HadJustDroppedObject(object obj)
{
var current_x = GetX(), current_y = GetY();
var i = 0, e = nil;
while (e = GetEffect("NoCollectDelay", this, i++))
{
if (e.item == obj) return true;
}
return false;
}
func RejectCollect(id objid, object obj)
{
var rejected = _inherited(objid,obj,...);
var rejected = _inherited(objid, obj, ...);
if(rejected) return rejected;
// check if the hand slot is full.
// If the overloaded Collect() is called, this check will be skipped.
// Also handle collection of contained objects (chests, other Clonks) more relaxed.
if (!this.inventory.force_collection && !obj->Contained())
if (this->GetHandItem(0) || HadJustDroppedObject(obj))
return true;
// Allow collection only if called via clonk->Collect, to prevent picking up stuff on the ground.
// Make an exception for containers, though.
if (!this.inventory.force_collection && !obj->Contained()) return true;
return false;
}
@ -91,6 +57,46 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
return true;
}
// Begin picking up objects.
if (ctrl == CON_PickUp && !release)
{
BeginPickingUp();
return true;
}
// Switching pickup object or finish pickup?
if (this.inventory.is_picking_up)
{
// Stop picking up.
if (ctrl == CON_PickUpNext_Stop)
{
this.inventory.pickup_item = nil;
EndPickingUp();
return true;
}
// Finish picking up (aka "collect").
if (ctrl == CON_PickUp && release)
{
EndPickingUp();
return true;
}
// Switch left/right through objects.
var dir = nil;
if (ctrl == CON_PickUpNext_Left) dir = -1;
else if (ctrl == CON_PickUpNext_Right) dir = 1;
if (dir != nil)
{
var item = FindNextPickupObject(this.inventory.pickup_item, dir);
if (item)
SetNextPickupItem(item);
return true;
}
}
// shift inventory
var inventory_shift = 0;
if (ctrl == CON_InventoryShiftForward) inventory_shift = 1;
@ -149,6 +155,151 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);
}
private func FxIntHighlightItemStart(object target, effect fx, temp, object item)
{
if (temp) return;
fx.item = item;
fx.dummy = CreateObject(Dummy, item->GetX() - GetX(), item->GetY() - GetY(), GetOwner());
fx.dummy.ActMap =
{
Attach =
{
Name = "Attach",
Procedure = DFA_ATTACH,
FaceBase = 1
}
};
fx.dummy.Visibility = VIS_Owner;
fx.dummy.Plane = item.Plane + 1;
fx.dummy->Message("@%s", item->GetName());
// Center dummy!
fx.dummy->SetVertexXY(0, item->GetVertex(0, VTX_X), item->GetVertex(0, VTX_Y));
fx.dummy->SetAction("Attach", item);
fx.width = item->GetDefWidth();
fx.height = item->GetDefHeight();
var particle =
{
Prototype = Particles_Flash(),
Size = Max(fx.width, fx.height),
Attach = ATTACH_Front
};
fx.dummy->CreateParticle("SphereSpark", 0, 0, 0, 0, 20, particle, 1);
// And smaller sparks during the effect.
fx.particles =
{
Prototype = particle,
Size = PV_Linear(2, 0),
Rotation = PV_Random(360),
Stretch = PV_Linear(0, 4000),
};
fx.width /= 2;
fx.height /= 2;
}
private func FxIntHighlightItemTimer(object target, effect fx, int time)
{
if (!fx.dummy) return -1;
if (!fx.item) return -1;
if (ObjectDistance(this, fx.item) > 20) return -1;
if (Contained(fx.item)) return -1;
fx.dummy->CreateParticle("StarSpark", PV_Random(-fx.width, fx.width), PV_Random(-fx.height, fx.height), 0, 0, 10, fx.particles, 2);
}
private func FxIntHighlightItemStop(object target, effect fx, int reason, temp)
{
if (temp) return;
if (fx.dummy) fx.dummy->RemoveObject();
if (!this) return;
if (fx.item == this.inventory.pickup_item)
this.inventory.pickup_item = nil;
}
private func SetNextPickupItem(object to)
{
// Clear all old markers.
var e = nil;
while (e = GetEffect("IntHighlightItem", this))
RemoveEffect(nil, this, e);
// And set & mark new one.
this.inventory.pickup_item = to;
if (to)
AddEffect("IntHighlightItem", this, 1, 2, this, nil, to);
}
private func FindNextPickupObject(object start_from, int x_dir)
{
if (!start_from) start_from = this;
var sort = Sort_Func("Library_ClonkInventoryControl_Sort_Priority", start_from->GetX());
var objects = FindObjects(Find_Distance(20), Find_Category(C4D_Object), Find_NoContainer(), Find_Func("GetProperty", "Collectible"), sort);
var len = GetLength(objects);
// Find object next to the current one.
var index = GetIndexOf(objects, start_from);
if (index != nil)
{
index = index + x_dir;
if (index < 0) index += len;
index = index % len;
}
else index = 0;
if (index >= len) return nil;
var next = objects[index];
if (next == start_from) return nil;
return next;
}
private func BeginPickingUp()
{
this.inventory.is_picking_up = true;
var dir = -1;
if (GetDir() == DIR_Right) dir = 1;
var obj = FindNextPickupObject(this, dir);
if (obj)
SetNextPickupItem(obj);
}
private func EndPickingUp()
{
this.inventory.is_picking_up = false;
if (this.inventory.pickup_item)
{
// Remember stuff for a possible message - the item might have removed itself later.
var item = this.inventory.pickup_item;
var x = item->GetX();
var y = item->GetY();
var name = item->GetName();
// Try to collect the item.
Collect(item);
// If anything happened, assume collection.
if (!item || item->Contained())
{
var message = CreateObject(FloatingMessage, AbsX(x), AbsY(y), GetOwner());
message.Visibility = VIS_Owner;
message->SetMessage(name);
message->SetYDir(-10);
message->FadeOut(1, 20);
}
}
var e = nil;
while (e = GetEffect("IntHighlightItem", this))
{
RemoveEffect(nil, this, e);
}
this.inventory.pickup_item = nil;
}
// used in Inventory.ocd
public func SetHandItemPos(int hand, int inv)
{

View File

@ -445,7 +445,7 @@ protected func RejectCollect(id objid, object obj)
if(GetEffect("NoCollection", obj)) return true;
// Only handle extra-slot objects if the object was not dropped on purpose.
if (this.inventory.force_collection || !this->HadJustDroppedObject(obj))
if (this.inventory.force_collection)
{
// try to stuff obj into an object with an extra slot
for(var i=0; Contents(i); ++i)

View File

@ -519,3 +519,15 @@ global func MouseDragDrop(int plr, object source, object target)
Log("%s%d, %s, %i, %d, %d, %d, %v, %v", rs, plr, GetPlayerControlName(ctrl), spec_id, x,y,strength, repeat, release);
return r;
}*/
/*
This is used by Library_ClonkInventoryControl and needs to be a global function (in a non-appendto).
This function returns the priority of an object when selecting an object to pick up.
*/
global func Library_ClonkInventoryControl_Sort_Priority(int x_position)
{
// Objects are sorted by position, preferring the direction of the key press.
var priority_x = GetX() - x_position;
if (priority_x < 0) priority_x += 1000;
return priority_x;
}

View File

@ -162,7 +162,26 @@
GUIName=$CON_Drop$
GUIDesc=$CON_Drop_Desc$
Hold=1
# Picking up objects on the ground.
[ControlDef]
Identifier=PickUp
GUIName=$CON_PickUp$
GUIDesc=$CON_PickUp_Desc$
Hold=1
[ControlDef]
Identifier=PickUpNext_Left
GUIName=None
[ControlDef]
Identifier=PickUpNext_Right
GUIName=None
[ControlDef]
Identifier=PickUpNext_Stop
GUIName=None
# Hotkeys (Inventory)
[ControlDef]
@ -566,13 +585,34 @@
[Assignment]
Key=E
Control=Contents
Group=1
GUIGroup=1
[Assignment]
Key=Q
Control=QuickSwitch
GUIGroup=50
[Assignment]
Key=Ctrl+LeftControl
Control=PickUp
GUIGroup=50
[Assignment]
Key=Ctrl+CON_Left
Control=PickUpNext_Left
[Assignment]
Key=Ctrl+CON_Right
Control=PickUpNext_Right
[Assignment]
Key=Ctrl+CON_Up
Control=PickUpNext_Stop
[Assignment]
Key=Ctrl+CON_Down
Control=PickUpNext_Stop
[Assignment]
Key=Mouse1Wheel1Up
GUIGroup=50

View File

@ -30,6 +30,9 @@ CON_Throw_Desc=Werfen des Gegenstandes in der Hand in die anvisierte Richtung.
CON_UseAlt=Use
CON_UseAlt_Desc=Use the item in the hand alternatively.
CON_PickUp=Aufheben
CON_PickUp_Desc=Hebt ein Objekt in der Nähe auf.
CON_Hotkey1=Hotkey 1
CON_Hotkey2=Hotkey 2
CON_Hotkey3=Hotkey 3

View File

@ -31,6 +31,9 @@ CON_Throw_Desc=Throw the item in the hand into the aimed direction.
CON_UseAlt=Use
CON_UseAlt_Desc=Use the item in the hand alternatively.
CON_PickUp=Pick Up
CON_PickUp_Desc=Pick up an object near you.
CON_Hotkey1=Hotkey 1
CON_Hotkey2=Hotkey 2
CON_Hotkey3=Hotkey 3