openclonk/planet/Arena.ocf/MeltingCastle.ocs/Script.c

187 lines
5.6 KiB
C

/* Melting Castle */
static g_respawn_flags, g_had_intro_msg;
static const EDIT_MAP = false; // Set to true to edit map and Objects.c; avoids map resize and object duplication
func Initialize()
{
if (EDIT_MAP) return true;
GetRelaunchRule()->SetDefaultRelaunchCount(nil);
GetRelaunchRule()->SetRespawnDelay(8);
GetRelaunchRule()->SetLastWeaponUse(false);
GetRelaunchRule()->SetAllowPlayerRestart(true);
// Mirror map objects by moving them to the other side, then re-running object initialization
for (var o in FindObjects(Find_NoContainer(), Find_Not(Find_Category(C4D_Goal | C4D_Rule))))
{
var oid = o->GetID();
if (oid == Ambience) continue; // Can't filter by C4D_Environment, because we do want waterfalls and item spawns
o->SetPosition(LandscapeWidth() - o->GetX(), o->GetY());
// Catapults and cannons should point left on the right island
if (oid == Catapult)
o->TurnLeft();
else if (oid == Cannon)
o->TurnCannon(DIR_Left, true);
}
ScenarioObjects->InitializeObjects();
// Some adjustments to the bridges
for (var bridge in FindObjects(Find_ID(WoodenBridge)))
{
bridge->SetClrModulation(0xff00ffff);
bridge->SetHalfVehicleSolidMask(true);
bridge->SetCategory(C4D_Vehicle);
bridge->SetVertex(,,-37); // prevent self-stuck
}
// Item spawns by team
for (var item_spawn in FindObjects(Find_ID(ItemSpawn)))
{
item_spawn->SetTeam(1 + (item_spawn->GetX() > LandscapeWidth()/2));
}
// Remember flags for respawn
g_respawn_flags = CreateArray(3);
for (var flag in FindObjects(Find_ID(Goal_Flag)))
{
flag->DisablePickup(); // Not using CTF goal
flag.Destruction = Scenario.OnFlagDestruction;
flag.team = 1;
flag.Plane = 274; // cannot be moved by airship
flag.RejectWindbagForce = Clonk.IsClonk;
if (flag->GetX() > LandscapeWidth()/2) ++flag.team;
g_respawn_flags[flag.team] = flag;
}
// Weapon drops timer
g_num_avail_weapons = 6;
ScheduleCall(nil, Scenario.DoBalloonDrop, 36*8, 99999);
return true;
}
local weapon_list = [ // id, vertex, offx, offy, deployy
[Firestone, 0, -3, -6, -18],
[IronBomb, 0, 0, -6, -10],
[IceWallKit, 2, 0, -5, -10],
[DynamiteBox, 0, 3, -5, -10],
[BombArrow, 2, 0, -8, -10],
[GrenadeLauncher, 3, 0, -4, -10],
[Boompack, 0, 0, 0, 0]
];
static g_num_avail_weapons; // boompack available later
func DoBalloonDrop()
{
// Random weapon
if (FrameCounter() > 36*60*4) g_num_avail_weapons = 7; // enable boompacks after some time
var wp = Scenario.weapon_list[Random(g_num_avail_weapons)];
var x = LandscapeWidth()/4 + Random(LandscapeWidth()/2);
var y = 0;
var balloon = CreateObject(BalloonDeployed, x, y);
if (!balloon) return;
balloon->SetInflated();
var cargo = CreateObject(wp[0]);
if (!cargo) return;
balloon->SetCargo(cargo, wp[1], wp[2], wp[3], wp[4]);
if (wp[0] == GrenadeLauncher) cargo->CreateContents(IronBomb);
return balloon;
}
func OnFlagDestruction()
{
// Callback from flag after it dropped
Log("$FlagDownMsg$", ["$TeamLeft$", "$TeamRight$"][this.team-1]);
return true;
}
func InitializePlayer(int plr)
{
// Everything freely visible (to allow aiming with the cannon)
SetFoW(false, plr);
SetPlayerZoomByViewRange(plr,LandscapeWidth(),LandscapeHeight(),PLRZOOM_LimitMax);
SetPlayerViewLock(plr, false);
// Acquire base
var team = GetPlayerTeam(plr);
var flag = g_respawn_flags[team];
if (flag && flag->GetOwner() == NO_OWNER) AcquireBase(plr, team);
// Intro message. Delayed to be visible to all players.
if (!g_had_intro_msg)
{
g_had_intro_msg = true;
ScheduleCall(nil, Scenario.IntroMsg, 10, 1);
}
// Initial launch
return true;
}
func IntroMsg()
{
var speaker = FindObject(Find_ID(Goal_Flag));
if (speaker)
{
var c = speaker->GetColor();
var n = speaker->GetName();
speaker->SetColor(0xffffff);
speaker->SetName("$IntroName$");
Dialogue->MessageBoxAll("$IntroMsg$", speaker, true);
speaker->SetName(n);
speaker->SetColor(c);
}
return true;
}
func LaunchPlayer(object clonk, int plr)
{
// Make sure clonk can move
DigFreeRect(clonk->GetX()-6,clonk->GetY()-10,13,18,true);
// Crew setup
clonk.MaxEnergy = 100000;
clonk->DoEnergy(1000);
clonk->CreateContents(WindBag);
return true;
}
public func OnPlayerRelaunch(int plr)
{
if (!g_respawn_flags[GetPlayerTeam(plr)])
return EliminatePlayer(plr);
}
public func RelaunchPosition(int iPlr, int iTeam)
{
if(!g_respawn_flags[iTeam]) return;
return [g_respawn_flags[iTeam]->GetX(), g_respawn_flags[iTeam]->GetY()];
}
public func OnClonkLeftRelaunch(object clonk, int plr)
{
// Find flag for respawn
var flagpole = g_respawn_flags[GetPlayerTeam(plr)];
if (!flagpole) return EliminatePlayer(plr); // Flag lost and clonk died? Game over!
// Reset available items in spawns
for (var item_spawn in FindObjects(Find_ID(ItemSpawn))) item_spawn->Reset(plr);
// Relaunch near current flag pos (will be adjusted on actual relaunch)
return LaunchPlayer(clonk, plr);
}
func RelaunchWeaponList() { return [Bow, Sword, Club, Javelin, Blunderbuss, Firestone, IceWallKit]; }
func AcquireBase(int plr, int team)
{
// Change ownership of some stuff in the base to the first player of a team joining
// Note that this may be called late into the game in case all players of one team join late into the game
var base_x0 = 0;
if (team == 2) base_x0 = LandscapeWidth()/2;
var base_ids = [Catapult, Cannon, Goal_Flag, Chest];
for (var obj in FindObjects(Find_InRect(base_x0, 100, LandscapeWidth()/2, LandscapeHeight()-100), Find_NoContainer(), Find_Owner(NO_OWNER)))
{
var idobj = obj->GetID();
if (GetIndexOf(base_ids, idobj))
{
obj->SetOwner(plr);
if (idobj == Goal_Flag) obj->SetClrModulation(0xff000000 | GetPlayerColor(plr));
}
}
return true;
}