forked from Mirrors/openclonk
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 firestonesshapetextures
parent
6e4c7a2c2d
commit
08b3584c5d
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
[DefCore]
|
||||
id=GUI_BuyMenu
|
||||
Version=7,0
|
||||
Category=C4D_StaticBack
|
Binary file not shown.
|
@ -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;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Buy=Shop
|
|
@ -0,0 +1 @@
|
|||
Buy=Shop
|
|
@ -0,0 +1,4 @@
|
|||
[DefCore]
|
||||
id=Homebase
|
||||
Version=7,0
|
||||
Category=C4D_StaticBack
|
|
@ -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];
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
Weapons=Waffen
|
||||
Items=Gegenstaende
|
||||
Technology=Technologie
|
||||
Upgrades=Verbesserungen
|
||||
Artifacts=Artefakte
|
|
@ -0,0 +1,5 @@
|
|||
Weapons=Weapons
|
||||
Items=Items
|
||||
Technology=Technology
|
||||
Upgrades=Upgrades
|
||||
Artifacts=Artifacts
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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(...);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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, ...);
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue