FightForGidl: Minor fixes and buy menu rework.

* New menu to be expanded with cool stuff (like damage upgrades, towers, etc.) later
* Automatic rebuy of consumables such as iron bombs and firestones
shapetextures
Sven Eberhardt 2015-11-22 01:03:15 -05:00
parent 6e4c7a2c2d
commit 08b3584c5d
18 changed files with 725 additions and 68 deletions

View File

@ -0,0 +1,4 @@
[DefCore]
id=GUI_BuyMenu
Version=7,0
Category=C4D_StaticBack

View File

@ -0,0 +1,204 @@
/**
Buy Menu
Shows icons to instantly buy+equip weapons
@authors Sven2
*/
local menu; // the actual menu (a MenuStyle_Grid)
local homebase; // associated base
local buymenu_toggle_id; // button to toggle menu visibility
/* Creation / Destruction */
public func Construction(...)
{
// The menu. Cannot inherit from MenuStyle_Grid, because at the moment the menu host
// is the object itself. Therefore, child elements such as the buy menu would become
// invisible if the menu closes. So just create an extra object for now.
menu = CreateObject(MenuStyle_Grid, 0,0, GetOwner());
menu->SetPermanent(true);
menu.Style |= GUI_Multiple;
menu.Player = nil; // by visibility
menu.Visibility = VIS_None; // default off - enable through button.
menu.Left = "100% - 12em";
menu.Top = "4em";
menu.Right = "100% - 4em";
menu.Bottom = "90% - 12em";
menu.BackgroundColor = 0x20000000;
// Create button to show/hide menu
CreateToggleVisibilityButton();
return true;
}
public func Destruction(...)
{
DestroyToggleVisibilityButton();
return true;
}
public func SetHomebase(object to)
{
homebase = [to];
return true;
}
// Forward menu operations
public func Open(...)
{
if (menu) return menu->Open(...);
return false;
}
public func RemoveItem(idx)
{
if (menu) return menu->RemoveItem(idx);
return false;
}
/* Buy menu entries */
public func UpdateCaption(string title, bool available, int item_idx)
{
if (!menu) return false;
var custom_entry = { Bottom = "+1.3em" }, fontclr, bgclr, bgclr_hover;
if (available)
{
fontclr = 0xffffff;
bgclr = nil;
}
else
{
fontclr = 0x7f7f7f;
bgclr = 0x50000000;
}
custom_entry.BackgroundColor = bgclr;
custom_entry.Text = Format(" <c %x>%s</c>", fontclr, title);
custom_entry.Style = GUI_IgnoreMouse | GUI_TextBottom;
menu->AddItem(GetID(), nil, item_idx, this, this.ClickCaption, item_idx, custom_entry, nil, true);
return true;
}
public func ClickCaption() { return true; } // nothing to be done here (maybe expand/collapse in the future)
public func UpdateBuyEntry(id buy_def, bool available, int price, int callback_idx, bool was_last_selection, int extra_width, string hotkey)
{
if (!menu) return false;
var custom_entry = {Bottom = "+2em", Right = Format("+%dem", 2+extra_width), Symbol = buy_def }, fontclr, bgclr, bgclr_hover;
if (available)
{
fontclr = 0x00ff00;
bgclr = 0x507f7f7f;
bgclr_hover = 0x507fff7f;
}
else
{
fontclr = 0x7f7f7f;
bgclr = 0x50000000;
bgclr_hover = 0x50ff0000;
}
if (price)
{
custom_entry.price = {
Text = Format("{{Icon_Wealth}}<c %x>%d</c>", fontclr, price),
Style = GUI_TextRight | GUI_TextBottom
};
custom_entry.Style = GUI_FitChildren;
}
if (hotkey)
{
custom_entry.hotkey = {
Text = Format("<c %x>[%s]</c>", 0xffff00, hotkey),
Style = GUI_TextRight | GUI_TextTop
};
}
if (was_last_selection)
{
custom_entry.selection_marker = {
Top = "100% - 2em", Right = "+50%", Symbol = Icon_Ok
};
}
custom_entry.BackgroundColor = {Std = bgclr, OnHover = bgclr_hover };
menu->AddItem(buy_def, nil, callback_idx, this, this.ClickBuyButton, callback_idx, custom_entry, nil, true);
return true;
}
public func ClickBuyButton(int callback_idx, entry_id, int player)
{
if (homebase && homebase[0])
{
if (player != homebase[0]->GetOwner()) return false; // wat?
if (homebase[0]->OnBuySelection(callback_idx)) return true;
Sound("DullMetalHit3", true, nil, player);
}
return false;
}
/* Buy menu open/close button */
private func CreateToggleVisibilityButton()
{
var plr = GetOwner();
// Place the button just below the wealth display
// (in tenths of em)
var margin = 5;
var whole = margin + 25;
var hotkey_string = GetPlayerControlAssignment(GetOwner(), CON_ToggleShop, true);
if (hotkey_string && GetLength(hotkey_string) > 0)
hotkey_string = Format("|<c ffff00>[%s]</c>", hotkey_string);
else
hotkey_string = "";
var buymenu_button_menu =
{
Target = this,
Player = plr,
Style = GUI_Multiple | GUI_TextHCenter | GUI_TextBottom,
Left = Format("100%%%s", ToEmString(-whole)),
Right = Format("100%%%s", ToEmString(-margin)),
Top = ToEmString(margin+whole),
Bottom = ToEmString(2*whole),
Priority = 1, // Z order?
// Hover child element because a root window cannot collect clicks properly
hover = {
OnMouseIn = GuiAction_SetTag("OnHover"),
OnMouseOut = GuiAction_SetTag("Std"),
OnClick = GuiAction_Call(this, "ToggleVisibility"),
BackgroundColor = {Std = nil, OnHover = 0x50000000 },
//GraphicsName = GetGraphicsName(is_open),
Symbol = { Std=Library_Base, OnHover=Library_Base },
Text = { Std=Format("$Buy$%s", hotkey_string), OnHover=Format("<c ffff00>$Buy$</c>%s", hotkey_string) },
}
};
buymenu_toggle_id = GuiOpen(buymenu_button_menu);
return true;
}
private func DestroyToggleVisibilityButton()
{
GuiClose(buymenu_toggle_id);
return true;
}
public func ToggleVisibility(int player, ...)
{
if (!menu) return false;
if (menu.Visibility == VIS_Owner)
{
// Close menu
menu.Visibility = VIS_None;
Sound("CloseBuyMenu", true, nil, GetOwner());
}
else
{
// Open menu
menu.Visibility = VIS_Owner;
Sound("OpenBuyMenu", true, nil, GetOwner());
}
return true;
}

