forked from Mirrors/openclonk
Improve PlayerStart initial material setting to allow specification of weapon ammo, stackable stack count and liquid contents
parent
ba371db0e6
commit
3330c592e3
|
@ -34,7 +34,7 @@ public func Definition(def)
|
|||
{ Name="$Specific$", Value={ Option="idlist", Data=[] }, ValueKey="Data", Delegate=EditorBase.IDSet },
|
||||
] };
|
||||
def.EditorProps.starting_crew = EditorBase->GetConditionalIDList("IsClonk", "$Crew$", Clonk);
|
||||
def.EditorProps.starting_material = EditorBase->GetConditionalIDList("Collectible", "$StartingMaterial$", nil, "$StartingMaterialHelp$");
|
||||
def.EditorProps.starting_material = new EditorBase.ItemPlusParameterList { Name="$StartingMaterial$", EditorHelp="$StartingMaterialHelp$" };
|
||||
def.EditorProps.starting_wealth = { Name="$Wealth$", Type="int", Min=0 };
|
||||
def.EditorProps.clonk_max_contents_count = { Name="$ClonkMaxContentsCount$", EditorHelp="$ClonkMaxContentsCountHelp$", Type="enum", Options = [
|
||||
{ Name=Format("$Default$ (%d)", Clonk.MaxContentsCount) }, { Name="$Custom$", Value=Clonk.MaxContentsCount, Delegate={ Type="int", Min=0, Max=10 } } ] };
|
||||
|
@ -43,13 +43,13 @@ public func Definition(def)
|
|||
def.EditorProps.respawn_material = { Name="$RespawnMaterial$", Type="enum", Set="SetRespawnMaterial", Save="RespawnMaterial", Options = [
|
||||
{ Name="$None$" },
|
||||
{ Name="$SameAsStartingMaterial$", Value="starting_material" },
|
||||
{ Name="$Custom$", Value=[], Type=C4V_Array, Delegate=EditorBase->GetConditionalIDList("Collectible", "$RespawnMaterial$", nil, "$RespawnMaterialHelp$") },
|
||||
{ Name="$Custom$", Value=[], Type=C4V_Array, Delegate=new EditorBase.ItemPlusParameterList { Name="$RespawnMaterial$", EditorHelp="$RespawnMaterialHelp$" } },
|
||||
] };
|
||||
return true;
|
||||
}
|
||||
|
||||
public func GetDefaultCrew() { return [{id=Clonk, count=1}]; }
|
||||
public func GetDefaultMaterial() { return [{id=Shovel, count=1}, {id=Hammer, count=1}, {id=Axe, count=1}]; }
|
||||
public func GetDefaultMaterial() { return [Shovel, Hammer, Axe]; }
|
||||
|
||||
public func Initialize()
|
||||
{
|
||||
|
@ -88,7 +88,19 @@ public func SetStartingCrew(array new_crew)
|
|||
|
||||
public func SetStartingMaterial(array new_material)
|
||||
{
|
||||
starting_material = new_material;
|
||||
// ID+count conversion (old style)
|
||||
if (new_material && GetLength(new_material) && new_material[0].id && new_material[0].count && !new_material[0]->~GetName())
|
||||
{
|
||||
starting_material = [];
|
||||
var n = 0;
|
||||
for (var idlist_entry in new_material)
|
||||
for (var i = 0; i < idlist_entry.count; ++i)
|
||||
starting_material[n++] = idlist_entry.id;
|
||||
}
|
||||
else
|
||||
{
|
||||
starting_material = new_material;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -257,27 +269,26 @@ private func InitializeMaterial(int plr)
|
|||
// Spread material across clonks. Try to fill them evenly and avoid giving the same item twice to the same clonk
|
||||
// So e.g. each clonk can get one shovel
|
||||
for (var idlist_entry in starting_material)
|
||||
for (var i=0; i<idlist_entry.count; ++i)
|
||||
{
|
||||
var best_target = nil, target_score, id = idlist_entry.id, clonk;
|
||||
var obj = CreateObjectAbove(id, 0,GetDefHeight()/2, plr);
|
||||
if (!obj || !obj.Collectible) continue;
|
||||
for (var j=0; j<GetCrewCount(plr); ++j)
|
||||
if (clonk = GetCrew(plr, j))
|
||||
{
|
||||
var best_target = nil, target_score, id = idlist_entry.id, clonk;
|
||||
var obj = EditorBase->CreateItemPlusParameter(idlist_entry, GetX(),GetY()+GetDefHeight()/2, plr);
|
||||
if (!obj || !obj.Collectible) continue;
|
||||
for (var j=0; j<GetCrewCount(plr); ++j)
|
||||
if (clonk = GetCrew(plr, j))
|
||||
{
|
||||
var clonk_score = 0;
|
||||
// High penalty: Already has item of same type
|
||||
clonk_score += clonk->ContentsCount(id)*1000;
|
||||
// Low penalty: Already has items
|
||||
clonk_score += clonk->ContentsCount();
|
||||
if (!best_target || clonk_score < target_score)
|
||||
{
|
||||
var clonk_score = 0;
|
||||
// High penalty: Already has item of same type
|
||||
clonk_score += clonk->ContentsCount(id)*1000;
|
||||
// Low penalty: Already has items
|
||||
clonk_score += clonk->ContentsCount();
|
||||
if (!best_target || clonk_score < target_score)
|
||||
{
|
||||
best_target = clonk;
|
||||
target_score = clonk_score;
|
||||
}
|
||||
best_target = clonk;
|
||||
target_score = clonk_score;
|
||||
}
|
||||
if (best_target) best_target->Collect(obj); // May fail due to contents full
|
||||
}
|
||||
}
|
||||
if (best_target) best_target->Collect(obj); // May fail due to contents full
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ local EditorProps;
|
|||
local Plane = 1;
|
||||
|
||||
local CountedID, IDList, AnyDef, IDSet, PlayerNumber, TeamID, PlayerMask;
|
||||
local ItemPlusParameter, ItemPlusParameterOptionMap;
|
||||
local ItemPlusParameterList;
|
||||
|
||||
local DefinitionPriority=100; // Call this definition early to allow EditorProp initialization
|
||||
func Definition(def)
|
||||
|
@ -37,6 +39,84 @@ func Definition(def)
|
|||
{ Name="$Specific$", Value={ Option="number" }, ValueKey="Data", Delegate=PlayerNumber },
|
||||
{ Name="$Team$", Value={ Option="team" }, ValueKey="Data", Delegate=TeamID },
|
||||
] };
|
||||
// Item plus extra stuff (contents, stack, etc.)
|
||||
ItemPlusParameterOptionMap = {};
|
||||
ItemPlusParameter = { Name="$Item", Type="enum", Sorted=true, Options = [ { Name="$Nothing$", Priority=50 } ] };
|
||||
var itemdef, i = 0, n = 0, option, contents_def, j, n2, contents_defs, mat;
|
||||
while ((itemdef = GetDefinition(i++)))
|
||||
if (itemdef.Collectible || itemdef->~GetLiquidType())
|
||||
{
|
||||
var group = itemdef->GetDefinitionGroupPath();
|
||||
if (WildcardMatch(group, "Objects/Items/*"))
|
||||
group = ReplaceString(group, "Objects/Items/", ""); // Shortcut this group since most items will be here
|
||||
else
|
||||
group = "$Other$";
|
||||
option = { Name=itemdef->GetName(), Group=group, Value=itemdef };
|
||||
var def_id = Format("%i", itemdef);
|
||||
ItemPlusParameterOptionMap[def_id] = option;
|
||||
// Test various kinds of extra parameters for new items
|
||||
if (itemdef->~IsLiquidContainer() && itemdef->~GetLiquidContainerMaxFillLevel())
|
||||
{
|
||||
// Liquid container: Offer to fill with liquid
|
||||
j = 0; n2 = 0;
|
||||
contents_defs = [{Name="$Nothing$"}];
|
||||
while ((contents_def = GetDefinition(j++)))
|
||||
if ((mat = contents_def->~GetLiquidType()))
|
||||
if (itemdef->IsLiquidContainerForMaterial(mat))
|
||||
contents_defs[++n2] = contents_def;
|
||||
if (n2)
|
||||
{
|
||||
option.Value = { ItemPlusParameter="liquid", ID=itemdef };
|
||||
option.OptionKey = "ID";
|
||||
option.ValueKey = "Liquid";
|
||||
option.Delegate = { Name="$Liquid$", Type="enum", Sorted=true, Options=contents_defs }; // Options resolved later uisng ItemPlusParameterOptionMap
|
||||
}
|
||||
}
|
||||
else if (itemdef.ExtraSlotFilter)
|
||||
{
|
||||
// Extra slot objects: Offer contents
|
||||
j = 0; n2 = 0;
|
||||
contents_defs = [{Name="$Nothing$"}];
|
||||
while ((contents_def = GetDefinition(j++)))
|
||||
if (contents_def[itemdef.ExtraSlotFilter])
|
||||
if (contents_def->Call(itemdef.ExtraSlotFilter))
|
||||
contents_defs[++n2] = contents_def;
|
||||
if (n2)
|
||||
{
|
||||
option.Value = { ItemPlusParameter="contents", ID=itemdef };
|
||||
option.OptionKey = "ID";
|
||||
option.ValueKey = "Contents";
|
||||
option.Delegate = { Name="$Contents$", Type="enum", Sorted=true, Options=contents_defs }; // Options resolved later uisng ItemPlusParameterOptionMap
|
||||
}
|
||||
}
|
||||
else if (itemdef->~IsStackable())
|
||||
{
|
||||
// Stackable: Offer stack count
|
||||
option.Value = { ItemPlusParameter="stack", ID=itemdef };
|
||||
option.OptionKey = "ID";
|
||||
option.ValueKey = "StackCount";
|
||||
option.Delegate = { Name="$Contents$", Type="enum", Options=[
|
||||
{ Name=Format("$DefaultStack$", itemdef->InitialStackCount()) },
|
||||
{ Name="$CustomStack$", Type=C4V_Int, Value=itemdef->InitialStackCount(), Delegate={ Type="int", Min=1/*, Max=itemdef->MaxStackCount()*/ } }, // there's no reason to restrict the max stack in editor
|
||||
{ Name="$InfiniteStack$", Value="infinite" }
|
||||
]};
|
||||
}
|
||||
// Add to item list if it's an item
|
||||
// Do not add liquids; they're just processed here to get the stackable definition
|
||||
if (itemdef.Collectible) ItemPlusParameter.Options[++n] = option;
|
||||
}
|
||||
// Link item contents parameter menus, but ignore group because it's usually a low number of items anyway
|
||||
for (option in ItemPlusParameter.Options)
|
||||
if (option.ValueKey == "Contents" || option.ValueKey == "Liquid")
|
||||
for (i = 1; i < GetLength(option.Delegate.Options); ++i)
|
||||
{
|
||||
var option_item = ItemPlusParameterOptionMap[Format("%i", option.Delegate.Options[i])] ?? option.Delegate.Options[i];
|
||||
if (option_item.Prototype == Global)
|
||||
option.Delegate.Options[i] = { Name=option_item->GetName(), Value=option_item }; // Regular definition
|
||||
else
|
||||
option.Delegate.Options[i] = new option_item { Group=nil }; // Definition with extra parameter
|
||||
}
|
||||
ItemPlusParameterList = { Name = "$ItemPlusParameterList$", Type = "array", Display = 3, Elements = ItemPlusParameter };
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -73,3 +153,50 @@ public func GetConditionalIDList(string condition, string name, proplist default
|
|||
id = { Type = "def", Filter=condition } } };
|
||||
return { Name = name, Type = "array", Display = 3, DefaultValue = { count=1, id=default_id }, Elements = counted_id, EditorHelp = help };
|
||||
}
|
||||
|
||||
// Create item specieid in ItemsPlusParameters delegate
|
||||
public func CreateItemPlusParameter(proplist param, int x, int y, int owner)
|
||||
{
|
||||
if (!param) return nil;
|
||||
var id;
|
||||
if (param.ItemPlusParameter) id = param.ID; else id = param;
|
||||
var obj = CreateObject(id, x, y, owner);
|
||||
return ApplyContentsPlusParameter(param, obj);
|
||||
}
|
||||
|
||||
public func CreateContentsPlusParameter(proplist param, object container)
|
||||
{
|
||||
if (!param || !container) return nil;
|
||||
var id;
|
||||
if (param.ItemPlusParameter) id = param.ID; else id = param;
|
||||
var obj = container->CreateContents(id);
|
||||
return ApplyContentsPlusParameter(param, obj);
|
||||
}
|
||||
|
||||
private func ApplyContentsPlusParameter(proplist param, object to_obj)
|
||||
{
|
||||
// Apply object contents or stack count setting
|
||||
if (to_obj && param.ItemPlusParameter)
|
||||
{
|
||||
if (param.ItemPlusParameter == "liquid")
|
||||
{
|
||||
CreateContentsPlusParameter(param.Liquid, to_obj);
|
||||
}
|
||||
else if (param.ItemPlusParameter == "contents")
|
||||
{
|
||||
CreateContentsPlusParameter(param.Contents, to_obj);
|
||||
}
|
||||
else if (param.ItemPlusParameter == "stack" && GetType(param.StackCount))
|
||||
{
|
||||
if (param.StackCount == "infinite")
|
||||
{
|
||||
to_obj->SetInfiniteStackCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
to_obj->SetStackCount(param.StackCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return to_obj;
|
||||
}
|
||||
|
|
|
@ -20,3 +20,11 @@ ClrModulationHelp=Faktor um den das Objekt verdunkelt wird.
|
|||
Name=Name
|
||||
Unknown=Unbekannt
|
||||
EditorVisible=Nur im Editor
|
||||
Contents=Inhalt
|
||||
DefaultStack=x%d (Standard)
|
||||
CustomStack=Menge...
|
||||
InfiniteStack=Unendlich
|
||||
ItemPlusParameterList=Gegenstaende
|
||||
Other=Sonstige
|
||||
Nothing=Nichts
|
||||
Liquid=Fluessigkeit
|
||||
|
|
|
@ -20,3 +20,11 @@ ClrModulationHelp=Factor by which an object is darkened.
|
|||
Name=Name
|
||||
Unknown=Unknown
|
||||
EditorVisible=Only in editor
|
||||
Contents=Contents
|
||||
DefaultStack=x%d (Default)
|
||||
CustomStack=Amount...
|
||||
InfiniteStack=Infinite
|
||||
ItemPlusParameterList=Items
|
||||
Other=Miscellaneous
|
||||
Nothing=Nothing
|
||||
Liquid=Liquid
|
||||
|
|
|
@ -168,4 +168,5 @@ local Name = "$Name$";
|
|||
local Description = "$Description$";
|
||||
local Collectible = true;
|
||||
local ForceFreeHands = true;
|
||||
local Components = {Wood = 1, Metal = 1};
|
||||
local Components = {Wood = 1, Metal = 1};
|
||||
local ExtraSlotFilter = "IsBucketMaterial";
|
||||
|
|
|
@ -237,4 +237,6 @@ local ForceFreeHands = true;
|
|||
local Components = {Wood = 1, Metal = 2};
|
||||
|
||||
local BulletsPerShot = 5;
|
||||
local BulletSpread = 300;
|
||||
local BulletSpread = 300;
|
||||
|
||||
local ExtraSlotFilter = "IsBullet"; // For editor-provided ammo list
|
||||
|
|
|
@ -240,4 +240,6 @@ local ContactIncinerate = 5;
|
|||
local ForceFreeHands = true;
|
||||
local Components = {Wood = 3};
|
||||
// Initial velocity of the arrow
|
||||
local shooting_strength = 100;
|
||||
local shooting_strength = 100;
|
||||
|
||||
local ExtraSlotFilter = "IsArrow"; // For editor-provided ammo list
|
||||
|
|
|
@ -254,4 +254,5 @@ local Collectible = true;
|
|||
local ForceFreeHands = true;
|
||||
local Components = {Wood = 1, Metal = 3};
|
||||
// Initial velocity of the bomb
|
||||
local shooting_strength = 75;
|
||||
local shooting_strength = 75;
|
||||
local ExtraSlotFilter = "IsGrenadeLauncherAmmo"; // For editor-provided ammo list
|
||||
|
|
|
@ -94,7 +94,7 @@ Inserts liquid into the container.
|
|||
@param amount: Max amount of material being inserted.
|
||||
Passing a nil parameter will fill the
|
||||
container to its maximum.
|
||||
@param source: Object which inserts the liquid
|
||||
@param source: Object which inserts the liquid [optional]
|
||||
@return returned_amount: The inserted amount
|
||||
*/
|
||||
func PutLiquid(liquid_name, int amount, object source)
|
||||
|
|
Loading…
Reference in New Issue