2010-10-17 14:07:34 +00:00
|
|
|
/*--
|
|
|
|
Hideout
|
|
|
|
Author: Maikel
|
|
|
|
|
2010-10-18 19:20:26 +00:00
|
|
|
A capture the flag scenario for two teams, both teams occupy a hideout and must steal the flag from
|
|
|
|
the opposing team. The hideout is protected by doors and various weapons are there to fight with.
|
2010-10-17 14:07:34 +00:00
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
|
|
protected func Initialize()
|
|
|
|
{
|
|
|
|
// Environment
|
2010-11-02 20:49:04 +00:00
|
|
|
PlaceGrass(185);
|
2010-10-17 14:07:34 +00:00
|
|
|
|
2010-10-18 19:20:26 +00:00
|
|
|
// Goal: Capture the flag, with bases in both hideouts.
|
2015-01-10 16:56:54 +00:00
|
|
|
var goal = CreateObject(Goal_CaptureTheFlag, 0, 0, NO_OWNER);
|
2015-11-29 18:40:30 +00:00
|
|
|
goal->SetFlagBase(1, 120, 502);
|
|
|
|
goal->SetFlagBase(2, LandscapeWidth() - 120, 502);
|
2010-10-18 19:20:26 +00:00
|
|
|
|
|
|
|
// Rules
|
2015-01-10 16:56:54 +00:00
|
|
|
CreateObject(Rule_Restart);
|
|
|
|
CreateObject(Rule_ObjectFade)->DoFadeTime(5 * 36);
|
|
|
|
CreateObject(Rule_KillLogs);
|
|
|
|
CreateObject(Rule_Gravestones);
|
2010-10-17 14:07:34 +00:00
|
|
|
|
2012-10-21 21:14:37 +00:00
|
|
|
var lwidth = LandscapeWidth();
|
|
|
|
|
2010-10-17 14:07:34 +00:00
|
|
|
// Doors and spinwheels.
|
|
|
|
var gate, wheel;
|
2015-01-10 09:14:02 +00:00
|
|
|
gate = CreateObjectAbove(StoneDoor, 364, 448, NO_OWNER);
|
2012-11-01 20:49:53 +00:00
|
|
|
DrawMaterialQuad("Tunnel-brickback", 360, 446, 360, 448, 368, 448, 368, 446);
|
2011-09-03 11:55:47 +00:00
|
|
|
gate->DoDamage(50); // Upper doors are easier to destroy
|
2011-10-03 12:04:38 +00:00
|
|
|
gate->SetAutoControl(1);
|
2015-01-10 09:14:02 +00:00
|
|
|
gate = CreateObjectAbove(StoneDoor, 340, 584, NO_OWNER);
|
2012-11-01 20:49:53 +00:00
|
|
|
DrawMaterialQuad("Tunnel-brickback", 336, 582, 336, 584, 344, 584, 344, 582);
|
2011-10-03 12:04:38 +00:00
|
|
|
gate->SetAutoControl(1);
|
2015-01-10 09:14:02 +00:00
|
|
|
gate = CreateObjectAbove(StoneDoor, 692, 544, NO_OWNER);
|
2012-11-01 20:49:53 +00:00
|
|
|
DrawMaterialQuad("Tunnel-brickback", 688, 542, 688, 544, 696, 544, 696, 542);
|
2011-09-03 11:55:47 +00:00
|
|
|
gate->DoDamage(80); // Middle doors even easier
|
2015-01-10 09:14:02 +00:00
|
|
|
wheel = CreateObjectAbove(SpinWheel, 660, 552, NO_OWNER);
|
2010-10-20 18:47:32 +00:00
|
|
|
wheel->SetStoneDoor(gate);
|
2011-09-03 11:55:47 +00:00
|
|
|
|
2015-01-10 09:14:02 +00:00
|
|
|
gate = CreateObjectAbove(StoneDoor, lwidth - 364, 448, NO_OWNER);
|
2012-10-21 21:14:37 +00:00
|
|
|
DrawMaterialQuad("Tunnel-brickback", lwidth - 361, 446, lwidth - 361, 448, lwidth - 365, 448, lwidth - 365, 446);
|
2011-09-03 11:55:47 +00:00
|
|
|
gate->DoDamage(50); // Upper doors are easier to destroy
|
2011-10-03 12:04:38 +00:00
|
|
|
gate->SetAutoControl(2);
|
2015-01-10 09:14:02 +00:00
|
|
|
gate = CreateObjectAbove(StoneDoor, lwidth - 340, 584, NO_OWNER);
|
2012-10-21 21:14:37 +00:00
|
|
|
DrawMaterialQuad("Tunnel-brickback", lwidth - 337, 582, lwidth - 337, 584, lwidth - 345, 584, lwidth - 345, 582);
|
2011-10-03 12:04:38 +00:00
|
|
|
gate->SetAutoControl(2);
|
2015-01-10 09:14:02 +00:00
|
|
|
gate = CreateObjectAbove(StoneDoor, lwidth - 692, 544, NO_OWNER);
|
2012-10-21 21:14:37 +00:00
|
|
|
DrawMaterialQuad("Tunnel-brickback", lwidth - 689, 542, lwidth - 689, 544, lwidth - 697, 544, lwidth - 697, 542);
|
2011-09-03 11:55:47 +00:00
|
|
|
gate->DoDamage(80); // Middle doors even easier
|
2015-01-10 09:14:02 +00:00
|
|
|
wheel = CreateObjectAbove(SpinWheel, lwidth - 660, 552, NO_OWNER);
|
2010-10-20 18:47:32 +00:00
|
|
|
wheel->SetStoneDoor(gate);
|
2010-10-17 14:07:34 +00:00
|
|
|
|
|
|
|
// Chests with weapons.
|
|
|
|
var chest;
|
2015-01-10 09:14:02 +00:00
|
|
|
chest = CreateObjectAbove(Chest, 110, 592, NO_OWNER);
|
2012-10-14 13:04:23 +00:00
|
|
|
chest->MakeInvincible();
|
2010-12-04 19:30:12 +00:00
|
|
|
AddEffect("FillBaseChest", chest, 100, 6 * 36,nil,nil,true);
|
2015-01-10 09:14:02 +00:00
|
|
|
chest = CreateObjectAbove(Chest, 25, 464, NO_OWNER);
|
2012-10-14 13:04:23 +00:00
|
|
|
chest->MakeInvincible();
|
2010-12-04 19:30:12 +00:00
|
|
|
AddEffect("FillBaseChest", chest, 100, 6 * 36,nil,nil,false);
|
2015-01-10 09:14:02 +00:00
|
|
|
chest = CreateObjectAbove(Chest, 730, 408, NO_OWNER);
|
2012-10-14 13:04:23 +00:00
|
|
|
chest->MakeInvincible();
|
2010-12-04 19:30:12 +00:00
|
|
|
AddEffect("FillOtherChest", chest, 100, 6 * 36);
|
2015-01-10 09:14:02 +00:00
|
|
|
chest = CreateObjectAbove(Chest, lwidth - 110, 592, NO_OWNER);
|
2012-10-14 13:04:23 +00:00
|
|
|
chest->MakeInvincible();
|
2010-12-04 19:30:12 +00:00
|
|
|
AddEffect("FillBaseChest", chest, 100, 6 * 36,nil,nil,true);
|
2015-01-10 09:14:02 +00:00
|
|
|
chest = CreateObjectAbove(Chest, lwidth - 25, 464, NO_OWNER);
|
2012-10-14 13:04:23 +00:00
|
|
|
chest->MakeInvincible();
|
2010-12-04 19:30:12 +00:00
|
|
|
AddEffect("FillBaseChest", chest, 100, 6 * 36,nil,nil,false);
|
2015-01-10 09:14:02 +00:00
|
|
|
chest = CreateObjectAbove(Chest, lwidth - 730, 408, NO_OWNER);
|
2012-10-14 13:04:23 +00:00
|
|
|
chest->MakeInvincible();
|
2010-12-04 19:30:12 +00:00
|
|
|
AddEffect("FillOtherChest", chest, 100, 6 * 36);
|
2015-01-10 09:14:02 +00:00
|
|
|
chest = CreateObjectAbove(Chest, lwidth/2, 512, NO_OWNER);
|
2012-10-14 13:04:23 +00:00
|
|
|
chest->MakeInvincible();
|
2010-12-02 20:55:04 +00:00
|
|
|
AddEffect("FillSpecialChest", chest, 100, 4 * 36);
|
2010-11-02 20:49:04 +00:00
|
|
|
|
2010-12-04 22:12:50 +00:00
|
|
|
/*
|
|
|
|
// No Cannons
|
2010-10-17 14:07:34 +00:00
|
|
|
// Cannons loaded with 12 shots.
|
|
|
|
var cannon;
|
2015-01-10 09:14:02 +00:00
|
|
|
cannon = CreateObjectAbove(Cannon, 429, 444, NO_OWNER);
|
2010-10-17 14:07:34 +00:00
|
|
|
cannon->SetDir(DIR_Right);
|
|
|
|
cannon->SetR(15);
|
|
|
|
cannon->CreateContents(PowderKeg);
|
2015-01-10 09:14:02 +00:00
|
|
|
cannon = CreateObjectAbove(Cannon, lwidth - 429, 444, NO_OWNER);
|
2010-10-17 14:07:34 +00:00
|
|
|
cannon->SetDir(DIR_Left);
|
|
|
|
cannon->SetR(-15);
|
|
|
|
cannon->CreateContents(PowderKeg);
|
2010-12-04 22:12:50 +00:00
|
|
|
*/
|
2010-11-28 18:25:50 +00:00
|
|
|
|
2010-10-17 14:07:34 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected func InitializePlayer(int plr)
|
|
|
|
{
|
|
|
|
SetPlayerZoomByViewRange(plr, 600, nil, PLRZOOM_Direct);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gamecall from CTF goal, on respawning.
|
|
|
|
protected func OnPlayerRelaunch(int plr)
|
|
|
|
{
|
|
|
|
var clonk = GetCrew(plr);
|
2015-01-10 09:14:02 +00:00
|
|
|
var relaunch = CreateObjectAbove(RelaunchContainer, clonk->GetX(), clonk->GetY(), clonk->GetOwner());
|
2010-10-17 14:07:34 +00:00
|
|
|
relaunch->StartRelaunch(clonk);
|
|
|
|
relaunch->SetRelaunchTime(8, true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-02 21:43:56 +00:00
|
|
|
// Game call from RelaunchContainer when a Clonk has left the respawn.
|
|
|
|
public func OnClonkLeftRelaunch(object clonk)
|
|
|
|
{
|
|
|
|
// Randomize the Clonk's position a bit.
|
|
|
|
var x = clonk->GetX();
|
|
|
|
var y = clonk->GetY();
|
|
|
|
clonk->SetPosition(x + RandomX(-20, 20), y + RandomX(-20, 10));
|
|
|
|
if (clonk->Stuck()) clonk->SetPosition(x, y);
|
|
|
|
|
|
|
|
// Some small spark-like particles that just fly around.
|
|
|
|
var sparks =
|
|
|
|
{
|
|
|
|
Prototype = Particles_Glimmer(),
|
|
|
|
Size = PV_Random(0, 1),
|
|
|
|
R = 200, G = 0, B = 200,
|
|
|
|
ForceX = PV_Random(-5, 5, 10),
|
|
|
|
ForceY = PV_Random(-5, 5, 10),
|
|
|
|
Attach = ATTACH_Front
|
|
|
|
};
|
|
|
|
|
|
|
|
if (GetPlayerTeam(clonk->GetOwner()) == 1)
|
|
|
|
{
|
|
|
|
sparks.R = 255;
|
|
|
|
sparks.B = 0;
|
|
|
|
}
|
|
|
|
clonk->CreateParticle("Flash", 0, 0, PV_Random(-20, 20), PV_Random(-20, 20), PV_Random(10, 400), sparks, 100);
|
|
|
|
|
|
|
|
// And a larger flash as if the Clonk had just been teleported there.
|
|
|
|
var flash =
|
|
|
|
{
|
|
|
|
Prototype = Particles_Flash(),
|
|
|
|
Size = 10,
|
|
|
|
Stretch = PV_Linear(40000, 0),
|
|
|
|
R = sparks.R, G = sparks.G, B = sparks.B
|
|
|
|
};
|
|
|
|
clonk->CreateParticle("StarSpark", 0, 0, 0, 0, 10, flash, 1);
|
|
|
|
}
|
|
|
|
|
2010-10-26 16:42:51 +00:00
|
|
|
func RelaunchWeaponList() { return [Bow, Shield, Sword, Javelin, Shovel, Firestone, Dynamite, Loam]; }
|
2010-10-17 14:07:34 +00:00
|
|
|
|
|
|
|
/*-- Chest filler effects --*/
|
|
|
|
|
2010-12-23 13:35:16 +00:00
|
|
|
global func FxFillBaseChestStart(object target, effect, int temporary, bool supply)
|
2010-10-17 14:07:34 +00:00
|
|
|
{
|
2010-10-29 11:43:58 +00:00
|
|
|
if (temporary)
|
2010-10-17 14:07:34 +00:00
|
|
|
return 1;
|
2010-11-02 20:49:04 +00:00
|
|
|
|
2011-07-31 15:59:51 +00:00
|
|
|
effect.supply_type=supply;
|
|
|
|
if(effect.supply_type)
|
2010-12-02 20:55:04 +00:00
|
|
|
var w_list = [Firestone, Dynamite, Ropeladder, ShieldGem];
|
2010-11-02 20:49:04 +00:00
|
|
|
else
|
2010-12-02 20:55:04 +00:00
|
|
|
var w_list = [Bow, Sword, Javelin, PyreGem];
|
2010-11-02 20:49:04 +00:00
|
|
|
for(var i=0; i<4; i++)
|
|
|
|
target->CreateChestContents(w_list[i]);
|
2010-10-17 14:07:34 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2010-12-23 13:35:16 +00:00
|
|
|
global func FxFillBaseChestTimer(object target, effect)
|
2010-10-17 14:07:34 +00:00
|
|
|
{
|
2011-07-31 15:59:51 +00:00
|
|
|
if(effect.supply_type)
|
2010-11-28 15:28:10 +00:00
|
|
|
{
|
2010-12-02 20:55:04 +00:00
|
|
|
var w_list = [Firestone, Dynamite, Shovel, Loam, Ropeladder, SlowGem, ShieldGem];
|
|
|
|
var maxcount = [2,2,1,2,1,2,1];
|
2010-11-28 15:28:10 +00:00
|
|
|
}
|
2010-11-02 20:49:04 +00:00
|
|
|
else
|
2010-11-28 15:28:10 +00:00
|
|
|
{
|
2016-08-22 14:31:05 +00:00
|
|
|
var w_list = [Sword, Javelin, Blunderbuss, ShieldGem, PyreGem];
|
2010-12-04 19:30:12 +00:00
|
|
|
var maxcount = [1,2,1,1,1];
|
2010-11-28 15:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var contents;
|
|
|
|
for(var i=0; i<target->GetLength(w_list); i++)
|
|
|
|
contents+=target->ContentsCount(w_list[i]);
|
|
|
|
if(contents > 5) return 1;
|
|
|
|
|
|
|
|
for(var i=0; i<2 ; i++)
|
|
|
|
{
|
|
|
|
var r = Random(GetLength(w_list));
|
|
|
|
if (target->ContentsCount(w_list[r]) < maxcount[r])
|
|
|
|
{
|
|
|
|
target->CreateChestContents(w_list[r]);
|
|
|
|
i=3;
|
|
|
|
}
|
|
|
|
}
|
2010-10-17 14:07:34 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-12-23 13:35:16 +00:00
|
|
|
global func FxFillOtherChestStart(object target, effect, int temporary)
|
2010-10-17 14:07:34 +00:00
|
|
|
{
|
2010-10-29 11:43:58 +00:00
|
|
|
if (temporary)
|
2010-10-17 14:07:34 +00:00
|
|
|
return 1;
|
2010-12-03 17:48:02 +00:00
|
|
|
var w_list = [Shield, Sword, Javelin, Club, Firestone, Dynamite];
|
2010-10-17 14:07:34 +00:00
|
|
|
if (target->ContentsCount() < 5)
|
|
|
|
target->CreateChestContents(w_list[Random(GetLength(w_list))]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
global func FxFillOtherChestTimer(object target)
|
|
|
|
{
|
2010-12-03 17:48:02 +00:00
|
|
|
var w_list = [Shield ,Sword, Club, Bow, Dynamite, Firestone, SlowGem, ShieldGem, PyreGem];
|
|
|
|
var maxcount = [2,1,1,1,2,2,1,2,2];
|
2010-11-28 15:28:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
var contents;
|
|
|
|
for(var i=0; i<target->GetLength(w_list); i++)
|
|
|
|
contents+=target->ContentsCount(w_list[i]);
|
|
|
|
if(contents > 6) return 1;
|
|
|
|
|
|
|
|
for(var i=0; i<2 ; i++)
|
|
|
|
{
|
|
|
|
var r = Random(GetLength(w_list));
|
|
|
|
if (target->ContentsCount(w_list[r]) < maxcount[r])
|
|
|
|
{
|
|
|
|
target->CreateChestContents(w_list[r]);
|
|
|
|
i=3;
|
|
|
|
}
|
|
|
|
}
|
2010-10-17 14:07:34 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-11-02 20:49:04 +00:00
|
|
|
global func FxFillSpecialChestTimer(object target)
|
|
|
|
{
|
2010-12-03 11:02:34 +00:00
|
|
|
if (Random(2)) return 1;
|
2010-12-02 20:55:04 +00:00
|
|
|
|
|
|
|
var w_list = [PyreGem, ShieldGem, SlowGem];
|
|
|
|
var r=Random(3);
|
|
|
|
if (target->ContentsCount() < 4)
|
|
|
|
target->CreateChestContents(w_list[r]);
|
|
|
|
|
2010-11-04 13:57:43 +00:00
|
|
|
var w_list = [GrappleBow, DynamiteBox, Boompack];
|
|
|
|
var r=Random(3);
|
|
|
|
for(var i=0; i < GetLength(w_list); i++)
|
|
|
|
if (FindObject(Find_ID(w_list[i]))) return 1;
|
2010-11-02 20:49:04 +00:00
|
|
|
target->CreateChestContents(w_list[r]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-10-17 14:07:34 +00:00
|
|
|
global func CreateChestContents(id obj_id)
|
|
|
|
{
|
|
|
|
if (!this)
|
|
|
|
return;
|
2015-01-10 09:14:02 +00:00
|
|
|
var obj = CreateObjectAbove(obj_id);
|
2010-12-02 20:55:04 +00:00
|
|
|
|
2010-10-17 14:07:34 +00:00
|
|
|
if (obj_id == Bow)
|
|
|
|
obj->CreateContents(Arrow);
|
2016-08-22 14:31:05 +00:00
|
|
|
if (obj_id == Blunderbuss)
|
2016-08-16 21:37:17 +00:00
|
|
|
obj->CreateContents(LeadBullet);
|
2010-11-03 17:33:44 +00:00
|
|
|
if (obj_id == GrappleBow)
|
2010-11-02 20:49:04 +00:00
|
|
|
AddEffect("NotTooLong",obj,100,36);
|
2010-12-02 20:55:04 +00:00
|
|
|
|
2010-10-17 14:07:34 +00:00
|
|
|
obj->Enter(this);
|
2010-11-02 20:49:04 +00:00
|
|
|
|
2010-10-17 14:07:34 +00:00
|
|
|
return;
|
2010-11-02 20:49:04 +00:00
|
|
|
}
|
|
|
|
|
2011-09-18 17:42:19 +00:00
|
|
|
protected func CaptureFlagCount() { return 2;} //4 + GetPlayerCount()) / 2; }
|
2010-11-02 20:49:04 +00:00
|
|
|
|
2010-12-23 13:35:16 +00:00
|
|
|
global func FxNotTooLongTimer(object target, effect)
|
2010-11-03 17:33:44 +00:00
|
|
|
{ if (!(target->Contained())) return 1;
|
2011-07-31 15:59:51 +00:00
|
|
|
if (target->Contained()->GetID() == Clonk) effect.inClonk_time++;
|
|
|
|
if (effect.inClonk_time > 40) return target->RemoveObject();
|
|
|
|
else if (effect.inClonk_time > 35) target->Message("@<c ff%x%x>%d",(41-effect.inClonk_time)*50,(41-effect.inClonk_time)*50,41-effect.inClonk_time);
|
2010-12-03 19:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func OnClonkDeath(object clonk, int killed_by)
|
|
|
|
{
|
|
|
|
// create a magic healing gem on Clonk death
|
2010-12-06 16:55:51 +00:00
|
|
|
if(Hostile(clonk->GetOwner(), killed_by))
|
|
|
|
{
|
2015-01-10 09:14:02 +00:00
|
|
|
var gem=clonk->CreateObjectAbove(LifeGem, 0, 0, killed_by);
|
2010-12-06 16:55:51 +00:00
|
|
|
if(GetPlayerTeam(killed_by) == 1)
|
|
|
|
gem->SetGraphics("E");
|
|
|
|
}
|
2010-12-03 19:23:11 +00:00
|
|
|
return _inherited(clonk, killed_by);
|
2015-01-10 09:14:02 +00:00
|
|
|
}
|