View File

@ -0,0 +1,4 @@
[DefCore]
id=Homebase
Version=7,0
Category=C4D_StaticBack

View File

@ -0,0 +1,260 @@
/**
Homebase
Manage buyable stuff and technology upgrades in Gidl
@authors Sven2
*/
local buy_menu;
local base_material; // array of base material entries
local last_buy_idx;
local techs;
local is_selling; // temp to prevent recursion from object removal
static g_quickbuy_items;
// Types for purchasable stuff
local ITEMTYPE_Weapon = {
free_rebuy = true,
stack_count = -1
};
local ITEMTYPE_Consumable = {
auto_rebuy = true
};
local ITEMTYPE_Technology = {
remove_after_buy = true,
callback = "GainTechnology",
extra_width = 2,
};
/* Creation / Destruction */
public func Construction(...)
{
base_material = [];
techs = {};
last_buy_idx = -1;
// Buy menu
buy_menu = CreateObject(GUI_BuyMenu, 0,0, GetOwner());
buy_menu->SetHomebase(this);
// Initial availability of items
AddCaption("$Weapons$");
AddHomebaseItem(new ITEMTYPE_Weapon { item = Bow, ammo = Arrow });
AddHomebaseItem(new ITEMTYPE_Weapon { item = Sword, cost = 25 });
AddHomebaseItem(new ITEMTYPE_Consumable { item = Firestone, cost = 5 });
AddHomebaseItem(new ITEMTYPE_Weapon { item = Musket, cost = 50, ammo = LeadShot, requirements = ["AdvancedWeapons"] });
AddHomebaseItem(new ITEMTYPE_Consumable { item = IronBomb, cost = 15, requirements = ["AdvancedWeapons"] });
AddHomebaseItem(new ITEMTYPE_Consumable { item = DynamiteBox,cost = 15, requirements = ["AdvancedWeapons"] });
AddHomebaseItem(new ITEMTYPE_Weapon { item = GrenadeLauncher, ammo = IronBomb, requirements = ["MasterWeapons"] });
AddCaption("$Items$");
AddHomebaseItem(new ITEMTYPE_Consumable { item = Bread, cost = 5 });
AddHomebaseItem(new ITEMTYPE_Weapon { item = Hammer, cost = 1000, extra_width = 1 });
AddCaption("$Technology$");
AddHomebaseItem(new ITEMTYPE_Technology { item = Icon_World,cost = 100, tech = "AdvancedWeapons" });
AddHomebaseItem(new ITEMTYPE_Technology { item = Icon_World,cost = 1000, tech = "MasterWeapons", requirements = ["AdvancedWeapons"] });
AddCaption("$Upgrades$");
AddCaption("$Artifacts$");
// Buy menu always open (but hidden at start)
buy_menu->Open();
return true;
}
public func AddCaption(string title, array requirements)
{
return AddHomebaseItem({is_caption = true, title=title, requirements=requirements});
}
public func AddHomebaseItem(proplist entry)
{
var idx = GetLength(base_material);
base_material[idx] = entry;
var quickbuy_idx = GetIndexOf(g_quickbuy_items, entry.item);
if (quickbuy_idx >= 0) entry.hotkey = GetPlayerControlAssignment(GetOwner(), CON_QuickBuy0+quickbuy_idx, true);
UpdateIndexedItem(idx);
return entry;
}
public func UpdateIndexedItem(int index)
{
if (index >= 0 && buy_menu)
{
var entry = base_material[index];
if (entry.hidden) return true;
var available = true;
if (entry.requirements)
for (var req in entry.requirements)
if (!techs[req])
available = false;
if (entry.is_caption)
return buy_menu->UpdateCaption(entry.title, available, index);
else
return buy_menu->UpdateBuyEntry(entry.item, available, entry.cost, index, index == last_buy_idx, entry.extra_width, entry.hotkey);
}
return false;
}
public func OnBuySelection(int callback_idx)
{
// Buy directly into cursor
var plr = GetOwner();
var cursor = GetCursor(plr);
if (!cursor) return false;
// Safety
var entry = base_material[callback_idx];
if (!entry) return false;
// Ignore if already have
var last_item = cursor->Contents(), item;
if (!last_item || (last_item->GetID() != entry.item))
{
// Requirements
if (entry.requirements)
for (var req in entry.requirements)
if (!techs[req])
return false;
// Cost
if (entry.cost)
{
if (GetWealth(plr) < entry.cost) return false;
DoWealth(plr, -entry.cost);
Sound("Cash", true, nil, plr);
// Some items cost only once
if (entry.free_rebuy) entry.cost = nil;
}
else
{
// Still some feedback even on free selections
Sound("Waterdrop1", true, nil, plr);
}
// Technology?
if (entry.callback)
{
// Teach technology
if (!Call(entry.callback, entry)) return false;
}
else
{
// Regular item: Buy into inventory
// Get rid of current item (unless it's the same we already want)
var item;
if (last_item) SellItem(last_item);
// Create item
if (!item) item = cursor->CreateContents(entry.item);
if (!item) return false;
// for later sale
item.GidlValue = entry.cost;
// ammo up!
if (entry.ammo)
{
var ammo = item->CreateContents(entry.ammo);
if (!ammo) return false;
var stack_count = entry.stack_count;
if (stack_count < 0)
ammo->~SetInfiniteStackCount();
else if (stack_count > 0)
ammo->SetStackCount(stack_count);
}
}
}
// Buy only once? (all technologies)
if (entry.remove_after_buy)
{
entry.hidden = true;
if (buy_menu) buy_menu->RemoveItem(callback_idx);
}
else
{
// Remember what has been bought
if (last_buy_idx != callback_idx)
{
var last_last_buy_idx = last_buy_idx;
last_buy_idx = callback_idx;
UpdateIndexedItem(last_last_buy_idx);
UpdateIndexedItem(last_buy_idx);
}
}
return true;
}
public func SellItem(item)
{
// Cash!
// Use custom value assigned by buy menu only
if (item.GidlValue)
{
DoWealth(GetOwner(), item.GidlValue);
Sound("Cash", true, nil, GetOwner());
}
is_selling = true; // no item re-buy during sale
var success = item->RemoveObject();
is_selling = false;
return success;
}
public func OnOwnerChanged(new_owner)
{
if (buy_menu) buy_menu->SetOwner(new_owner);
return true;
}
// Callback from clonk or weapon: Ammo has been used up.
// Recharge from selected home base item if that option has been enabled
public func OnNoAmmo(object clonk)
{
if (is_selling) return false;
if (last_buy_idx < 0) return false;
var entry = base_material[last_buy_idx];
if (entry && entry.auto_rebuy)
{
ScheduleCall(this, this.OnBuySelection, 1, 1, last_buy_idx);
}
return false;
}
public func QuickBuyItem(id item)
{
// Find item in buy list
var entry, i=0;
for (entry in base_material)
if (entry.item == item)
break;
else
++i;
// If found, try to buy it
if (!OnBuySelection(i))
{
// TODO: Error sound
return false;
}
return true;
}
private func GainTechnology(proplist entry)
{
techs[entry.tech] = true;
Call(Format("~Gain%s", entry.tech));
// Update any related techs that may become available
var n = GetLength(base_material), req;
for (var i=0; i<n; ++i)
if (req = base_material[i].requirements)
if (GetIndexOf(req, entry.tech) >= 0)
UpdateIndexedItem(i);
return true;
}
private func GainAdvancedWeapons(proplist entry)
{
// All done by requirements
}
public func Definition(def)
{
// Arrays in static const are broken
// So init them here
g_quickbuy_items = [Hammer, Bow, Sword, Musket, GrenadeLauncher, nil, Firestone, IronBomb, nil, nil];
}

View File

@ -0,0 +1,5 @@
Weapons=Waffen
Items=Gegenstaende
Technology=Technologie
Upgrades=Verbesserungen
Artifacts=Artefakte

View File

@ -0,0 +1,5 @@
Weapons=Weapons
Items=Items
Technology=Technology
Upgrades=Upgrades
Artifacts=Artifacts

View File

@ -4,7 +4,6 @@ static g_goal, g_object_fade, g_statue, g_doorleft, g_doorright;
func InitializeObjects()
{
CreateObject(Rule_BuyAtFlagpole, 0, 0);
CreateObject(Rule_TeamAccount, 0, 0);
g_goal = CreateObject(Goal_ProtectTheStatue, 0, 0);
@ -27,10 +26,10 @@ func InitializeObjects()
var Flagpole0012 = CreateObjectAbove(Flagpole, 676, 369);
Flagpole0012->SetCategory(C4D_StaticBack);
Flagpole0012->SetColor(0xff);
Flagpole0012->MakeInvincible();
var Flagpole0007 = CreateObjectAbove(Flagpole, 582, 369);
Flagpole0007->SetCategory(C4D_StaticBack);
Flagpole0007->SetColor(0xff);
Flagpole0007->MakeInvincible();
CreateObjectAbove(Rock, 312, 713);
CreateObjectAbove(Rock, 353, 679);

View File

@ -7,23 +7,19 @@ NoInitialize=true
[Game]
Goals=Goal_ProtectTheStatue=1
Rules=Rule_ObjectFace=1
Rules=Rule_ObjectFade=1
[Player1]
Wealth=50,0,0,250
BaseMaterial=Sword=999;Firestone=999;Bow=999;Musket=999;Bread=999;DynamiteBox=999;IronBomb=999;GrenadeLauncher=999;
[Player2]
Wealth=50,0,0,250
BaseMaterial=Sword=999;Firestone=999;Bow=999;Musket=999;Bread=999;DynamiteBox=999;IronBomb=999;GrenadeLauncher=999;
[Player3]
Wealth=50,0,0,250
BaseMaterial=Sword=999;Firestone=999;Bow=999;Musket=999;Bread=999;DynamiteBox=999;IronBomb=999;GrenadeLauncher=999;
[Player4]
Wealth=50,0,0,250
BaseMaterial=Sword=999;Firestone=999;Bow=999;Musket=999;Bread=999;DynamiteBox=999;IronBomb=999;GrenadeLauncher=999;
[Landscape]
Sky=Clouds1

View File

@ -11,6 +11,7 @@ static g_spawned_enemies;
static g_relaunchs; // array of relaunch counts
static g_scores; // array of player scores
static g_ai; // derived from AI; contains changes for this scenario
static g_homebases; // item management / buy menus for each player
static const ENEMY = 10; // player number of enemy
static const MAX_RELAUNCH = 10;
@ -20,6 +21,8 @@ static const MAX_RELAUNCH = 10;
func Initialize()
{
// Player homebase preparation
g_homebases = [];
// static variable init
InitWaveData();
}
@ -27,6 +30,7 @@ func Initialize()
func InitializePlayer(int plr, int iX, int iY, object pBase, int iTeam)
{
if (GetPlayerType(plr) != C4PT_User) return;
//DoWealth(plr, 10000);
if (!g_statue) { EliminatePlayer(plr); return; } // no post-elimination join
if (!g_relaunchs)
{
@ -42,7 +46,8 @@ func InitializePlayer(int plr, int iX, int iY, object pBase, int iTeam)
Scoreboard->NewPlayerEntry(plr);
Scoreboard->SetPlayerData(plr, "relaunchs", g_relaunchs[plr]);
Scoreboard->SetPlayerData(plr, "score", g_scores[plr]);
SetFoW(false,plr);
//SetFoW(false,plr); - need FoW for lights
g_homebases[plr] = CreateObject(Homebase, 0,0, plr);
JoinPlayer(plr);
if (!g_wave) StartGame();
return;
@ -50,32 +55,23 @@ func InitializePlayer(int plr, int iX, int iY, object pBase, int iTeam)
func RemovePlayer(int plr)
{
if (g_homebases[plr]) g_homebases[plr]->RemoveObject();
Scoreboard->SetPlayerData(plr, "relaunchs", Icon_Cancel);
return;
}
func RelaunchPlayer(int plr)
private func TransferInventory(object from, object to)
{
// Not for AI attackers
if (GetPlayerType(plr) != C4PT_User) return;
// Relaunch count
if (!g_relaunchs[plr])
{
Log("$MsgOutOfRelaunchs$", GetTaggedPlayerName(plr));
Scoreboard->SetPlayerData(plr, "relaunchs", Icon_Cancel);
EliminatePlayer(plr);
return false;
}
// Relaunch count
--g_relaunchs[plr];
Scoreboard->SetPlayerData(plr, "relaunchs", g_relaunchs[plr]);
Log("$MsgRelaunch$", GetTaggedPlayerName(plr));
JoinPlayer(plr);
//var gui_arrow = FindObject(Find_ID(GUI_GoalArrow), Find_Owner(plr));
//gui_arrow->SetAction("Show", GetCursor(plr));
// Drop some items that cannot be transferred (such as connected pipes and dynamite igniters)
var i = from->ContentsCount(), contents;
while (i--)
if (contents = from->Contents(i))
if (contents->~IsDroppedOnDeath(from))
contents->Exit();
return to->GrabContents(from);
}
func JoinPlayer(plr)
func JoinPlayer(plr, prev_clonk)
{
var relaunch_target = FindObject(Find_ID(Flagpole), Sort_Random()),x,y;
if (relaunch_target)
@ -95,12 +91,16 @@ func JoinPlayer(plr)
SetCursor(plr, clonk);
clonk->DoEnergy(1000);
// contents
//clonk.MaxContentsCount = CustomAI.Clonk_MaxContentsCount;
//clonk.MaxContentsCountVal = 2;
clonk->CreateContents(Bow);
var arrow = CreateObjectAbove(Arrow);
clonk->Collect(arrow);
arrow->SetInfiniteStackCount();
clonk.MaxContentsCount = CustomAI.Clonk_MaxContentsCount;
clonk.MaxContentsCountVal = 1;
if (prev_clonk) TransferInventory(prev_clonk, clonk);
if (!clonk->ContentsCount())
{
clonk->CreateContents(Bow);
var arrow = CreateObjectAbove(Arrow);
clonk->Collect(arrow);
arrow->SetInfiniteStackCount();
}
//clonk->CreateContents(Musket);
//clonk->Collect(CreateObjectAbove(LeadShot));
clonk->~CrewSelection(); // force update HUD
@ -226,21 +226,46 @@ func OnWaveCleared(int wave)
// Clonk death callback
func OnClonkDeath(clonk, killed_by)
{
// Remove inventory (players and enemies)
var i = clonk->ContentsCount(), obj;
while (i--) if (obj=clonk->Contents(i))
if (!obj->~OnContainerDeath())
obj->RemoveObject();
// Clear enemies from list
i = GetIndexOf(g_spawned_enemies, clonk);
if (i>=0)
// Player died?
if (!clonk) return;
var plr = clonk->GetOwner();
if (GetPlayerType(plr) == C4PT_User)
{
g_spawned_enemies[i] = nil;
// Kill bounty
if (killed_by>=0)
// Relaunch count
if (!g_relaunchs[plr])
{
Scoreboard->SetPlayerData(killed_by, "score", ++g_scores[killed_by]);
DoWealth(killed_by, clonk.Bounty);
Log("$MsgOutOfRelaunchs$", GetTaggedPlayerName(plr));
Scoreboard->SetPlayerData(plr, "relaunchs", Icon_Cancel);
EliminatePlayer(plr);
return false;
}
// Relaunch count
--g_relaunchs[plr];
Scoreboard->SetPlayerData(plr, "relaunchs", g_relaunchs[plr]);
Log("$MsgRelaunch$", GetTaggedPlayerName(plr));
JoinPlayer(plr, clonk);
//var gui_arrow = FindObject(Find_ID(GUI_GoalArrow), Find_Owner(plr));
//gui_arrow->SetAction("Show", GetCursor(plr));
}
else
{
// Enemy clonk death
// Remove inventory
var i = clonk->ContentsCount(), obj;
while (i--) if (obj=clonk->Contents(i))
if (!obj->~OnContainerDeath())
obj->RemoveObject();
// Clear enemies from list
i = GetIndexOf(g_spawned_enemies, clonk);
if (i>=0)
{
g_spawned_enemies[i] = nil;
// Kill bounty
if (killed_by>=0)
{
Scoreboard->SetPlayerData(killed_by, "score", ++g_scores[killed_by]);
DoWealth(killed_by, clonk.Bounty);
}
}
}
return;

View File

@ -1,21 +0,0 @@
#appendto Library_Base
func DoBuy(id idDef, int iForPlr, int iPayPlr, object pClonk, bool bRight, bool fShowErrors)
{
var obj = _inherited(idDef, iForPlr, iPayPlr, pClonk, bRight, fShowErrors, ...);
if (!obj || !pClonk) return obj;
var idobj = obj->GetID(), idammo;
if (idobj == Bow) idammo = Arrow;
else if (idobj == Musket) idammo = LeadShot;
else if (idobj == GrenadeLauncher) idammo = IronBomb;
if (idammo)
{
var ammo = CreateObjectAbove(idammo,0,0,iForPlr);
if (ammo)
{
ammo->~SetInfiniteStackCount();
ammo->Enter(obj);
}
}
return obj;
}

View File

@ -0,0 +1,21 @@
/* Recharge callback in clonk if ammo has been used up */
#appendto Clonk
static g_homebases; // item management / buy menus for each player
func Ejection()
{
if (!Contents() && g_homebases && g_homebases[GetOwner()])
if (GetAlive() && GetPlayerType(GetOwner()) == C4PT_User)
g_homebases[GetOwner()]->OnNoAmmo(this);
return _inherited(...);
}
func ContentsDestruction()
{
if (ContentsCount() <= 1 && g_homebases && g_homebases[GetOwner()])
if (GetAlive() && GetPlayerType(GetOwner()) == C4PT_User)
g_homebases[GetOwner()]->OnNoAmmo(this);
return _inherited(...);
}

View File

@ -0,0 +1,34 @@
/* Recharge callback in clonk if ammo has been used up */
#appendto GrenadeLauncher
static g_homebases; // item management / buy menus for each player
func Ejection()
{
var cont = Contained();
if (cont)
{
if (!Contents() && cont->GetAlive()) RechargeIronBomb();
}
return _inherited(...);
}
func ContentsDestruction()
{
var cont = Contained();
if (cont)
{
if (ContentsCount()<=1 && cont->GetAlive()) RechargeIronBomb();
}
return _inherited(...);
}
// Recreate ammo - but max one per frame (also to ensure we don't run into endless loops when destructing)
func RechargeIronBomb()
{
var t = FrameCounter();
if (this.last_iron_bomb_recharge == t) return nil;
this.last_iron_bomb_recharge = t;
return CreateContents(IronBomb);
}

View File

@ -0,0 +1,24 @@
/*--
QuickBuy
--*/
static g_quickbuy_items;
global func PlayerControl(int plr, int ctrl)
{
if (ctrl >= CON_QuickBuy0 && ctrl <= CON_QuickBuy9)
{
if (!g_homebases || plr < 0) return false;
var base = g_homebases[plr];
if (!base) return false;
base->QuickBuyItem(g_quickbuy_items[ctrl - CON_QuickBuy0]);
return true;
}
if (ctrl == CON_ToggleShop)
{
var buy_menu = FindObject(Find_ID(GUI_BuyMenu), Find_Owner(plr));
if (!buy_menu) return false;
return buy_menu->ToggleVisibility(plr);
}
return _inherited(plr, ctrl, ...);
}

View File

@ -0,0 +1,95 @@
[ControlDefs]
[ControlDef]
Identifier=ToggleShop
[ControlDef]
Identifier=QuickBuy0
[ControlDef]
Identifier=QuickBuy1
[ControlDef]
Identifier=QuickBuy2
[ControlDef]
Identifier=QuickBuy3
[ControlDef]
Identifier=QuickBuy4
[ControlDef]
Identifier=QuickBuy5
[ControlDef]
Identifier=QuickBuy6
[ControlDef]
Identifier=QuickBuy7
[ControlDef]
Identifier=QuickBuy8
[ControlDef]
Identifier=QuickBuy9
[ControlSets]
[ControlSet]
Name=*
[Assignment]
Key=P
Priority=-1
Control=ToggleShop
[Assignment]
Key=0
Priority=999
Control=QuickBuy0
[Assignment]
Key=1
Priority=999
Control=QuickBuy1
[Assignment]
Key=2
Priority=999
Control=QuickBuy2
[Assignment]
Key=3
Priority=999
Control=QuickBuy3
[Assignment]
Key=4
Priority=999
Control=QuickBuy4
[Assignment]
Key=5
Priority=999
Control=QuickBuy5
[Assignment]
Key=6
Priority=999
Control=QuickBuy6
[Assignment]
Key=7
Priority=999
Control=QuickBuy7
[Assignment]
Key=8
Priority=999
Control=QuickBuy8
[Assignment]
Key=9
Priority=999
Control=QuickBuy9